update loan products api-docs and validation. some refactor at point where loan product and GLAccount mappings meet.
This commit is contained in:
+17
-11
@@ -1956,9 +1956,6 @@ Request Body:
|
||||
"numberOfRepayments": 12,
|
||||
"loanTermFrequency": 12,
|
||||
"repaymentEvery": 1,
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"annualInterestRate": 21,
|
||||
"accountingType": 1,
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
@@ -1969,11 +1966,15 @@ Request Body:
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 0,
|
||||
"code": "amortizationType.equal.principal",
|
||||
@@ -1988,7 +1989,8 @@ Request Body:
|
||||
"id": 1,
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
}
|
||||
},
|
||||
"accountingType": 1
|
||||
}
|
||||
]
|
||||
</code>
|
||||
@@ -2019,7 +2021,6 @@ Request Body:
|
||||
"nameCode": "currency.USD",
|
||||
"displayLabel": "US Dollar ($)"
|
||||
},
|
||||
"accountingType": 1,
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
@@ -2050,6 +2051,7 @@ Request Body:
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"accountingType": 1,
|
||||
"currencyOptions": [
|
||||
{
|
||||
"code": "USD",
|
||||
@@ -2168,7 +2170,8 @@ Request Body:
|
||||
"code": "loanTermFrequency.periodFrequencyType.years",
|
||||
"value": "Years"
|
||||
}
|
||||
]
|
||||
],
|
||||
"accountingMappings": {}
|
||||
}
|
||||
</code>
|
||||
</div>
|
||||
@@ -2202,9 +2205,6 @@ Request Body:
|
||||
"numberOfRepayments": 12,
|
||||
"loanTermFrequency": 12,
|
||||
"repaymentEvery": 1,
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"annualInterestRate": 21,
|
||||
"accountingType": 1,
|
||||
"loanTermFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "loanTermFrequency.periodFrequencyType.months",
|
||||
@@ -2215,11 +2215,15 @@ Request Body:
|
||||
"code": "repaymentFrequency.periodFrequencyType.months",
|
||||
"value": "Months"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"interestRatePerPeriod": 1.75,
|
||||
"interestRateFrequencyType": {
|
||||
"id": 2,
|
||||
"code": "interestRateFrequency.periodFrequencyType.months",
|
||||
"value": "Per month"
|
||||
},
|
||||
"annualInterestRate": 21,
|
||||
"amortizationType": {
|
||||
"id": 0,
|
||||
"code": "amortizationType.equal.principal",
|
||||
@@ -2235,6 +2239,7 @@ Request Body:
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"accountingType": 1,
|
||||
"charges": []
|
||||
}
|
||||
</code>
|
||||
@@ -2263,9 +2268,10 @@ Request Body:
|
||||
"locale": "en_GB",
|
||||
"digitsAfterDecimal": "2",
|
||||
"principal": "100,000.00",
|
||||
"repaymentFrequencyType": 2,
|
||||
"repaymentEvery": "1",
|
||||
"numberOfRepayments": "12",
|
||||
"repaymentEvery": "1",
|
||||
"repaymentFrequencyType": 2,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"interestRatePerPeriod": "1.75",
|
||||
"interestRateFrequencyType": 2,
|
||||
"amortizationType": 1,
|
||||
|
||||
@@ -293,6 +293,10 @@ INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `c
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'READ_GUARANTOR', 'GUARANTOR', 'READ', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_GUARANTOR', 'GUARANTOR', 'UPDATE', 1);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'DELETE_OFFICETRANSACTION', 'OFFICETRANSACTION', 'DELETE', 1);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'DELETE_OFFICETRANSACTION_CHECKER', 'OFFICETRANSACTION', 'DELETE', 0);
|
||||
|
||||
INSERT INTO `m_permission`
|
||||
(
|
||||
`grouping`,
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'DELETE_OFFICETRANSACTION', 'OFFICETRANSACTION', 'DELETE', 1);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'DELETE_OFFICETRANSACTION', 'OFFICETRANSACTION', 'DELETE', 1);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('organisation', 'DELETE_OFFICETRANSACTION_CHECKER',
|
||||
'OFFICETRANSACTION', 'DELETE', 0);
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
package org.mifosplatform.accounting.api.data;
|
||||
|
||||
public class ProductToGLAccountMappingData {
|
||||
|
||||
private final Long id;
|
||||
private final Long glAccountId;
|
||||
private final Long productId;
|
||||
private final Integer productType;
|
||||
private final Integer financialAccountType;
|
||||
|
||||
public ProductToGLAccountMappingData(Long id, Long glAccountId, Long productId, Integer productType, Integer financialAccountType) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.glAccountId = glAccountId;
|
||||
this.productId = productId;
|
||||
this.productType = productType;
|
||||
this.financialAccountType = financialAccountType;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public Long getGlAccountId() {
|
||||
return this.glAccountId;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
|
||||
public Integer getProductType() {
|
||||
return this.productType;
|
||||
}
|
||||
|
||||
public Integer getFinancialAccountType() {
|
||||
return this.financialAccountType;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-4
@@ -1,9 +1,8 @@
|
||||
package org.mifosplatform.accounting.service;
|
||||
|
||||
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProductToGLAccountMappingReadPlatformService {
|
||||
|
||||
LoanProductData fetchAccountMappingDetailsForLoanProduct(LoanProductData loanProductData);
|
||||
|
||||
}
|
||||
Map<String, Object> fetchAccountMappingDetailsForLoanProduct(final Long loanProductId, final Integer accountingType);
|
||||
}
|
||||
+4
-5
@@ -2,14 +2,13 @@ package org.mifosplatform.accounting.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
|
||||
public interface ProductToGLAccountMappingWritePlatformService {
|
||||
|
||||
void createLoanProductToGLAccountMapping(Long loanProductId, LoanProductCommand command);
|
||||
void createLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command);
|
||||
|
||||
Map<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, LoanProductCommand command, boolean accountingRuleChanged);
|
||||
Map<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command, boolean accountingRuleChanged);
|
||||
|
||||
void deleteLoanProductToGLAccountMapping(Long loanProductId);
|
||||
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -2,14 +2,15 @@ package org.mifosplatform.accounting.service.impl;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.accounting.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
|
||||
import org.mifosplatform.accounting.AccountingConstants.CASH_ACCOUNTS_FOR_LOAN;
|
||||
import org.mifosplatform.accounting.api.data.ProductToGLAccountMappingData;
|
||||
import org.mifosplatform.accounting.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.mifosplatform.accounting.service.ProductToGLAccountMappingReadPlatformService;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -26,7 +27,7 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
private static final class LoanProductToGLAccountMappingMapper implements RowMapper<ProductToGLAccountMappingData> {
|
||||
private static final class LoanProductToGLAccountMappingMapper implements RowMapper<Map<String, Object>> {
|
||||
|
||||
public String schema() {
|
||||
return " id as id, gl_account_id as glAccountId,product_id as productId,product_type as productType,financial_account_type as financialAccountType"
|
||||
@@ -34,71 +35,89 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProductToGLAccountMappingData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
public Map<String, Object> mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
Long id = rs.getLong("id");
|
||||
Long glAccountId = rs.getLong("glAccountId");
|
||||
Long productId = rs.getLong("productId");
|
||||
Integer productType = rs.getInt("productType");
|
||||
Integer financialAccountType = rs.getInt("financialAccountType");
|
||||
final Long id = rs.getLong("id");
|
||||
final Long glAccountId = rs.getLong("glAccountId");
|
||||
final Long productId = rs.getLong("productId");
|
||||
final Integer productType = rs.getInt("productType");
|
||||
final Integer financialAccountType = rs.getInt("financialAccountType");
|
||||
|
||||
return new ProductToGLAccountMappingData(id, glAccountId, productId, productType, financialAccountType);
|
||||
final Map<String, Object> loanProductToGLAccountMap = new LinkedHashMap<String, Object>(5);
|
||||
loanProductToGLAccountMap.put("id", id);
|
||||
loanProductToGLAccountMap.put("glAccountId", glAccountId);
|
||||
loanProductToGLAccountMap.put("productId", productId);
|
||||
loanProductToGLAccountMap.put("productType", productType);
|
||||
loanProductToGLAccountMap.put("financialAccountType", financialAccountType);
|
||||
|
||||
return loanProductToGLAccountMap;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanProductData fetchAccountMappingDetailsForLoanProduct(LoanProductData loanProductData) {
|
||||
LoanProductToGLAccountMappingMapper rm = new LoanProductToGLAccountMappingMapper();
|
||||
String sql = "select " + rm.schema() + " and product_id = ?";
|
||||
List<ProductToGLAccountMappingData> productToGLAccountMappingDatas = this.jdbcTemplate.query(sql, rm,
|
||||
new Object[] { loanProductData.getId() });
|
||||
public Map<String, Object> fetchAccountMappingDetailsForLoanProduct(final Long loanProductId, final Integer accountingType) {
|
||||
|
||||
final Map<String, Object> accountMappingDetails = new LinkedHashMap<String, Object>(8);
|
||||
|
||||
final LoanProductToGLAccountMappingMapper rm = new LoanProductToGLAccountMappingMapper();
|
||||
final String sql = "select " + rm.schema() + " and product_id = ?";
|
||||
|
||||
final List<Map<String, Object>> listOfProductToGLAccountMaps = this.jdbcTemplate.query(sql, rm, new Object[] { loanProductId });
|
||||
|
||||
if (AccountingRuleType.CASH_BASED.getValue().equals(accountingType)) {
|
||||
|
||||
for (Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
CASH_ACCOUNTS_FOR_LOAN glAccountForLoan = CASH_ACCOUNTS_FOR_LOAN.fromInt(financialAccountType);
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
|
||||
if (loanProductData.getAccountingType() == AccountingRuleType.CASH_BASED.getValue()) {
|
||||
for (ProductToGLAccountMappingData productToGLAccountMappingData : productToGLAccountMappingDatas) {
|
||||
CASH_ACCOUNTS_FOR_LOAN glAccountForLoan = CASH_ACCOUNTS_FOR_LOAN.fromInt(productToGLAccountMappingData
|
||||
.getFinancialAccountType());
|
||||
if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE)) {
|
||||
loanProductData.setFundSourceAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES)) {
|
||||
loanProductData.setIncomeFromFeeAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES)) {
|
||||
loanProductData.setIncomeFromPenaltyAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS)) {
|
||||
loanProductData.setInterestOnLoanAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO)) {
|
||||
loanProductData.setLoanPortfolioAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF)) {
|
||||
loanProductData.setWriteOffAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), glAccountId);
|
||||
}
|
||||
}
|
||||
} else if (loanProductData.getAccountingType() == AccountingRuleType.ACCRUAL_BASED.getValue()) {
|
||||
for (ProductToGLAccountMappingData productToGLAccountMappingData : productToGLAccountMappingDatas) {
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN glAccountForLoan = ACCRUAL_ACCOUNTS_FOR_LOAN.fromInt(productToGLAccountMappingData
|
||||
.getFinancialAccountType());
|
||||
} else if (AccountingRuleType.ACCRUAL_BASED.getValue().equals(accountingType)) {
|
||||
|
||||
for (Map<String, Object> productToGLAccountMap : listOfProductToGLAccountMaps) {
|
||||
final Integer financialAccountType = (Integer) productToGLAccountMap.get("financialAccountType");
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN glAccountForLoan = ACCRUAL_ACCOUNTS_FOR_LOAN.fromInt(financialAccountType);
|
||||
|
||||
final Long glAccountId = (Long) productToGLAccountMap.get("glAccountId");
|
||||
|
||||
if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE)) {
|
||||
loanProductData.setFundSourceAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES)) {
|
||||
loanProductData.setIncomeFromFeeAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES)) {
|
||||
loanProductData.setIncomeFromPenaltyAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS)) {
|
||||
loanProductData.setInterestOnLoanAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO)) {
|
||||
loanProductData.setLoanPortfolioAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF)) {
|
||||
loanProductData.setWriteOffAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE)) {
|
||||
loanProductData.setReceivableInterestAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE)) {
|
||||
loanProductData.setReceivableFeeAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), glAccountId);
|
||||
} else if (glAccountForLoan.equals(ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE)) {
|
||||
loanProductData.setReceivablePenaltyAccountId(productToGLAccountMappingData.getGlAccountId());
|
||||
accountMappingDetails.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), glAccountId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return loanProductData;
|
||||
return accountMappingDetails;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+175
-118
@@ -2,6 +2,7 @@ package org.mifosplatform.accounting.service.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.accounting.AccountingConstants.ACCRUAL_ACCOUNTS_FOR_LOAN;
|
||||
@@ -15,168 +16,224 @@ import org.mifosplatform.accounting.domain.ProductToGLAccountMappingRepository;
|
||||
import org.mifosplatform.accounting.exceptions.GLAccountNotFoundException;
|
||||
import org.mifosplatform.accounting.exceptions.ProductToGLAccountMappingNotFoundException;
|
||||
import org.mifosplatform.accounting.service.ProductToGLAccountMappingWritePlatformService;
|
||||
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
@Service
|
||||
public class ProductToGLAccountMappingWritePlatformServiceImpl implements ProductToGLAccountMappingWritePlatformService {
|
||||
|
||||
private final GLAccountRepository accountRepository;
|
||||
private final ProductToGLAccountMappingRepository accountMappingRepository;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public ProductToGLAccountMappingWritePlatformServiceImpl(final GLAccountRepository glAccountRepository,
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository) {
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository, final FromJsonHelper fromApiJsonHelper) {
|
||||
this.accountRepository = glAccountRepository;
|
||||
this.accountMappingRepository = glAccountMappingRepository;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void createLoanProductToGLAccountMapping(Long loanProductId, LoanProductCommand command) {
|
||||
AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.getAccountingType());
|
||||
public void createLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command) {
|
||||
final JsonElement element = fromApiJsonHelper.parse(command.json());
|
||||
final Integer accountingRuleTypeId = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
if (accountingRuleType.equals(AccountingRuleType.NONE)) {
|
||||
return;
|
||||
} else if (accountingRuleType.equals(AccountingRuleType.CASH_BASED)) {
|
||||
// asset
|
||||
saveLoanToAccountMapping(command.getFundAccountId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue());
|
||||
saveLoanToAccountMapping(command.getLoanPortfolioAccountId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue());
|
||||
saveLoanToAccountMapping(command.getInterestOnLoanId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue());
|
||||
final Long loanPortfolioAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
element);
|
||||
final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element);
|
||||
final Long incomeFromInterestId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(),
|
||||
element);
|
||||
final Long incomeFromFeeId = fromApiJsonHelper
|
||||
.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
final Long writeOffAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
|
||||
// income
|
||||
saveLoanToAccountMapping(command.getIncomeFromFeeId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue());
|
||||
saveLoanToAccountMapping(command.getIncomeFromPenaltyId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue());
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
saveLoanToAccountMapping(fundAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue());
|
||||
saveLoanToAccountMapping(loanPortfolioAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue());
|
||||
saveLoanToAccountMapping(incomeFromInterestId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue());
|
||||
|
||||
// expenses
|
||||
saveLoanToAccountMapping(command.getWriteOffAccountId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue());
|
||||
} else if (accountingRuleType.equals(AccountingRuleType.ACCRUAL_BASED)) {
|
||||
// assets (including receivables)
|
||||
saveLoanToAccountMapping(command.getFundAccountId(), loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue());
|
||||
saveLoanToAccountMapping(command.getLoanPortfolioAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue());
|
||||
saveLoanToAccountMapping(command.getInterestOnLoanId(), loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue());
|
||||
// income
|
||||
saveLoanToAccountMapping(incomeFromFeeId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue());
|
||||
saveLoanToAccountMapping(incomeFromPenaltyId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
saveLoanToAccountMapping(command.getReceivableInterestAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue());
|
||||
saveLoanToAccountMapping(command.getReceivableFeeAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue());
|
||||
saveLoanToAccountMapping(command.getReceivablePenaltyAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue());
|
||||
// expenses
|
||||
saveLoanToAccountMapping(writeOffAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue());
|
||||
break;
|
||||
case ACCRUAL_BASED:
|
||||
final Long receivableInterestAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), element);
|
||||
final Long receivableFeeAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), element);
|
||||
final Long receivablePenaltyAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), element);
|
||||
|
||||
// income
|
||||
saveLoanToAccountMapping(command.getIncomeFromFeeId(), loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue());
|
||||
saveLoanToAccountMapping(command.getIncomeFromPenaltyId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue());
|
||||
// assets (including receivables)
|
||||
saveLoanToAccountMapping(fundAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue());
|
||||
saveLoanToAccountMapping(loanPortfolioAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue());
|
||||
saveLoanToAccountMapping(incomeFromInterestId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue());
|
||||
|
||||
// expenses
|
||||
saveLoanToAccountMapping(command.getWriteOffAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue());
|
||||
saveLoanToAccountMapping(receivableInterestAccountId, loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue());
|
||||
saveLoanToAccountMapping(receivableFeeAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue());
|
||||
saveLoanToAccountMapping(receivablePenaltyAccountId, loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue());
|
||||
|
||||
// income
|
||||
saveLoanToAccountMapping(incomeFromFeeId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue());
|
||||
saveLoanToAccountMapping(incomeFromPenaltyId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
// expenses
|
||||
saveLoanToAccountMapping(writeOffAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue());
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Map<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, LoanProductCommand command,
|
||||
public Map<String, Object> updateLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command,
|
||||
boolean accountingRuleChanged) {
|
||||
Map<String, Object> changes = new HashMap<String, Object>();
|
||||
AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.getAccountingType());
|
||||
final Map<String, Object> changes = new HashMap<String, Object>();
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(command.json());
|
||||
final Integer accountingRuleTypeId = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element);
|
||||
final Long loanPortfolioAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
element);
|
||||
final Long incomeFromInterestId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(),
|
||||
element);
|
||||
final Long incomeFromFeeId = fromApiJsonHelper
|
||||
.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
final Long writeOffAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
|
||||
final Long receivableInterestAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), element);
|
||||
final Long receivableFeeAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(),
|
||||
element);
|
||||
final Long receivablePenaltyAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), element);
|
||||
|
||||
if (accountingRuleChanged) {
|
||||
deleteLoanProductToGLAccountMapping(loanProductId);
|
||||
createLoanProductToGLAccountMapping(loanProductId, command);
|
||||
if (accountingRuleType.equals(AccountingRuleType.CASH_BASED)) {
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), command.getFundAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), command.getLoanPortfolioAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), command.getInterestOnLoanId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), command.getIncomeFromFeeId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), command.getIncomeFromPenaltyId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), command.getWriteOffAccountId());
|
||||
} else if (accountingRuleType.equals(AccountingRuleType.ACCRUAL_BASED)) {
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), command.getFundAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), command.getLoanPortfolioAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), command.getInterestOnLoanId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), command.getIncomeFromFeeId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), command.getIncomeFromPenaltyId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), command.getWriteOffAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), command.getReceivableInterestAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), command.getReceivableFeeAccountId());
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), command.getReceivablePenaltyAccountId());
|
||||
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), fundAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), loanPortfolioAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), incomeFromInterestId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeeId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), incomeFromPenaltyId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), writeOffAccountId);
|
||||
break;
|
||||
case ACCRUAL_BASED:
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), fundAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), loanPortfolioAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), incomeFromInterestId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeeId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), incomeFromPenaltyId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), writeOffAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), receivableInterestAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), receivableFeeAccountId);
|
||||
changes.put(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), receivablePenaltyAccountId);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
updateLoanToAccountMapping(fundAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), changes);
|
||||
updateLoanToAccountMapping(loanPortfolioAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
changes);
|
||||
updateLoanToAccountMapping(incomeFromInterestId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), changes);
|
||||
|
||||
if (accountingRuleType.equals(AccountingRuleType.NONE)) {
|
||||
// do nothing
|
||||
} else if (accountingRuleType.equals(AccountingRuleType.CASH_BASED)) {
|
||||
// asset
|
||||
updateLoanToAccountMapping(command.getFundAccountId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getLoanPortfolioAccountId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), CASH_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getInterestOnLoanId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue(), CASH_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), changes);
|
||||
// income
|
||||
updateLoanToAccountMapping(incomeFromFeeId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
changes);
|
||||
updateLoanToAccountMapping(incomeFromPenaltyId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), changes);
|
||||
|
||||
// income
|
||||
updateLoanToAccountMapping(command.getIncomeFromFeeId(), loanProductId, CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
changes);
|
||||
updateLoanToAccountMapping(command.getIncomeFromPenaltyId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(), CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), changes);
|
||||
// expenses
|
||||
updateLoanToAccountMapping(writeOffAccountId, loanProductId, CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(),
|
||||
CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), changes);
|
||||
break;
|
||||
case ACCRUAL_BASED:
|
||||
// assets (including receivables)
|
||||
updateLoanToAccountMapping(fundAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
|
||||
changes);
|
||||
updateLoanToAccountMapping(loanPortfolioAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
changes);
|
||||
updateLoanToAccountMapping(incomeFromInterestId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), changes);
|
||||
|
||||
// expenses
|
||||
updateLoanToAccountMapping(command.getWriteOffAccountId(), loanProductId,
|
||||
CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(), CASH_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), changes);
|
||||
} else if (accountingRuleType.equals(AccountingRuleType.ACCRUAL_BASED)) {
|
||||
// assets (including receivables)
|
||||
updateLoanToAccountMapping(command.getFundAccountId(), loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.FUND_SOURCE.toString(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getLoanPortfolioAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.LOAN_PORTFOLIO.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getInterestOnLoanId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_ON_LOANS.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), changes);
|
||||
updateLoanToAccountMapping(receivableInterestAccountId, loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), changes);
|
||||
|
||||
updateLoanToAccountMapping(command.getReceivableInterestAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INTEREST_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getReceivableFeeAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getReceivablePenaltyAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), changes);
|
||||
updateLoanToAccountMapping(receivableFeeAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.FEES_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), changes);
|
||||
|
||||
// income
|
||||
updateLoanToAccountMapping(command.getIncomeFromFeeId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), changes);
|
||||
updateLoanToAccountMapping(command.getIncomeFromPenaltyId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), changes);
|
||||
updateLoanToAccountMapping(receivablePenaltyAccountId, loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.PENALTIES_RECEIVABLE.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), changes);
|
||||
|
||||
// expenses
|
||||
updateLoanToAccountMapping(command.getWriteOffAccountId(), loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(), ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), changes);
|
||||
// income
|
||||
updateLoanToAccountMapping(incomeFromFeeId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_FEES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), changes);
|
||||
updateLoanToAccountMapping(incomeFromPenaltyId, loanProductId,
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), changes);
|
||||
|
||||
// expenses
|
||||
updateLoanToAccountMapping(writeOffAccountId, loanProductId, ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.getValue(),
|
||||
ACCRUAL_ACCOUNTS_FOR_LOAN.LOSSES_WRITTEN_OFF.toString(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), changes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
private void saveLoanToAccountMapping(Long glAccountId, Long productId, int accountTypeId) {
|
||||
private void saveLoanToAccountMapping(final Long glAccountId, final Long productId, final int accountTypeId) {
|
||||
GLAccount glAccount = accountRepository.findOne(glAccountId);
|
||||
if (glAccount == null) { throw new GLAccountNotFoundException(glAccountId); }
|
||||
ProductToGLAccountMapping accountMapping = new ProductToGLAccountMapping(glAccount, productId,
|
||||
@@ -184,8 +241,8 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
accountMappingRepository.save(accountMapping);
|
||||
}
|
||||
|
||||
private void updateLoanToAccountMapping(Long glAccountId, Long productId, int accountTypeId, String accountTypeName,
|
||||
String accountParamValue, Map<String, Object> changes) {
|
||||
private void updateLoanToAccountMapping(final Long glAccountId, final Long productId, final int accountTypeId,
|
||||
final String accountTypeName, final String accountParamValue, final Map<String, Object> changes) {
|
||||
// get the existing product
|
||||
ProductToGLAccountMapping accountMapping = accountMappingRepository.findByProductIdAndProductTypeAndFinancialAccountType(productId,
|
||||
PortfolioProductType.LOAN.getValue(), accountTypeId);
|
||||
@@ -201,7 +258,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteLoanProductToGLAccountMapping(Long loanProductId) {
|
||||
public void deleteLoanProductToGLAccountMapping(final Long loanProductId) {
|
||||
List<ProductToGLAccountMapping> productToGLAccountMappings = accountMappingRepository.findByProductIdAndProductType(loanProductId,
|
||||
PortfolioProductType.LOAN.getValue());
|
||||
if (productToGLAccountMappings != null && productToGLAccountMappings.size() > 0) {
|
||||
|
||||
+24
-16
@@ -2,8 +2,10 @@ package org.mifosplatform.portfolio.loanproduct.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
@@ -56,10 +58,12 @@ public class LoanProductsApiResource {
|
||||
"interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "charges", "createdOn",
|
||||
"lastModifedOn", "currencyOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||
"repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "transactionProcessingStrategyOptions",
|
||||
"chargeOptions", "assetAccountOptions", "incomeAccountOptions", "expenseAccountOptions", "accountingType" , LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue()));
|
||||
"chargeOptions", "assetAccountOptions", "incomeAccountOptions", "expenseAccountOptions", "accountingType",
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue()));
|
||||
|
||||
private final String resourceNameForPermissions = "LOANPRODUCT";
|
||||
|
||||
@@ -131,7 +135,7 @@ public class LoanProductsApiResource {
|
||||
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
|
||||
|
||||
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveNewLoanProductDetails();
|
||||
loanProduct = handleTemplate(loanProduct);
|
||||
loanProduct = handleTemplate(loanProduct, new HashMap<String, Object>());
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, loanProduct, LOAN_PRODUCT_DATA_PARAMETERS);
|
||||
@@ -148,13 +152,17 @@ public class LoanProductsApiResource {
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId);
|
||||
if (settings.isTemplate()) {
|
||||
loanProduct = handleTemplate(loanProduct);
|
||||
}
|
||||
|
||||
LoanProductData loanProductDataUpdatedWithAccountingMapping=accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(loanProduct);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, loanProductDataUpdatedWithAccountingMapping, LOAN_PRODUCT_DATA_PARAMETERS);
|
||||
Map<String, Object> accountingMappings = null;
|
||||
if (loanProduct.hasAccountingEnabled()) {
|
||||
accountingMappings = accountMappingReadPlatformService.fetchAccountMappingDetailsForLoanProduct(productId, loanProduct.accountingRuleType());
|
||||
loanProduct = LoanProductData.withAccountingMappings(loanProduct, accountingMappings);
|
||||
}
|
||||
|
||||
if (settings.isTemplate()) {
|
||||
loanProduct = handleTemplate(loanProduct, accountingMappings);
|
||||
}
|
||||
return this.toApiJsonSerializer.serialize(settings, loanProduct, LOAN_PRODUCT_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -171,7 +179,7 @@ public class LoanProductsApiResource {
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private LoanProductData handleTemplate(final LoanProductData productData) {
|
||||
private LoanProductData handleTemplate(final LoanProductData productData, final Map<String, Object> accountingMappings) {
|
||||
|
||||
final boolean feeChargesOnly = true;
|
||||
Collection<ChargeData> chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly);
|
||||
@@ -196,7 +204,7 @@ public class LoanProductsApiResource {
|
||||
}
|
||||
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService
|
||||
.retreiveTransactionProcessingStrategies();
|
||||
|
||||
|
||||
List<GLAccountData> assetAccountOptions = accountReadPlatformService.retrieveAllEnabledDetailGLAccounts(GLAccountType.ASSET);
|
||||
if (assetAccountOptions.isEmpty()) {
|
||||
assetAccountOptions = null;
|
||||
@@ -209,10 +217,10 @@ public class LoanProductsApiResource {
|
||||
if (expenseAccountOptions.isEmpty()) {
|
||||
expenseAccountOptions = null;
|
||||
}
|
||||
|
||||
|
||||
return new LoanProductData(productData, chargeOptions, currencyOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
|
||||
interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions,
|
||||
assetAccountOptions, incomeAccountOptions, expenseAccountOptions);
|
||||
interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, assetAccountOptions,
|
||||
incomeAccountOptions, expenseAccountOptions, accountingMappings);
|
||||
}
|
||||
}
|
||||
-345
@@ -1,345 +0,0 @@
|
||||
package org.mifosplatform.portfolio.loanproduct.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.accounting.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType;
|
||||
|
||||
/**
|
||||
* Immutable command for creating or updating details of a loan product.
|
||||
*/
|
||||
public class LoanProductCommand {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final Long fundId;
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String currencyCode;
|
||||
private final Integer digitsAfterDecimal;
|
||||
private final BigDecimal principal;
|
||||
private final BigDecimal inArrearsTolerance;
|
||||
private final Integer numberOfRepayments;
|
||||
private final Integer repaymentEvery;
|
||||
private final BigDecimal interestRatePerPeriod;
|
||||
private final Integer repaymentFrequencyType;
|
||||
private final Integer interestRateFrequencyType;
|
||||
private final Integer amortizationType;
|
||||
private final Integer interestType;
|
||||
private final Integer interestCalculationPeriodType;
|
||||
private final String[] charges;
|
||||
|
||||
// accounting fields
|
||||
private final Integer accountingType;
|
||||
// accounting heads used for cash/accrual based accounting
|
||||
private final Long loanPortfolioAccountId;
|
||||
private final Long fundAccountId;
|
||||
private final Long interestOnLoanId;
|
||||
private final Long incomeFromFeeId;
|
||||
private final Long incomeFromPenaltyId;
|
||||
private final Long writeOffAccountId;
|
||||
// accounting heads used only for accrual based accounting
|
||||
private final Long receivableInterestAccountId;
|
||||
private final Long receivableFeeAccountId;
|
||||
private final Long receivablePenaltyAccountId;
|
||||
|
||||
public LoanProductCommand(final String name, final String description, final Long fundId, final Long transactionProcessingStrategyId,
|
||||
final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal principal, final BigDecimal inArrearsTolerance,
|
||||
final Integer numberOfRepayments, final Integer repaymentEvery, final BigDecimal interestRatePerPeriod,
|
||||
final Integer repaymentFrequencyType, final Integer interestRateFrequencyType, final Integer amortizationType,
|
||||
final Integer interestType, final Integer interestCalculationPeriodType, final String[] charges, final Integer accountingType,
|
||||
final Long loanPortfolioAccountId, final Long fundAccountId, final Long interestOnLoanId, final Long incomeFromFeeId,
|
||||
final Long incomeFromPenaltyId, final Long writeOffAccountId, final Long receivableInterestAccountId,
|
||||
final Long receivableFeeAccountId, final Long receivablePenaltyAccountId) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.fundId = fundId;
|
||||
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
|
||||
this.currencyCode = currencyCode;
|
||||
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||
this.principal = principal;
|
||||
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
|
||||
this.inArrearsTolerance = null;
|
||||
} else {
|
||||
this.inArrearsTolerance = inArrearsTolerance;
|
||||
}
|
||||
this.numberOfRepayments = numberOfRepayments;
|
||||
this.repaymentEvery = repaymentEvery;
|
||||
this.interestRatePerPeriod = interestRatePerPeriod;
|
||||
this.repaymentFrequencyType = repaymentFrequencyType;
|
||||
this.interestRateFrequencyType = interestRateFrequencyType;
|
||||
this.amortizationType = amortizationType;
|
||||
this.interestType = interestType;
|
||||
this.interestCalculationPeriodType = interestCalculationPeriodType;
|
||||
this.charges = charges;
|
||||
this.accountingType = accountingType;
|
||||
// accounting heads used for cash/accrual based accounting
|
||||
this.loanPortfolioAccountId = loanPortfolioAccountId;
|
||||
this.fundAccountId = fundAccountId;
|
||||
this.interestOnLoanId = interestOnLoanId;
|
||||
this.incomeFromFeeId = incomeFromFeeId;
|
||||
this.incomeFromPenaltyId = incomeFromPenaltyId;
|
||||
this.writeOffAccountId = writeOffAccountId;
|
||||
// accounting heads used only for accrual based accounting
|
||||
this.receivableInterestAccountId = receivableInterestAccountId;
|
||||
this.receivableFeeAccountId = receivableFeeAccountId;
|
||||
this.receivablePenaltyAccountId = receivablePenaltyAccountId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Long getFundId() {
|
||||
return fundId;
|
||||
}
|
||||
|
||||
public Long getTransactionProcessingStrategyId() {
|
||||
return transactionProcessingStrategyId;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return currencyCode;
|
||||
}
|
||||
|
||||
public Integer getDigitsAfterDecimal() {
|
||||
return digitsAfterDecimal;
|
||||
}
|
||||
|
||||
public BigDecimal getPrincipal() {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public BigDecimal getInArrearsTolerance() {
|
||||
return inArrearsTolerance;
|
||||
}
|
||||
|
||||
public Integer getNumberOfRepayments() {
|
||||
return numberOfRepayments;
|
||||
}
|
||||
|
||||
public Integer getRepaymentEvery() {
|
||||
return repaymentEvery;
|
||||
}
|
||||
|
||||
public BigDecimal getInterestRatePerPeriod() {
|
||||
return interestRatePerPeriod;
|
||||
}
|
||||
|
||||
public Integer getRepaymentFrequencyType() {
|
||||
return repaymentFrequencyType;
|
||||
}
|
||||
|
||||
public Integer getInterestRateFrequencyType() {
|
||||
return interestRateFrequencyType;
|
||||
}
|
||||
|
||||
public Integer getAmortizationType() {
|
||||
return amortizationType;
|
||||
}
|
||||
|
||||
public Integer getInterestType() {
|
||||
return interestType;
|
||||
}
|
||||
|
||||
public Integer getInterestCalculationPeriodType() {
|
||||
return interestCalculationPeriodType;
|
||||
}
|
||||
|
||||
public String[] getCharges() {
|
||||
return charges;
|
||||
}
|
||||
|
||||
public Integer getAccountingType() {
|
||||
return this.accountingType;
|
||||
}
|
||||
|
||||
|
||||
public Long getLoanPortfolioAccountId() {
|
||||
return this.loanPortfolioAccountId;
|
||||
}
|
||||
|
||||
|
||||
public Long getFundAccountId() {
|
||||
return this.fundAccountId;
|
||||
}
|
||||
|
||||
|
||||
public Long getInterestOnLoanId() {
|
||||
return this.interestOnLoanId;
|
||||
}
|
||||
|
||||
|
||||
public Long getIncomeFromFeeId() {
|
||||
return this.incomeFromFeeId;
|
||||
}
|
||||
|
||||
|
||||
public Long getIncomeFromPenaltyId() {
|
||||
return this.incomeFromPenaltyId;
|
||||
}
|
||||
|
||||
|
||||
public Long getWriteOffAccountId() {
|
||||
return this.writeOffAccountId;
|
||||
}
|
||||
|
||||
|
||||
public Long getReceivableInterestAccountId() {
|
||||
return this.receivableInterestAccountId;
|
||||
}
|
||||
|
||||
|
||||
public Long getReceivableFeeAccountId() {
|
||||
return this.receivableFeeAccountId;
|
||||
}
|
||||
|
||||
|
||||
public Long getReceivablePenaltyAccountId() {
|
||||
return this.receivablePenaltyAccountId;
|
||||
}
|
||||
|
||||
public void validateForCreate() {
|
||||
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("product");
|
||||
|
||||
baseDataValidator.reset().parameter("name").value(this.name).notBlank();
|
||||
baseDataValidator.reset().parameter("description").value(this.description).notExceedingLengthOf(500);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(this.currencyCode).notBlank();
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(this.digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
|
||||
baseDataValidator.reset().parameter("principal").value(this.principal).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(this.inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(this.repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
baseDataValidator.reset().parameter("repaymentEvery").value(this.repaymentEvery).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(this.numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(this.interestRatePerPeriod).notNull();
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(this.interestRateFrequencyType).notNull()
|
||||
.inMinMaxRange(0, 3);
|
||||
|
||||
baseDataValidator.reset().parameter("amortizationType").value(this.amortizationType).notNull().inMinMaxRange(0, 1);
|
||||
baseDataValidator.reset().parameter("interestType").value(this.interestType).notNull().inMinMaxRange(0, 1);
|
||||
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(this.interestCalculationPeriodType).notNull()
|
||||
.inMinMaxRange(0, 1);
|
||||
|
||||
// validation for accounting rules
|
||||
baseDataValidator.reset().parameter("accountingType").value(this.accountingType).notNull().inMinMaxRange(1,3);
|
||||
if (this.getAccountingType() != null) {
|
||||
/**
|
||||
* validation for heads applicable for both cash and accrual based
|
||||
* accounting
|
||||
**/
|
||||
if (this.getAccountingType().equals(AccountingRuleType.CASH_BASED.getValue())
|
||||
|| this.getAccountingType().equals(AccountingRuleType.ACCRUAL_BASED.getValue())) {
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue())
|
||||
.value(this.loanPortfolioAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue()).value(this.fundAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue())
|
||||
.value(this.interestOnLoanId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(this.incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(this.incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue())
|
||||
.value(this.writeOffAccountId).notNull().integerGreaterThanZero();
|
||||
}// validation for accrual based accounting specific heads
|
||||
if (this.getAccountingType().equals(AccountingRuleType.ACCRUAL_BASED.getValue())) {
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue())
|
||||
.value(this.receivableInterestAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue())
|
||||
.value(this.receivableFeeAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue())
|
||||
.value(this.receivablePenaltyAccountId).notNull().integerGreaterThanZero();
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
public void validateForUpdate() {
|
||||
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("product");
|
||||
|
||||
baseDataValidator.reset().parameter("name").value(this.name).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("description").value(this.description).ignoreIfNull().notExceedingLengthOf(500);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(this.currencyCode).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(this.digitsAfterDecimal).ignoreIfNull().notNull()
|
||||
.inMinMaxRange(0, 6);
|
||||
|
||||
baseDataValidator.reset().parameter("principal").value(this.principal).ignoreIfNull().notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(this.inArrearsTolerance).ignoreIfNull().notNull()
|
||||
.zeroOrPositiveAmount();
|
||||
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(this.repaymentFrequencyType).ignoreIfNull().notNull()
|
||||
.inMinMaxRange(0, 3);
|
||||
|
||||
baseDataValidator.reset().parameter("repaymentEvery").value(this.repaymentEvery).ignoreIfNull().notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(this.numberOfRepayments).ignoreIfNull().notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(this.interestRatePerPeriod).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(this.interestRateFrequencyType).ignoreIfNull().notNull()
|
||||
.inMinMaxRange(0, 3);
|
||||
|
||||
baseDataValidator.reset().parameter("amortizationType").value(this.amortizationType).ignoreIfNull().notNull().inMinMaxRange(0, 1);
|
||||
baseDataValidator.reset().parameter("interestType").value(this.interestType).ignoreIfNull().notNull().inMinMaxRange(0, 1);
|
||||
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(this.interestCalculationPeriodType).ignoreIfNull()
|
||||
.notNull().inMinMaxRange(0, 1);
|
||||
|
||||
// validation for accounting rules
|
||||
baseDataValidator.reset().parameter("accountingType").value(this.accountingType).ignoreIfNull().inMinMaxRange(1, 3);
|
||||
if (this.getAccountingType() != null) {
|
||||
/**
|
||||
* validation for heads applicable for both cash and accrual based
|
||||
* accounting
|
||||
**/
|
||||
if (this.getAccountingType().equals(AccountingRuleType.CASH_BASED.getValue())
|
||||
|| this.getAccountingType().equals(AccountingRuleType.ACCRUAL_BASED.getValue())) {
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue())
|
||||
.value(this.loanPortfolioAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue()).value(this.fundAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue())
|
||||
.value(this.interestOnLoanId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(this.incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(this.incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue())
|
||||
.value(this.writeOffAccountId).notNull().integerGreaterThanZero();
|
||||
}// validation for accrual based accounting specific heads
|
||||
if (this.getAccountingType().equals(AccountingRuleType.ACCRUAL_BASED.getValue())) {
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue())
|
||||
.value(this.receivableInterestAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue())
|
||||
.value(this.receivableFeeAccountId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue())
|
||||
.value(this.receivablePenaltyAccountId).notNull().integerGreaterThanZero();
|
||||
}
|
||||
}
|
||||
|
||||
baseDataValidator.reset().anyOfNotNull(this.fundId, this.transactionProcessingStrategyId, this.name, this.description,
|
||||
this.currencyCode, this.digitsAfterDecimal, this.principal, this.inArrearsTolerance, this.repaymentFrequencyType,
|
||||
this.repaymentEvery, this.numberOfRepayments, this.interestRatePerPeriod, this.interestRateFrequencyType,
|
||||
this.amortizationType, this.interestType, this.interestCalculationPeriodType, this.charges, this.accountingType);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+34
-112
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.accounting.api.data.GLAccountData;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
@@ -24,33 +25,31 @@ public class LoanProductData {
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private final Long fundId;
|
||||
private final String fundName;
|
||||
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String transactionProcessingStrategyName;
|
||||
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal principal;
|
||||
private final BigDecimal inArrearsTolerance;
|
||||
|
||||
private final Integer numberOfRepayments;
|
||||
private final Integer loanTermFrequency;
|
||||
private final Integer repaymentEvery;
|
||||
private final BigDecimal interestRatePerPeriod;
|
||||
private final BigDecimal annualInterestRate;
|
||||
private final Integer accountingType;
|
||||
|
||||
private final EnumOptionData loanTermFrequencyType;
|
||||
private final EnumOptionData repaymentFrequencyType;
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String transactionProcessingStrategyName;
|
||||
private final BigDecimal interestRatePerPeriod;
|
||||
private final EnumOptionData interestRateFrequencyType;
|
||||
private final BigDecimal annualInterestRate;
|
||||
private final EnumOptionData amortizationType;
|
||||
private final EnumOptionData interestType;
|
||||
private final EnumOptionData interestCalculationPeriodType;
|
||||
private final BigDecimal inArrearsTolerance;
|
||||
|
||||
// FIXME - KW - This should be returned for serialization as an EnumOptionData like the other Enumerated values
|
||||
private final Integer accountingType;
|
||||
|
||||
private final Collection<ChargeData> charges;
|
||||
|
||||
// template related
|
||||
private final Collection<CurrencyData> currencyOptions;
|
||||
private final Collection<FundData> fundOptions;
|
||||
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
|
||||
@@ -67,17 +66,9 @@ public class LoanProductData {
|
||||
private final List<GLAccountData> incomeAccountOptions;
|
||||
private final List<GLAccountData> expenseAccountOptions;
|
||||
|
||||
// accounting related mapping feilds
|
||||
private Long loanPortfolioAccountId;
|
||||
private Long fundSourceAccountId;
|
||||
private Long interestOnLoanAccountId;
|
||||
private Long incomeFromFeeAccountId;
|
||||
private Long incomeFromPenaltyAccountId;
|
||||
private Long writeOffAccountId;
|
||||
// accounting heads used only for accrual based accounting
|
||||
private Long receivableInterestAccountId;
|
||||
private Long receivableFeeAccountId;
|
||||
private Long receivablePenaltyAccountId;
|
||||
// accounting related mapping fields
|
||||
@SuppressWarnings("unused")
|
||||
private final Map<String, Object> accountingMappings;
|
||||
|
||||
/**
|
||||
* Used when returning lookup information about loan product for dropdowns.
|
||||
@@ -143,6 +134,15 @@ public class LoanProductData {
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
|
||||
public static LoanProductData withAccountingMappings(final LoanProductData productData, final Map<String, Object> accountingMappings) {
|
||||
|
||||
return new LoanProductData(productData, productData.chargeOptions, productData.currencyOptions,
|
||||
productData.amortizationTypeOptions, productData.interestTypeOptions, productData.interestCalculationPeriodTypeOptions,
|
||||
productData.loanTermFrequencyTypeOptions, productData.repaymentFrequencyTypeOptions,
|
||||
productData.interestRateFrequencyTypeOptions, productData.fundOptions, productData.transactionProcessingStrategyOptions,
|
||||
productData.assetAccountOptions, productData.incomeAccountOptions, productData.expenseAccountOptions, accountingMappings);
|
||||
}
|
||||
|
||||
public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
final BigDecimal principal, final BigDecimal tolerance, final Integer numberOfRepayments, final Integer loanTermFrequency,
|
||||
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, final BigDecimal annualInterestRate,
|
||||
@@ -189,6 +189,7 @@ public class LoanProductData {
|
||||
this.assetAccountOptions = null;
|
||||
this.incomeAccountOptions = null;
|
||||
this.expenseAccountOptions = null;
|
||||
this.accountingMappings = null;
|
||||
}
|
||||
|
||||
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
|
||||
@@ -198,7 +199,7 @@ public class LoanProductData {
|
||||
final List<EnumOptionData> interestRateFrequencyTypeOptions, final Collection<FundData> fundOptions,
|
||||
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions,
|
||||
final List<GLAccountData> assetAccountOptions, final List<GLAccountData> incomeAccountOptions,
|
||||
final List<GLAccountData> expenseAccountOptions) {
|
||||
final List<GLAccountData> expenseAccountOptions, final Map<String, Object> accountingMappings) {
|
||||
this.id = productData.id;
|
||||
this.name = productData.name;
|
||||
this.description = productData.description;
|
||||
@@ -224,7 +225,7 @@ public class LoanProductData {
|
||||
|
||||
this.chargeOptions = chargeOptions;
|
||||
this.currencyOptions = currencyOptions;
|
||||
if (this.currencyOptions.size() == 1) {
|
||||
if (this.currencyOptions != null && this.currencyOptions.size() == 1) {
|
||||
this.currency = new ArrayList<CurrencyData>(this.currencyOptions).get(0);
|
||||
} else {
|
||||
this.currency = productData.currency;
|
||||
@@ -241,6 +242,7 @@ public class LoanProductData {
|
||||
this.assetAccountOptions = assetAccountOptions;
|
||||
this.incomeAccountOptions = incomeAccountOptions;
|
||||
this.expenseAccountOptions = expenseAccountOptions;
|
||||
this.accountingMappings = accountingMappings;
|
||||
}
|
||||
|
||||
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
|
||||
@@ -259,6 +261,14 @@ public class LoanProductData {
|
||||
return chargesLocal;
|
||||
}
|
||||
|
||||
public Integer accountingRuleType() {
|
||||
return this.accountingType;
|
||||
}
|
||||
|
||||
public boolean hasAccountingEnabled() {
|
||||
return this.accountingType > 1;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -378,92 +388,4 @@ public class LoanProductData {
|
||||
public Collection<ChargeData> getChargeOptions() {
|
||||
return chargeOptions;
|
||||
}
|
||||
|
||||
public List<GLAccountData> getAssetAccountOptions() {
|
||||
return this.assetAccountOptions;
|
||||
}
|
||||
|
||||
public List<GLAccountData> getIncomeAccountOptions() {
|
||||
return this.incomeAccountOptions;
|
||||
}
|
||||
|
||||
public List<GLAccountData> getExpenseAccountOptions() {
|
||||
return this.expenseAccountOptions;
|
||||
}
|
||||
|
||||
public Long getLoanPortfolioAccountId() {
|
||||
return this.loanPortfolioAccountId;
|
||||
}
|
||||
|
||||
public void setLoanPortfolioAccountId(Long loanPortfolioAccountId) {
|
||||
this.loanPortfolioAccountId = loanPortfolioAccountId;
|
||||
}
|
||||
|
||||
public Long getFundSourceAccountId() {
|
||||
return this.fundSourceAccountId;
|
||||
}
|
||||
|
||||
public void setFundSourceAccountId(Long fundSourceAccountId) {
|
||||
this.fundSourceAccountId = fundSourceAccountId;
|
||||
}
|
||||
|
||||
public Long getInterestOnLoanAccountId() {
|
||||
return this.interestOnLoanAccountId;
|
||||
}
|
||||
|
||||
public void setInterestOnLoanAccountId(Long interestOnLoanAccountId) {
|
||||
this.interestOnLoanAccountId = interestOnLoanAccountId;
|
||||
}
|
||||
|
||||
public Long getIncomeFromFeeAccountId() {
|
||||
return this.incomeFromFeeAccountId;
|
||||
}
|
||||
|
||||
public void setIncomeFromFeeAccountId(Long incomeFromFeeAccountId) {
|
||||
this.incomeFromFeeAccountId = incomeFromFeeAccountId;
|
||||
}
|
||||
|
||||
public Long getIncomeFromPenaltyAccountId() {
|
||||
return this.incomeFromPenaltyAccountId;
|
||||
}
|
||||
|
||||
public void setIncomeFromPenaltyAccountId(Long incomeFromPenaltyAccountId) {
|
||||
this.incomeFromPenaltyAccountId = incomeFromPenaltyAccountId;
|
||||
}
|
||||
|
||||
public Long getWriteOffAccountId() {
|
||||
return this.writeOffAccountId;
|
||||
}
|
||||
|
||||
public void setWriteOffAccountId(Long writeOffAccountId) {
|
||||
this.writeOffAccountId = writeOffAccountId;
|
||||
}
|
||||
|
||||
public Long getReceivableInterestAccountId() {
|
||||
return this.receivableInterestAccountId;
|
||||
}
|
||||
|
||||
public void setReceivableInterestAccountId(Long receivableInterestAccountId) {
|
||||
this.receivableInterestAccountId = receivableInterestAccountId;
|
||||
}
|
||||
|
||||
public Long getReceivableFeeAccountId() {
|
||||
return this.receivableFeeAccountId;
|
||||
}
|
||||
|
||||
public void setReceivableFeeAccountId(Long receivableFeeAccountId) {
|
||||
this.receivableFeeAccountId = receivableFeeAccountId;
|
||||
}
|
||||
|
||||
public Long getReceivablePenaltyAccountId() {
|
||||
return this.receivablePenaltyAccountId;
|
||||
}
|
||||
|
||||
public void setReceivablePenaltyAccountId(Long receivablePenaltyAccountId) {
|
||||
this.receivablePenaltyAccountId = receivablePenaltyAccountId;
|
||||
}
|
||||
|
||||
public Integer getAccountingType() {
|
||||
return this.accountingType;
|
||||
}
|
||||
}
|
||||
+296
-51
@@ -2,30 +2,30 @@ package org.mifosplatform.portfolio.loanproduct.serialization;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.accounting.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* Implementation of {@link FromApiJsonDeserializer} for
|
||||
* {@link LoanProductCommand}'s.
|
||||
*/
|
||||
@Component
|
||||
public final class LoanProductCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<LoanProductCommand> {
|
||||
public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
@@ -33,10 +33,12 @@ public final class LoanProductCommandFromApiJsonDeserializer extends AbstractFro
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("name", "description", "fundId",
|
||||
"transactionProcessingStrategyId", "currencyCode", "digitsAfterDecimal", "principal", "inArrearsTolerance",
|
||||
"interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType", "interestRateFrequencyType",
|
||||
"amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingType" , LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue()));
|
||||
"amortizationType", "interestType", "interestCalculationPeriodType", "charges", "locale", "accountingType",
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue()));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@@ -45,54 +47,297 @@ public final class LoanProductCommandFromApiJsonDeserializer extends AbstractFro
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanProductCommand commandFromApiJson(final String json) {
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
||||
final String description = fromApiJsonHelper.extractStringNamed("description", element);
|
||||
final Long fundId = fromApiJsonHelper.extractLongNamed("fundId", element);
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanproduct");
|
||||
|
||||
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
|
||||
|
||||
final String description = fromApiJsonHelper.extractStringNamed("description", element);
|
||||
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(500);
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("fundId", element)) {
|
||||
final Long fundId = fromApiJsonHelper.extractLongNamed("fundId", element);
|
||||
baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
|
||||
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerWithLocaleNamed("digitsAfterDecimal", element);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
|
||||
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerNamed("digitsAfterDecimal", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
|
||||
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||
final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
final Integer repaymentEvery = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
final Integer repaymentFrequencyType = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentFrequencyType", element);
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestRateFrequencyType", element);
|
||||
final Integer amortizationType = fromApiJsonHelper.extractIntegerWithLocaleNamed("amortizationType", element);
|
||||
final Integer interestType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestType", element);
|
||||
final Integer interestCalculationPeriodType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestCalculationPeriodType",
|
||||
element);
|
||||
final String[] charges = fromApiJsonHelper.extractArrayNamed("charges", element);
|
||||
|
||||
//extract accounting related fields
|
||||
final Integer accountingType = fromApiJsonHelper.extractIntegerWithLocaleNamed("accountingType",
|
||||
element);
|
||||
final Long loanPortfolioAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), element);
|
||||
final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element);
|
||||
final Long incomeFromInterestId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), element);
|
||||
final Long incomeFromFeeId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
final Long writeOffAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
final Long receivableInterestAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), element);
|
||||
final Long receivableFeeAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), element);
|
||||
final Long receivablePenaltyAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
|
||||
|
||||
return new LoanProductCommand(name, description, fundId, transactionProcessingStrategyId, currencyCode, digitsAfterDecimal,
|
||||
principal, inArrearsTolerance, numberOfRepayments, repaymentEvery, interestRatePerPeriod, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, charges, accountingType,
|
||||
loanPortfolioAccountId, fundAccountId, incomeFromInterestId, incomeFromFeeId, incomeFromPenaltyId, writeOffAccountId,
|
||||
receivableInterestAccountId, receivableFeeAccountId, receivablePenaltyAccountId);
|
||||
}
|
||||
final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer repaymentEvery = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
|
||||
baseDataValidator.reset().parameter("repaymentEvery").value(repaymentEvery).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer repaymentFrequencyType = fromApiJsonHelper
|
||||
.extractIntegerNamed("repaymentFrequencyType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
final Integer amortizationType = fromApiJsonHelper.extractIntegerNamed("amortizationType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("amortizationType").value(amortizationType).notNull().inMinMaxRange(0, 1);
|
||||
|
||||
final Integer interestType = fromApiJsonHelper.extractIntegerNamed("interestType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestType").value(interestType).notNull().inMinMaxRange(0, 1);
|
||||
|
||||
final Integer interestCalculationPeriodType = fromApiJsonHelper.extractIntegerNamed("interestCalculationPeriodType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(interestCalculationPeriodType).notNull()
|
||||
.inMinMaxRange(0, 1);
|
||||
|
||||
// accounting related data validation
|
||||
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingType").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
if (isCashBased(accountingRuleType) || isAccrualBased(accountingRuleType)) {
|
||||
|
||||
final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue()).value(fundAccountId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final Long loanPortfolioAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue()).value(loanPortfolioAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (isAccrualBased(accountingRuleType)) {
|
||||
|
||||
final Long receivableInterestAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue())
|
||||
.value(receivableInterestAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long receivableFeeAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue()).value(receivableFeeAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long receivablePenaltyAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue())
|
||||
.value(receivablePenaltyAccountId).notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (isCashBased(accountingRuleType) || isAccrualBased(accountingRuleType)) {
|
||||
final Long incomeFromInterestId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue()).value(incomeFromInterestId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromFeeId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writeOffAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanproduct");
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
if (fromApiJsonHelper.parameterExists("name", element)) {
|
||||
final String name = fromApiJsonHelper.extractStringNamed("name", element);
|
||||
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("description", element)) {
|
||||
final String description = fromApiJsonHelper.extractStringNamed("description", element);
|
||||
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(500);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("fundId", element)) {
|
||||
final Long fundId = fromApiJsonHelper.extractLongNamed("fundId", element);
|
||||
baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("currencyCode", element)) {
|
||||
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("digitsAfterDecimal", element)) {
|
||||
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerNamed("digitsAfterDecimal", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("principal", element)) {
|
||||
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("inArrearsTolerance", element)) {
|
||||
final BigDecimal inArrearsTolerance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) {
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("numberOfRepayments", element)) {
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("repaymentEvery", element)) {
|
||||
final Integer repaymentEvery = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
|
||||
baseDataValidator.reset().parameter("repaymentEvery").value(repaymentEvery).notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("repaymentFrequencyType", element)) {
|
||||
final Integer repaymentFrequencyType = fromApiJsonHelper.extractIntegerNamed("repaymentFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("transactionProcessingStrategyId", element)) {
|
||||
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestRateFrequencyType", element)) {
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("amortizationType", element)) {
|
||||
final Integer amortizationType = fromApiJsonHelper.extractIntegerNamed("amortizationType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("amortizationType").value(amortizationType).notNull().inMinMaxRange(0, 1);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestType", element)) {
|
||||
final Integer interestType = fromApiJsonHelper.extractIntegerNamed("interestType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestType").value(interestType).notNull().inMinMaxRange(0, 1);
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestCalculationPeriodType", element)) {
|
||||
final Integer interestCalculationPeriodType = fromApiJsonHelper.extractIntegerNamed("interestCalculationPeriodType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestCalculationPeriodType").value(interestCalculationPeriodType).notNull()
|
||||
.inMinMaxRange(0, 1);
|
||||
}
|
||||
|
||||
// FIXME - KW - accounting here doesnt allow me to just update one part
|
||||
// of cash based or accrual based settings?
|
||||
// accounting related data validation
|
||||
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingType").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
if (isCashBased(accountingRuleType) || isAccrualBased(accountingRuleType)) {
|
||||
|
||||
final Long fundAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue()).value(fundAccountId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final Long loanPortfolioAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOAN_PORTFOLIO.getValue()).value(loanPortfolioAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (isAccrualBased(accountingRuleType)) {
|
||||
|
||||
final Long receivableInterestAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue())
|
||||
.value(receivableInterestAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long receivableFeeAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue()).value(receivableFeeAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long receivablePenaltyAccountId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue())
|
||||
.value(receivablePenaltyAccountId).notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (isCashBased(accountingRuleType) || isAccrualBased(accountingRuleType)) {
|
||||
final Long incomeFromInterestId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue()).value(incomeFromInterestId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromFeeId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = fromApiJsonHelper.extractLongNamed(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue()).value(writeOffAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private boolean isCashBased(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
private boolean isAccrualBased(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -6,11 +6,11 @@ import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
|
||||
|
||||
public interface LoanProductReadPlatformService {
|
||||
|
||||
Collection<LoanProductData> retrieveAllLoanProducts();
|
||||
Collection<LoanProductData> retrieveAllLoanProducts();
|
||||
|
||||
Collection<LoanProductData> retrieveAllLoanProductsForLookup();
|
||||
Collection<LoanProductData> retrieveAllLoanProductsForLookup();
|
||||
|
||||
LoanProductData retrieveLoanProduct(Long productId);
|
||||
LoanProductData retrieveLoanProduct(Long productId);
|
||||
|
||||
LoanProductData retrieveNewLoanProductDetails();
|
||||
LoanProductData retrieveNewLoanProductDetails();
|
||||
}
|
||||
+29
-22
@@ -19,7 +19,6 @@ import org.mifosplatform.portfolio.fund.exception.FundNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
@@ -65,24 +64,29 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanProductCommand loanProductCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
|
||||
loanProductCommand.validateForCreate();
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
|
||||
// associating fund with loan product at creation is optional for now.
|
||||
final Fund fund = findFundByIdIfProvided(command.longValueOfParameterNamed("fundId"));
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command
|
||||
.longValueOfParameterNamed("transactionProcessingStrategyId"));
|
||||
final Set<Charge> charges = this.assembleSetOfCharges(command, null);
|
||||
|
||||
final Long transactionProcessingStrategyId = command.longValueOfParameterNamed("transactionProcessingStrategyId");
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(transactionProcessingStrategyId);
|
||||
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
final Set<Charge> charges = this.assembleSetOfCharges(command, currencyCode);
|
||||
|
||||
final LoanProduct loanproduct = LoanProduct.assembleFromJson(fund, loanTransactionProcessingStrategy, charges, command,
|
||||
this.aprCalculator);
|
||||
|
||||
this.loanProductRepository.save(loanproduct);
|
||||
|
||||
//save accounting mappings
|
||||
accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), loanProductCommand);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanproduct.getId()).build();
|
||||
// save accounting mappings
|
||||
accountMappingWritePlatformService.createLoanProductToGLAccountMapping(loanproduct.getId(), command);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanproduct.getId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
||||
@@ -108,13 +112,12 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
public CommandProcessingResult updateLoanProduct(final Long loanProductId, final JsonCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanProductCommand loanProductCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
|
||||
loanProductCommand.validateForUpdate();
|
||||
|
||||
this.fromApiJsonDeserializer.validateForUpdate(command.json());
|
||||
|
||||
final LoanProduct product = this.loanProductRepository.findOne(loanProductId);
|
||||
if (product == null) { throw new LoanProductNotFoundException(loanProductId); }
|
||||
|
||||
|
||||
final Map<String, Object> changes = product.update(command, this.aprCalculator);
|
||||
|
||||
// associating fund with loan product at creation is optional for now.
|
||||
@@ -129,23 +132,27 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(transactionProcessingStrategyId);
|
||||
product.update(loanTransactionProcessingStrategy);
|
||||
}
|
||||
|
||||
|
||||
if (changes.containsKey("charges")) {
|
||||
final Set<Charge> charges = this.assembleSetOfCharges(command, product.getCurrency().getCode());
|
||||
product.update(charges);
|
||||
}
|
||||
|
||||
|
||||
// accounting related changes
|
||||
if (loanProductCommand.getAccountingType() != null) {
|
||||
boolean accountingTypeChanged = changes.containsKey("accountingType");
|
||||
accountMappingWritePlatformService.updateLoanProductToGLAccountMapping(product.getId(), loanProductCommand, accountingTypeChanged);
|
||||
boolean accountingTypeChanged = changes.containsKey("accountingType");
|
||||
if (accountingTypeChanged) {
|
||||
accountMappingWritePlatformService.updateLoanProductToGLAccountMapping(product.getId(), command, accountingTypeChanged);
|
||||
}
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.loanProductRepository.save(product);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanProductId).with(changes).build();
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanProductId) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private Set<Charge> assembleSetOfCharges(final JsonCommand command, final String currencyCode) {
|
||||
@@ -176,5 +183,5 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
return charges;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user