You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by av...@apache.org on 2021/10/21 11:05:46 UTC
[fineract] branch develop updated: Fineract-1410 Allow Payment
types to map to all types of Ledgers (#1917)
This is an automated email from the ASF dual-hosted git repository.
avikg 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 c6b7546 Fineract-1410 Allow Payment types to map to all types of Ledgers (#1917)
c6b7546 is described below
commit c6b754621839db74a3f427a5d95e1e478bb73493
Author: ankita10r <92...@users.noreply.github.com>
AuthorDate: Thu Oct 21 16:35:37 2021 +0530
Fineract-1410 Allow Payment types to map to all types of Ledgers (#1917)
---
.../service/ProductToGLAccountMappingHelper.java | 8 ++++--
.../api/GlobalConfigurationApiConstant.java | 1 +
.../data/GlobalConfigurationDataValidator.java | 12 ++++++---
.../data/GlobalConfigurationPropertyData.java | 13 +++++++---
.../domain/ConfigurationDomainService.java | 4 +++
.../domain/ConfigurationDomainServiceJpa.java | 30 ++++++++++++++++++++++
.../domain/GlobalConfigurationProperty.java | 24 ++++++++++++++---
.../ConfigurationReadPlatformServiceImpl.java | 11 ++++----
.../portfolio/savings/SavingsApiConstants.java | 2 ++
.../savings/api/SavingsApiSetConstants.java | 5 ++--
.../savings/api/SavingsProductsApiResource.java | 17 ++++++++----
.../api/SavingsProductsApiResourceSwagger.java | 4 +++
.../portfolio/savings/data/SavingsProductData.java | 25 +++++++++++-------
..._adding_expenseliablity_to_paymentorfeetype.sql | 25 ++++++++++++++++++
.../common/GlobalConfigurationHelper.java | 24 ++++++++++++++---
15 files changed, 168 insertions(+), 37 deletions(-)
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
index 2db50c5..2e44ad9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingHelper.java
@@ -362,8 +362,7 @@ public class ProductToGLAccountMappingHelper {
private void savePaymentChannelToFundSourceMapping(final Long productId, final Long paymentTypeId,
final Long paymentTypeSpecificFundAccountId, final PortfolioProductType portfolioProductType) {
final PaymentType paymentType = this.paymentTypeRepositoryWrapper.findOneWithNotFoundDetection(paymentTypeId);
- final GLAccount glAccount = getAccountByIdAndType(LoanProductAccountingParams.FUND_SOURCE.getValue(), GLAccountType.ASSET,
- paymentTypeSpecificFundAccountId);
+ final GLAccount glAccount = getAccountById(LoanProductAccountingParams.FUND_SOURCE.getValue(), paymentTypeSpecificFundAccountId);
final ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
portfolioProductType.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(), paymentType);
this.accountMappingRepository.save(accountMapping);
@@ -427,6 +426,11 @@ public class ProductToGLAccountMappingHelper {
return glAccount;
}
+ public GLAccount getAccountById(final String paramName, final Long accountId) {
+ final GLAccount glAccount = this.accountRepositoryWrapper.findOneWithNotFoundDetection(accountId);
+ return glAccount;
+ }
+
public GLAccount getAccountByIdAndType(final String paramName, final List<GLAccountType> expectedAccountTypes, final Long accountId) {
final GLAccount glAccount = this.accountRepositoryWrapper.findOneWithNotFoundDetection(accountId);
// validate account is of the expected Type
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationApiConstant.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationApiConstant.java
index 3174b45..b8e86d5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationApiConstant.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationApiConstant.java
@@ -31,5 +31,6 @@ public final class GlobalConfigurationApiConstant {
public static final String CONFIGURATION_RESOURCE_NAME = "globalConfiguration";
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
+ public static final String STRING_VALUE = "stringValue";
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationDataValidator.java
index 40676ed..668d619 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationDataValidator.java
@@ -43,9 +43,10 @@ import org.springframework.stereotype.Component;
public class GlobalConfigurationDataValidator {
private final FromJsonHelper fromApiJsonHelper;
- private static final Set<String> UPDATE_CONFIGURATION_DATA_PARAMETERS = new HashSet<>(Arrays.asList(
- GlobalConfigurationApiConstant.localeParamName, GlobalConfigurationApiConstant.dateFormatParamName,
- GlobalConfigurationApiConstant.ENABLED, GlobalConfigurationApiConstant.VALUE, GlobalConfigurationApiConstant.DATE_VALUE));
+ private static final Set<String> UPDATE_CONFIGURATION_DATA_PARAMETERS = new HashSet<>(
+ Arrays.asList(GlobalConfigurationApiConstant.localeParamName, GlobalConfigurationApiConstant.dateFormatParamName,
+ GlobalConfigurationApiConstant.ENABLED, GlobalConfigurationApiConstant.VALUE, GlobalConfigurationApiConstant.DATE_VALUE,
+ GlobalConfigurationApiConstant.STRING_VALUE));
@Autowired
public GlobalConfigurationDataValidator(final FromJsonHelper fromApiJsonHelper) {
@@ -81,6 +82,11 @@ public class GlobalConfigurationDataValidator {
baseDataValidator.reset().parameter(GlobalConfigurationApiConstant.DATE_VALUE).value(dateValue).notNull();
}
+ if (this.fromApiJsonHelper.parameterExists(GlobalConfigurationApiConstant.STRING_VALUE, element)) {
+ final String stringValue = this.fromApiJsonHelper.extractStringNamed(GlobalConfigurationApiConstant.STRING_VALUE, element);
+ baseDataValidator.reset().parameter(GlobalConfigurationApiConstant.STRING_VALUE).value(stringValue).notNull();
+ }
+
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java
index a893b93..7e54b01 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/data/GlobalConfigurationPropertyData.java
@@ -33,6 +33,7 @@ public class GlobalConfigurationPropertyData {
private final Long value;
@SuppressWarnings("unused")
private final Date dateValue;
+ private String stringValue;
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
@@ -41,22 +42,24 @@ public class GlobalConfigurationPropertyData {
private final boolean trapDoor;
public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value, final Date dateValue,
- final String description, final boolean trapDoor) {
+ final String stringValue, final String description, final boolean trapDoor) {
this.name = name;
this.enabled = enabled;
this.value = value;
this.dateValue = dateValue;
+ this.stringValue = stringValue;
this.id = null;
this.description = description;
this.trapDoor = trapDoor;
}
- public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value, Date dateValue, final Long id,
- final String description, final boolean isTrapDoor) {
+ public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value, Date dateValue,
+ final String stringValue, final Long id, final String description, final boolean isTrapDoor) {
this.name = name;
this.enabled = enabled;
this.value = value;
this.dateValue = dateValue;
+ this.stringValue = stringValue;
this.id = id;
this.description = description;
this.trapDoor = isTrapDoor;
@@ -74,6 +77,10 @@ public class GlobalConfigurationPropertyData {
return this.value;
}
+ public String getStringValue() {
+ return this.stringValue;
+ }
+
public Date getDateValue() {
return this.dateValue;
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
index 4b791c9..b35611c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
@@ -98,4 +98,8 @@ public interface ConfigurationDomainService {
boolean isFirstRepaymentDateAfterRescheduleAllowedOnHoliday();
boolean isInterestToBeAppropriatedEquallyWhenGreaterThanEMI();
+
+ String getAccountMappingForPaymentType();
+
+ String getAccountMappingForCharge();
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
index 321d640..b03c2a9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
@@ -363,4 +363,34 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
}
}
+ @Override
+ public String getAccountMappingForPaymentType() {
+ final String propertyName = "account-mapping-for-payment-type";
+ String defaultValue = "Asset"; // 1 Stands for Account mapped from asset only
+ final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(propertyName);
+ if (property.isEnabled()) {
+ String value = property.getStringValue();
+ if (value == null) {
+ return defaultValue;
+ }
+ return value;
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public String getAccountMappingForCharge() {
+ final String propertyName = "account-mapping-for-charge";
+ String defaultValue = "Income"; // 1 Stands for Account mapped from income only
+ final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(propertyName);
+ if (property.isEnabled()) {
+ String value = property.getValue().toString();
+ if (value == null) {
+ return defaultValue;
+ }
+ return value;
+ }
+ return defaultValue;
+ }
+
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
index e6a3a2e..84e0283 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/GlobalConfigurationProperty.java
@@ -46,6 +46,9 @@ public class GlobalConfigurationProperty extends AbstractPersistableCustom {
@Column(name = "date_value", nullable = true)
private Date dateValue;
+ @Column(name = "string_value", nullable = true)
+ private String stringValue;
+
@Column(name = "description", nullable = true)
private String description;
@@ -57,16 +60,18 @@ public class GlobalConfigurationProperty extends AbstractPersistableCustom {
this.enabled = false;
this.value = null;
this.dateValue = null;
+ this.stringValue = null;
this.description = null;
this.isTrapDoor = false;
}
public GlobalConfigurationProperty(final String name, final boolean enabled, final Long value, final Date dateValue,
- final String description, final boolean isTrapDoor) {
+ final String stringValue, final String description, final boolean isTrapDoor) {
this.name = name;
this.enabled = enabled;
this.value = value;
this.dateValue = dateValue;
+ this.stringValue = stringValue;
this.description = description;
this.isTrapDoor = isTrapDoor;
}
@@ -83,6 +88,10 @@ public class GlobalConfigurationProperty extends AbstractPersistableCustom {
return this.dateValue;
}
+ public String getStringValue() {
+ return this.stringValue;
+ }
+
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
@@ -113,6 +122,13 @@ public class GlobalConfigurationProperty extends AbstractPersistableCustom {
this.dateValue = newDateValue;
}
+ final String stringValueParamName = "stringValue";
+ if (command.isChangeInStringParameterNamed(stringValueParamName, this.stringValue)) {
+ final String newStringValue = command.stringValueOfParameterNamed(stringValueParamName);
+ actualChanges.put(stringValueParamName, newStringValue);
+ this.stringValue = newStringValue;
+ }
+
final String passwordPropertyName = "force-password-reset-days";
if (this.name.equalsIgnoreCase(passwordPropertyName)) {
if ((this.enabled == true && command.hasParameter(valueParamName) && (this.value == 0))
@@ -126,12 +142,12 @@ public class GlobalConfigurationProperty extends AbstractPersistableCustom {
}
public static GlobalConfigurationProperty newSurveyConfiguration(final String name) {
- return new GlobalConfigurationProperty(name, false, null, null, null, false);
+ return new GlobalConfigurationProperty(name, false, null, null, null, null, false);
}
public GlobalConfigurationPropertyData toData() {
- return new GlobalConfigurationPropertyData(getName(), isEnabled(), getValue(), getDateValue(), this.getId(), this.description,
- this.isTrapDoor);
+ return new GlobalConfigurationPropertyData(getName(), isEnabled(), getValue(), getDateValue(), getStringValue(), this.getId(),
+ this.description, this.isTrapDoor);
}
public String getName() {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java
index 65eaec1..dd7326a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/service/ConfigurationReadPlatformServiceImpl.java
@@ -52,7 +52,7 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
this.context.authenticatedUser();
- String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.description, c.is_trap_door FROM c_configuration c ";
+ String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.description,c.string_value, c.is_trap_door FROM c_configuration c ";
if (survey) {
sql += " JOIN x_registered_table on x_registered_table.registered_table_name = c.name ";
@@ -68,11 +68,11 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
}
@Override
- public GlobalConfigurationPropertyData retrieveGlobalConfiguration(String name) {
+ public GlobalConfigurationPropertyData retrieveGlobalConfiguration(final String name) {
this.context.authenticatedUser();
- final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.description, c.is_trap_door FROM "
+ final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.string_value, c.description, c.is_trap_door FROM "
+ "c_configuration c where c.name=? order by c.id";
final GlobalConfigurationPropertyData globalConfiguration = this.jdbcTemplate.queryForObject(sql, this.rm, new Object[] { name });
@@ -84,7 +84,7 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
this.context.authenticatedUser();
- final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.description, c.is_trap_door FROM "
+ final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.date_value, c.string_value ,c.description, c.is_trap_door FROM "
+ "c_configuration c where c.id=? order by c.id";
final GlobalConfigurationPropertyData globalConfiguration = this.jdbcTemplate.queryForObject(sql, this.rm,
new Object[] { configId });
@@ -102,10 +102,11 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
final boolean enabled = rs.getBoolean("enabled");
final Long value = rs.getLong("value");
final Date dateValue = rs.getDate("date_value");
+ final String stringValue = rs.getString("string_value");
final String description = rs.getString("description");
final Long id = rs.getLong("id");
final boolean isTrapDoor = rs.getBoolean("is_trap_door");
- return new GlobalConfigurationPropertyData(name, enabled, value, dateValue, id, description, isTrapDoor);
+ return new GlobalConfigurationPropertyData(name, enabled, value, dateValue, stringValue, id, description, isTrapDoor);
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
index 8f2e884..1113571 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
@@ -191,4 +191,6 @@ public class SavingsApiConstants {
public static final String gsimApplicationId = "applicationId";
public static final String gsimLastApplication = "lastApplication";
public static final String ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE = "not.in.active.state";
+
+ public static final String accountMappingForPaymentParamName = "accountMappingForPayment";
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
index 3ec70e7..d278167 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
@@ -41,13 +41,12 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
"withdrawalFeeTypeOptions", nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
withHoldTaxParamName, taxGroupIdParamName, isDormancyTrackingActiveParamName, daysToInactiveParamName,
- daysToDormancyParamName, daysToInactiveParamName));
+ daysToDormancyParamName, daysToInactiveParamName, accountMappingForPaymentParamName));
/**
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
* get response parameters to match those of request parameters.
*/
-
protected static final Set<String> SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList(idParamName,
accountNoParamName, externalIdParamName, statusParamName, activatedOnDateParamName, staffIdParamName, clientIdParamName,
"clientName", groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency",
@@ -58,7 +57,7 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee",
"annualFee", onHoldFundsParamName, nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
- datatables, savingsAmountOnHold));
+ datatables, savingsAmountOnHold, accountMappingForPaymentParamName));
protected static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName, paymentDetailDataParamName,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
index ab8d4c2..d01f4dc 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResource.java
@@ -52,6 +52,7 @@ import org.apache.fineract.accounting.producttoaccountmapping.service.ProductToG
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.commands.service.CommandWrapperBuilder;
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
+import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
@@ -100,6 +101,7 @@ public class SavingsProductsApiResource {
private final ChargeReadPlatformService chargeReadPlatformService;
private final PaymentTypeReadPlatformService paymentTypeReadPlatformService;
private final TaxReadPlatformService taxReadPlatformService;
+ private final ConfigurationDomainService configurationDomainService;
@Autowired
public SavingsProductsApiResource(final SavingsProductReadPlatformService savingProductReadPlatformService,
@@ -111,7 +113,7 @@ public class SavingsProductsApiResource {
final AccountingDropdownReadPlatformService accountingDropdownReadPlatformService,
final ProductToGLAccountMappingReadPlatformService accountMappingReadPlatformService,
final ChargeReadPlatformService chargeReadPlatformService, PaymentTypeReadPlatformService paymentTypeReadPlatformService,
- final TaxReadPlatformService taxReadPlatformService) {
+ final TaxReadPlatformService taxReadPlatformService, final ConfigurationDomainService configurationDomainService) {
this.savingProductReadPlatformService = savingProductReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService;
this.currencyReadPlatformService = currencyReadPlatformService;
@@ -124,6 +126,7 @@ public class SavingsProductsApiResource {
this.chargeReadPlatformService = chargeReadPlatformService;
this.paymentTypeReadPlatformService = paymentTypeReadPlatformService;
this.taxReadPlatformService = taxReadPlatformService;
+ this.configurationDomainService = configurationDomainService;
}
@POST
@@ -132,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")
+ + "Optional Fields: minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, charges, allowOverdraft, overdraftLimit, minBalanceForInterestCalculation,withHoldTax,taxGroupId,accountMapping")
@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))) })
@@ -229,7 +232,8 @@ public class SavingsProductsApiResource {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve Savings Product Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
- + "\n" + "Field Defaults\n" + "Allowed description Lists\n" + "Example Request:\n" + "\n" + "savingsproducts/template")
+ + "\n" + "Field Defaults\n" + "Allowed description Lists\n" + "Example Request:\n" + "Account Mapping:\n" + "\n"
+ + "savingsproducts/template")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = SavingsProductsApiResourceSwagger.GetSavingsProductsTemplateResponse.class))) })
public String retrieveTemplate(@Context final UriInfo uriInfo) {
@@ -288,6 +292,8 @@ public class SavingsProductsApiResource {
final Map<String, List<GLAccountData>> accountingMappingOptions = this.accountingDropdownReadPlatformService
.retrieveAccountMappingOptionsForSavingsProducts();
+ final String accountMappingForPayment = configurationDomainService.getAccountMappingForPaymentType();
+
// charges
final boolean feeChargesOnly = false;
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveSavingsProductApplicableCharges(feeChargesOnly);
@@ -301,13 +307,14 @@ public class SavingsProductsApiResource {
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
- accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions);
+ accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions, accountMappingForPayment);
} else {
savingsProductToReturn = SavingsProductData.template(currency, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, accountingRule, currencyOptions,
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
- paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions);
+ paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions,
+ accountMappingForPayment);
}
return savingsProductToReturn;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResourceSwagger.java
index 20fdd3e..5aaeabb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResourceSwagger.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsProductsApiResourceSwagger.java
@@ -70,6 +70,8 @@ final class SavingsProductsApiResourceSwagger {
@Schema(example = "1")
public Integer accountingRule;
public Set<PostSavingsCharges> charges;
+ @Schema(example = "accountMappingForPayment")
+ public String accountMappingForPayment;
}
@Schema(description = "PostSavingsProductsResponse")
@@ -725,6 +727,8 @@ final class SavingsProductsApiResourceSwagger {
public Set<GetSavingsProductsTemplateAccountingRule> accountingRuleOptions;
public GetSavingsProductsAccountingMappingOptions accountingMappingOptions;
public Set<GetSavingsProductsChargeOptions> chargeOptions;
+ public GetSavingsProductsResponse.GetSavingsCurrency accountMapping;
+
}
@Schema(description = "DeleteSavingsProductsProductIdResponse")
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductData.java
index 856adf4..95505c8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductData.java
@@ -62,6 +62,7 @@ public final class SavingsProductData implements Serializable {
private final boolean withHoldTax;
private final TaxGroupData taxGroup;
private String depositAccountType = null;
+ private final String accountMappingForPayment;
// accounting
private final EnumOptionData accountingRule;
@@ -102,7 +103,8 @@ public final class SavingsProductData implements Serializable {
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
final Collection<PaymentTypeData> paymentTypeOptions, final Collection<EnumOptionData> accountingRuleOptions,
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<ChargeData> chargeOptions,
- final Collection<ChargeData> penaltyOptions, final Collection<TaxGroupData> taxGroupOptions) {
+ final Collection<ChargeData> penaltyOptions, final Collection<TaxGroupData> taxGroupOptions,
+ final String accountMappingForPayment) {
final Long id = null;
final String name = null;
@@ -141,7 +143,7 @@ public final class SavingsProductData implements Serializable {
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
- daysToDormancy, daysToEscheat);
+ daysToDormancy, daysToEscheat, accountMappingForPayment);
}
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
@@ -158,7 +160,7 @@ public final class SavingsProductData implements Serializable {
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.daysToEscheat, product.accountMappingForPayment);
}
/**
@@ -167,6 +169,7 @@ public final class SavingsProductData implements Serializable {
*
* @param taxGroupOptions
* TODO
+ * @param accountMapping
*/
public static SavingsProductData withTemplate(final SavingsProductData existingProduct, final Collection<CurrencyData> currencyOptions,
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
@@ -176,7 +179,7 @@ public final class SavingsProductData implements Serializable {
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
final Collection<PaymentTypeData> paymentTypeOptions, final Collection<EnumOptionData> accountingRuleOptions,
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<ChargeData> chargeOptions,
- final Collection<ChargeData> penaltyOptions, Collection<TaxGroupData> taxGroupOptions) {
+ final Collection<ChargeData> penaltyOptions, Collection<TaxGroupData> taxGroupOptions, final String accountMappingForPayment) {
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
@@ -192,7 +195,7 @@ public final class SavingsProductData implements Serializable {
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup, taxGroupOptions,
existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive, existingProduct.daysToDormancy,
- existingProduct.daysToEscheat);
+ existingProduct.daysToEscheat, existingProduct.accountMappingForPayment);
}
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
@@ -212,6 +215,7 @@ public final class SavingsProductData implements Serializable {
final Map<String, List<GLAccountData>> accountingMappingOptions = null;
final Collection<ChargeData> chargeOptions = null;
final Collection<ChargeData> penaltyOptions = null;
+ final String accountMappingForPayment = null;
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
@@ -227,7 +231,7 @@ public final class SavingsProductData implements Serializable {
existingProduct.minBalanceForInterestCalculation, existingProduct.nominalAnnualInterestRateOverdraft,
existingProduct.minOverdraftForInterestCalculation, existingProduct.withHoldTax, existingProduct.taxGroup,
existingProduct.taxGroupOptions, existingProduct.isDormancyTrackingActive, existingProduct.daysToInactive,
- existingProduct.daysToDormancy, existingProduct.daysToEscheat);
+ existingProduct.daysToDormancy, existingProduct.daysToEscheat, existingProduct.accountMappingForPayment);
}
public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description,
@@ -260,6 +264,7 @@ public final class SavingsProductData implements Serializable {
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
final Collection<TaxGroupData> taxGroupOptions = null;
+ final String accountMappingForPayment = null;
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
@@ -270,7 +275,7 @@ public final class SavingsProductData implements Serializable {
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
- daysToDormancy, daysToEscheat);
+ daysToDormancy, daysToEscheat, accountMappingForPayment);
}
public static SavingsProductData lookup(final Long id, final String name) {
@@ -320,6 +325,7 @@ public final class SavingsProductData implements Serializable {
final Long daysToInactive = null;
final Long daysToDormancy = null;
final Long daysToEscheat = null;
+ final String accountMappingForPayment = null;
return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
@@ -330,7 +336,7 @@ public final class SavingsProductData implements Serializable {
penaltyOptions, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit,
minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, taxGroup, taxGroupOptions, isDormancyTrackingActive, daysToInactive,
- daysToDormancy, daysToEscheat);
+ daysToDormancy, daysToEscheat, accountMappingForPayment);
}
private SavingsProductData(final Long id, final String name, final String shortName, final String description,
@@ -354,7 +360,7 @@ public final class SavingsProductData implements Serializable {
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 Long daysToDormancy, final Long daysToEscheat, final String accountMappingForPayment) {
this.id = id;
this.name = name;
this.shortName = shortName;
@@ -411,6 +417,7 @@ public final class SavingsProductData implements Serializable {
this.daysToInactive = daysToInactive;
this.daysToDormancy = daysToDormancy;
this.daysToEscheat = daysToEscheat;
+ this.accountMappingForPayment = accountMappingForPayment;
}
public boolean hasAccountingEnabled() {
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V374__adding_expenseliablity_to_paymentorfeetype.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V374__adding_expenseliablity_to_paymentorfeetype.sql
new file mode 100644
index 0000000..fa090be
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V374__adding_expenseliablity_to_paymentorfeetype.sql
@@ -0,0 +1,25 @@
+--
+-- 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 `c_configuration`
+ ADD COLUMN `string_value` VARCHAR(100) NULL DEFAULT NULL AFTER `date_value`;
+
+insert into c_configuration(name, string_value, enabled, description) values('account-mapping-for-payment-type', 'Asset', '1', 'Asset: default for asset, Use comma seperated values for Liability, Asset and Expense accounts');
+
+insert into c_configuration(name, string_value, enabled, description) values('account-mapping-for-charge', 'Income', '1', 'Income: default for Income, Use comma seperated values for Income, Liability and Expense accounts');
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/GlobalConfigurationHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/GlobalConfigurationHelper.java
index 39657e2..6721857 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/GlobalConfigurationHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/GlobalConfigurationHelper.java
@@ -88,9 +88,9 @@ public class GlobalConfigurationHelper {
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
- // There are currently 30 global configurations.
- Assertions.assertEquals(30, expectedGlobalConfigurations.size());
- Assertions.assertEquals(30, actualGlobalConfigurations.size());
+ // There are currently 32 global configurations.
+ Assertions.assertEquals(32, expectedGlobalConfigurations.size());
+ Assertions.assertEquals(32, actualGlobalConfigurations.size());
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
@@ -362,6 +362,24 @@ public class GlobalConfigurationHelper {
isInterestAppropriationEnabled.put("trapDoor", false);
defaults.add(isInterestAppropriationEnabled);
+ HashMap<String, Object> isAccountMappedForPayment = new HashMap<>();
+ isAccountMappedForPayment.put("id", 35);
+ isAccountMappedForPayment.put("name", "account-mapping-for-payment-type");
+ isAccountMappedForPayment.put("value", 0);
+ isAccountMappedForPayment.put("enabled", false);
+ isAccountMappedForPayment.put("trapDoor", false);
+ isAccountMappedForPayment.put("string_value", "Asset");
+ defaults.add(isAccountMappedForPayment);
+
+ HashMap<String, Object> isAccountMappedForCharge = new HashMap<>();
+ isAccountMappedForCharge.put("id", 36);
+ isAccountMappedForCharge.put("name", "account-mapping-for-charge");
+ isAccountMappedForCharge.put("value", 0);
+ isAccountMappedForCharge.put("enabled", false);
+ isAccountMappedForCharge.put("trapDoor", false);
+ isAccountMappedForCharge.put("string_value", "Income");
+ defaults.add(isAccountMappedForCharge);
+
return defaults;
}