diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/LoanProductToGLAccountMappingHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/LoanProductToGLAccountMappingHelper.java index 82e5c3ef2..e7514deb7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/LoanProductToGLAccountMappingHelper.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/LoanProductToGLAccountMappingHelper.java @@ -20,16 +20,19 @@ package org.apache.fineract.accounting.producttoaccountmapping.service; import com.google.gson.JsonElement; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForLoan; import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForLoan; import org.apache.fineract.accounting.common.AccountingConstants.LoanProductAccountingParams; import org.apache.fineract.accounting.common.AccountingRuleType; +import org.apache.fineract.accounting.glaccount.domain.GLAccount; import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository; import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper; import org.apache.fineract.accounting.glaccount.domain.GLAccountType; import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioProductType; import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository; +import org.apache.fineract.accounting.producttoaccountmapping.exception.ProductToGLAccountMappingInvalidException; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper; @@ -56,6 +59,14 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.ASSET, PortfolioProductType.LOAN); } + public void saveLoanToAssetOrLiabilityAccountMapping(final JsonElement element, final String paramName, final Long productId, + final int placeHolderTypeId) { + GLAccountType glAccountType = getGLAccountType(element, paramName, ASSET_LIABILITY_TYPES); + if (glAccountType != null) { + saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, glAccountType, PortfolioProductType.LOAN); + } + } + public void saveLoanToIncomeAccountMapping(final JsonElement element, final String paramName, final Long productId, final int placeHolderTypeId) { saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.INCOME, PortfolioProductType.LOAN); @@ -80,6 +91,15 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi PortfolioProductType.LOAN); } + public void mergeLoanToAssetOrLiabilityAccountMappingChanges(final JsonElement element, final String paramName, final Long productId, + final int accountTypeId, final String accountTypeName, final Map changes) { + GLAccountType glAccountType = getGLAccountType(element, paramName, ASSET_LIABILITY_TYPES); + if (glAccountType != null) { + mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, glAccountType, + PortfolioProductType.LOAN); + } + } + public void mergeLoanToIncomeAccountMappingChanges(final JsonElement element, final String paramName, final Long productId, final int accountTypeId, final String accountTypeName, final Map changes) { mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.INCOME, @@ -223,9 +243,11 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi case NONE: break; case CASH_BASED: - // asset - mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, + // asset or liabilities + mergeLoanToAssetOrLiabilityAccountMappingChanges(element, LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, CashAccountsForLoan.FUND_SOURCE.getValue(), CashAccountsForLoan.FUND_SOURCE.toString(), changes); + + // asset mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), loanProductId, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(), CashAccountsForLoan.LOAN_PORTFOLIO.toString(), changes); mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), loanProductId, @@ -255,9 +277,11 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi case ACCRUAL_UPFRONT: // fall through to periodic accrual case ACCRUAL_PERIODIC: + // asset or liabilities + mergeLoanToAssetOrLiabilityAccountMappingChanges(element, LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, + CashAccountsForLoan.FUND_SOURCE.getValue(), CashAccountsForLoan.FUND_SOURCE.toString(), changes); + // assets (including receivables) - mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, - AccrualAccountsForLoan.FUND_SOURCE.getValue(), AccrualAccountsForLoan.FUND_SOURCE.toString(), changes); mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), loanProductId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(), AccrualAccountsForLoan.LOAN_PORTFOLIO.toString(), changes); mergeLoanToAssetAccountMappingChanges(element, LoanProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), loanProductId, @@ -302,4 +326,18 @@ public class LoanProductToGLAccountMappingHelper extends ProductToGLAccountMappi deleteProductToGLAccountMapping(loanProductId, PortfolioProductType.LOAN); } + private GLAccountType getGLAccountType(final JsonElement element, final String paramName, final List allowedTypes) { + GLAccountType gLAccountType = null; + final Long accountId = this.fromApiJsonHelper.extractLongNamed(paramName, element); + if (accountId != null) { + final GLAccount glAccount = getAccountById(paramName, accountId); + gLAccountType = GLAccountType.fromInt(glAccount.getType()); + if (!allowedTypes.contains(gLAccountType)) { + throw new ProductToGLAccountMappingInvalidException(paramName, glAccount.getName(), accountId, gLAccountType.toString(), + GLAccountType.ASSET.getCode() + " or " + GLAccountType.LIABILITY.getCode()); + } + } + return gLAccountType; + } + } 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 7887156a4..c127be060 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 @@ -51,6 +51,8 @@ import org.springframework.stereotype.Component; @RequiredArgsConstructor public class ProductToGLAccountMappingHelper { + protected static final List ASSET_LIABILITY_TYPES = List.of(GLAccountType.ASSET, GLAccountType.LIABILITY); + protected final GLAccountRepository accountRepository; protected final ProductToGLAccountMappingRepository accountMappingRepository; protected final FromJsonHelper fromApiJsonHelper; diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java index b48dafb27..41d94d28b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java @@ -62,9 +62,10 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc case NONE: break; case CASH_BASED: - // asset - this.loanProductToGLAccountMappingHelper.saveLoanToAssetAccountMapping(element, + // asset or liability + this.loanProductToGLAccountMappingHelper.saveLoanToAssetOrLiabilityAccountMapping(element, LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, CashAccountsForLoan.FUND_SOURCE.getValue()); + // asset this.loanProductToGLAccountMappingHelper.saveLoanToAssetAccountMapping(element, LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), loanProductId, CashAccountsForLoan.LOAN_PORTFOLIO.getValue()); @@ -105,9 +106,11 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc case ACCRUAL_UPFRONT: // Fall Through case ACCRUAL_PERIODIC: + // asset or liability + this.loanProductToGLAccountMappingHelper.saveLoanToAssetOrLiabilityAccountMapping(element, + LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, CashAccountsForLoan.FUND_SOURCE.getValue()); + // assets (including receivables) - this.loanProductToGLAccountMappingHelper.saveLoanToAssetAccountMapping(element, - LoanProductAccountingParams.FUND_SOURCE.getValue(), loanProductId, AccrualAccountsForLoan.FUND_SOURCE.getValue()); this.loanProductToGLAccountMappingHelper.saveLoanToAssetAccountMapping(element, LoanProductAccountingParams.LOAN_PORTFOLIO.getValue(), loanProductId, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue());