FINERACT-1783: Customizeable LoanRepaymentScheduleTransactionProcessor
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
f2756b25bb
commit
fc895fce05
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract COB Loan'
|
||||
|
||||
group = 'com.acme.fineract.cob'
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-cob-loan'
|
||||
archivesBaseName = 'acme-fineract-loan-cob'
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
+6
-2
@@ -31,6 +31,10 @@ import org.springframework.stereotype.Component;
|
||||
@RequiredArgsConstructor
|
||||
public class AcmeNoopBusinessStep implements LoanCOBBusinessStep, InitializingBean {
|
||||
|
||||
private static final String ENUM_STYLED_NAME = "ACME_LOAN_NOOP";
|
||||
|
||||
private static final String HUMAN_READABLE_NAME = "ACME Loan Noop";
|
||||
|
||||
// NOTE: just to demonstrate that dependency injection is working
|
||||
private final LoanAccountDomainService loanAccountDomainService;
|
||||
|
||||
@@ -46,11 +50,11 @@ public class AcmeNoopBusinessStep implements LoanCOBBusinessStep, InitializingBe
|
||||
|
||||
@Override
|
||||
public String getEnumStyledName() {
|
||||
return "ACME_LOAN_NOOP";
|
||||
return ENUM_STYLED_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHumanReadableName() {
|
||||
return "ACME Loan Noop";
|
||||
return HUMAN_READABLE_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="acme" id="1">
|
||||
<insert tableName="m_batch_business_steps">
|
||||
<column name="job_name" value="LOAN_CLOSE_OF_BUSINESS"/>
|
||||
<column name="step_name" value="ACME_LOAN_NOOP"/>
|
||||
<column name="step_order" value="5"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract Loan Transaction Processors'
|
||||
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-loan-processor'
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
+2
-8
@@ -16,13 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface LoanTransactionProcessingStrategyRepository
|
||||
extends JpaRepository<LoanTransactionProcessingStrategy, Long>, JpaSpecificationExecutor<LoanTransactionProcessingStrategy> {
|
||||
// no added behaviour
|
||||
dependencies {
|
||||
implementation(project(':fineract-provider'))
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.acme.fineract.loan.processor;
|
||||
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AcmeLoanRepaymentScheduleTransactionProcessor extends FineractStyleLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "acme-standard-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "ACME Corp.: standard loan transaction processing strategy";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
description = 'ACME Corp.: Fineract COB Starter'
|
||||
|
||||
group = 'com.acme.fineract.cob'
|
||||
group = 'com.acme.fineract'
|
||||
|
||||
archivesBaseName = 'acme-fineract-cob-starter'
|
||||
archivesBaseName = 'acme-fineract-loan-starter'
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
implementation(project(':fineract-provider'))
|
||||
implementation(project(':custom:acme:loan:cob'))
|
||||
implementation(project(':custom:acme:loan:processor'))
|
||||
implementation('org.springframework.boot:spring-boot-starter')
|
||||
testImplementation(project(':fineract-provider'))
|
||||
testImplementation('org.springframework.boot:spring-boot-starter-jdbc')
|
||||
|
||||
+16
-2
@@ -18,11 +18,25 @@
|
||||
*/
|
||||
package com.acme.fineract.loan.starter;
|
||||
|
||||
import com.acme.fineract.loan.processor.AcmeLoanRepaymentScheduleTransactionProcessor;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScans;
|
||||
|
||||
@AutoConfiguration
|
||||
@ComponentScan("com.acme.fineract.loan.cob")
|
||||
@ComponentScans({ @ComponentScan("com.acme.fineract.loan.cob"), @ComponentScan("com.acme.fineract.loan.processor") })
|
||||
@ConditionalOnProperty("acme.loan.enabled")
|
||||
public class AcmeLoanAutoConfiguration {}
|
||||
public class AcmeLoanAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory(
|
||||
AcmeLoanRepaymentScheduleTransactionProcessor defaultLoanRepaymentScheduleTransactionProcessor,
|
||||
List<LoanRepaymentScheduleTransactionProcessor> processors) {
|
||||
return new LoanRepaymentScheduleTransactionProcessorFactory(defaultLoanRepaymentScheduleTransactionProcessor, processors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ jib {
|
||||
}
|
||||
// NOTE: other custom dependencies
|
||||
implementation 'org.mariadb.jdbc:mariadb-java-client:3.0.7'
|
||||
implementation 'mysql:mysql-connector-java:8.0.30'
|
||||
implementation 'mysql:mysql-connector-java:8.0.31'
|
||||
implementation 'org.postgresql:postgresql:42.5.0'
|
||||
annotationProcessor('org.springframework.boot:spring-boot-autoconfigure-processor')
|
||||
annotationProcessor('org.springframework.boot:spring-boot-configuration-processor')
|
||||
|
||||
@@ -341,10 +341,10 @@
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "transactionProcessingStrategyId",
|
||||
"name": "transactionProcessingStrategyCode",
|
||||
"type": [
|
||||
"null",
|
||||
"long"
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -341,10 +341,10 @@
|
||||
},
|
||||
{
|
||||
"default": null,
|
||||
"name": "transactionProcessingStrategyId",
|
||||
"name": "transactionProcessingStrategyCode",
|
||||
"type": [
|
||||
"null",
|
||||
"long"
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1011,7 +1011,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -1027,7 +1026,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -1506,9 +1504,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1770,36 +1766,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (1,'mifos-standard-strategy','Mifos style',NULL,NULL,NULL,NULL),(2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL),(3,'creocore-strategy','Creocore',NULL,NULL,NULL,NULL),(4,'rbi-india-strategy','RBI (India)',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -1012,7 +1012,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -1028,7 +1027,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -1507,9 +1505,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1771,36 +1767,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (1,'mifos-standard-strategy','Mifos style',NULL,NULL,NULL,NULL),(2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL),(3,'creocore-strategy','Creocore',NULL,NULL,NULL,NULL),(4,'rbi-india-strategy','RBI (India)',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -930,7 +930,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -946,7 +945,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -1399,7 +1397,7 @@ CREATE TABLE `m_portfolio_command_source` (
|
||||
|
||||
LOCK TABLES `m_portfolio_command_source` WRITE;
|
||||
/*!40000 ALTER TABLE `m_portfolio_command_source` DISABLE KEYS */;
|
||||
INSERT INTO `m_portfolio_command_source` VALUES (1,'CREATE','CLIENT',2,NULL,1,NULL,NULL,'/clients/template',1,NULL,'{\"officeId\":\"2\",\"firstname\":\"Test\",\"middlename\":\"\",\"lastname\":\"One\",\"fullname\":\"\",\"externalId\":\"\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"joinedDate\":\"2011-02-01\"}',1,'2013-04-05 12:38:05',NULL,NULL,1),(2,'CREATE','LOAN',2,NULL,1,1,NULL,'/loans',1,NULL,'{\"clientId\":\"1\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"productId\":\"1\",\"loanOfficerId\":\"2\",\"submittedOnDate\":\"2011-04-01\",\"loanPurposeId\":\"25\",\"principal\":\"1,000,000.00\",\"loanTermFrequency\":\"12\",\"loanTermFrequencyType\":\"2\",\"numberOfRepayments\":\"12\",\"repaymentEvery\":\"1\",\"repaymentFrequencyType\":\"2\",\"interestRatePerPeriod\":\"24\",\"interestRateFrequencyType\":\"3\",\"expectedDisbursementDate\":\"2011-04-01\",\"amortizationType\":\"1\",\"interestType\":\"1\",\"interestCalculationPeriodType\":\"1\",\"inArrearsTolerance\":\"\",\"transactionProcessingStrategyId\":\"2\",\"repaymentsStartingFromDate\":\"\",\"interestChargedFromDate\":\"\",\"charges\":[{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-05-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-06-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-07-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-08-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-09-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-10-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-11-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-12-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-01-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-02-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-03-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-04-01\"}],\"collateral\":[{\"id\":\"\",\"type\":\"23\",\"description\":\" small description.\",\"value\":\"\"}]}',1,'2013-04-05 12:41:57',NULL,NULL,1),(3,'APPROVE','LOAN',2,NULL,1,1,NULL,'/loans/1',1,NULL,'{\"status\":{\"id\":200,\"code\":\"loanStatusType.approved\",\"value\":\"Approved\",\"pendingApproval\":false,\"waitingForDisbursal\":true,\"active\":false,\"closedObligationsMet\":false,\"closedWrittenOff\":false,\"closedRescheduled\":false,\"closed\":false,\"overpaid\":false},\"locale\":\"en\",\"dateFormat\":\"yyyy-MM-dd\",\"approvedOnDate\":\"2011-04-01\"}',1,'2013-04-05 12:42:09',NULL,NULL,1);
|
||||
INSERT INTO `m_portfolio_command_source` VALUES (1,'CREATE','CLIENT',2,NULL,1,NULL,NULL,'/clients/template',1,NULL,'{\"officeId\":\"2\",\"firstname\":\"Test\",\"middlename\":\"\",\"lastname\":\"One\",\"fullname\":\"\",\"externalId\":\"\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"joinedDate\":\"2011-02-01\"}',1,'2013-04-05 12:38:05',NULL,NULL,1),(2,'CREATE','LOAN',2,NULL,1,1,NULL,'/loans',1,NULL,'{\"clientId\":\"1\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"productId\":\"1\",\"loanOfficerId\":\"2\",\"submittedOnDate\":\"2011-04-01\",\"loanPurposeId\":\"25\",\"principal\":\"1,000,000.00\",\"loanTermFrequency\":\"12\",\"loanTermFrequencyType\":\"2\",\"numberOfRepayments\":\"12\",\"repaymentEvery\":\"1\",\"repaymentFrequencyType\":\"2\",\"interestRatePerPeriod\":\"24\",\"interestRateFrequencyType\":\"3\",\"expectedDisbursementDate\":\"2011-04-01\",\"amortizationType\":\"1\",\"interestType\":\"1\",\"interestCalculationPeriodType\":\"1\",\"inArrearsTolerance\":\"\",\"transactionProcessingStrategy\":\"heavensfamily-strategy\",\"repaymentsStartingFromDate\":\"\",\"interestChargedFromDate\":\"\",\"charges\":[{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-05-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-06-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-07-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-08-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-09-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-10-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-11-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-12-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-01-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-02-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-03-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-04-01\"}],\"collateral\":[{\"id\":\"\",\"type\":\"23\",\"description\":\" small description.\",\"value\":\"\"}]}',1,'2013-04-05 12:41:57',NULL,NULL,1),(3,'APPROVE','LOAN',2,NULL,1,1,NULL,'/loans/1',1,NULL,'{\"status\":{\"id\":200,\"code\":\"loanStatusType.approved\",\"value\":\"Approved\",\"pendingApproval\":false,\"waitingForDisbursal\":true,\"active\":false,\"closedObligationsMet\":false,\"closedWrittenOff\":false,\"closedRescheduled\":false,\"closed\":false,\"overpaid\":false},\"locale\":\"en\",\"dateFormat\":\"yyyy-MM-dd\",\"approvedOnDate\":\"2011-04-01\"}',1,'2013-04-05 12:42:09',NULL,NULL,1);
|
||||
/*!40000 ALTER TABLE `m_portfolio_command_source` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
@@ -1435,9 +1433,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1709,36 +1705,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -930,7 +930,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -946,7 +945,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -1399,7 +1397,7 @@ CREATE TABLE `m_portfolio_command_source` (
|
||||
|
||||
LOCK TABLES `m_portfolio_command_source` WRITE;
|
||||
/*!40000 ALTER TABLE `m_portfolio_command_source` DISABLE KEYS */;
|
||||
INSERT INTO `m_portfolio_command_source` VALUES (1,'CREATE','CLIENT',2,NULL,1,NULL,NULL,'/clients/template',1,NULL,'{\"officeId\":\"2\",\"firstname\":\"Test\",\"middlename\":\"\",\"lastname\":\"One\",\"fullname\":\"\",\"externalId\":\"\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"joinedDate\":\"2011-02-01\"}',1,'2013-04-05 12:38:05',NULL,NULL,1),(2,'CREATE','LOAN',2,NULL,1,1,NULL,'/loans',1,NULL,'{\"clientId\":\"1\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"productId\":\"1\",\"loanOfficerId\":\"2\",\"submittedOnDate\":\"2011-04-01\",\"loanPurposeId\":\"25\",\"principal\":\"1,000,000.00\",\"loanTermFrequency\":\"12\",\"loanTermFrequencyType\":\"2\",\"numberOfRepayments\":\"12\",\"repaymentEvery\":\"1\",\"repaymentFrequencyType\":\"2\",\"interestRatePerPeriod\":\"24\",\"interestRateFrequencyType\":\"3\",\"expectedDisbursementDate\":\"2011-04-01\",\"amortizationType\":\"1\",\"interestType\":\"1\",\"interestCalculationPeriodType\":\"1\",\"inArrearsTolerance\":\"\",\"transactionProcessingStrategyId\":\"2\",\"repaymentsStartingFromDate\":\"\",\"interestChargedFromDate\":\"\",\"charges\":[{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-05-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-06-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-07-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-08-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-09-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-10-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-11-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-12-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-01-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-02-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-03-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-04-01\"}],\"collateral\":[{\"id\":\"\",\"type\":\"23\",\"description\":\" small description.\",\"value\":\"\"}]}',1,'2013-04-05 12:41:57',NULL,NULL,1),(3,'APPROVE','LOAN',2,NULL,1,1,NULL,'/loans/1',1,NULL,'{\"status\":{\"id\":200,\"code\":\"loanStatusType.approved\",\"value\":\"Approved\",\"pendingApproval\":false,\"waitingForDisbursal\":true,\"active\":false,\"closedObligationsMet\":false,\"closedWrittenOff\":false,\"closedRescheduled\":false,\"closed\":false,\"overpaid\":false},\"locale\":\"en\",\"dateFormat\":\"yyyy-MM-dd\",\"approvedOnDate\":\"2011-04-01\"}',1,'2013-04-05 12:42:09',NULL,NULL,1);
|
||||
INSERT INTO `m_portfolio_command_source` VALUES (1,'CREATE','CLIENT',2,NULL,1,NULL,NULL,'/clients/template',1,NULL,'{\"officeId\":\"2\",\"firstname\":\"Test\",\"middlename\":\"\",\"lastname\":\"One\",\"fullname\":\"\",\"externalId\":\"\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"joinedDate\":\"2011-02-01\"}',1,'2013-04-05 12:38:05',NULL,NULL,1),(2,'CREATE','LOAN',2,NULL,1,1,NULL,'/loans',1,NULL,'{\"clientId\":\"1\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"productId\":\"1\",\"loanOfficerId\":\"2\",\"submittedOnDate\":\"2011-04-01\",\"loanPurposeId\":\"25\",\"principal\":\"1,000,000.00\",\"loanTermFrequency\":\"12\",\"loanTermFrequencyType\":\"2\",\"numberOfRepayments\":\"12\",\"repaymentEvery\":\"1\",\"repaymentFrequencyType\":\"2\",\"interestRatePerPeriod\":\"24\",\"interestRateFrequencyType\":\"3\",\"expectedDisbursementDate\":\"2011-04-01\",\"amortizationType\":\"1\",\"interestType\":\"1\",\"interestCalculationPeriodType\":\"1\",\"inArrearsTolerance\":\"\",\"transactionProcessingStrategy\":\"heavensfamily-strategy\",\"repaymentsStartingFromDate\":\"\",\"interestChargedFromDate\":\"\",\"charges\":[{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-05-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-06-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-07-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-08-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-09-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-10-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-11-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-12-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-01-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-02-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-03-01\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-04-01\"}],\"collateral\":[{\"id\":\"\",\"type\":\"23\",\"description\":\" small description.\",\"value\":\"\"}]}',1,'2013-04-05 12:41:57',NULL,NULL,1),(3,'APPROVE','LOAN',2,NULL,1,1,NULL,'/loans/1',1,NULL,'{\"status\":{\"id\":200,\"code\":\"loanStatusType.approved\",\"value\":\"Approved\",\"pendingApproval\":false,\"waitingForDisbursal\":true,\"active\":false,\"closedObligationsMet\":false,\"closedWrittenOff\":false,\"closedRescheduled\":false,\"closed\":false,\"overpaid\":false},\"locale\":\"en\",\"dateFormat\":\"yyyy-MM-dd\",\"approvedOnDate\":\"2011-04-01\"}',1,'2013-04-05 12:42:09',NULL,NULL,1);
|
||||
/*!40000 ALTER TABLE `m_portfolio_command_source` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
@@ -1435,9 +1433,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1709,36 +1705,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
-- under the License.
|
||||
--
|
||||
|
||||
DELETE FROM `ref_loan_transaction_processing_strategy` WHERE id in (1, 3, 4);
|
||||
|
||||
INSERT INTO `m_code` (`code_name`, `is_system_defined`)
|
||||
VALUES
|
||||
('FieldOfEmployment', '0'),
|
||||
|
||||
@@ -1012,7 +1012,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -1028,7 +1027,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -1507,9 +1505,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1771,36 +1767,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (1,'mifos-standard-strategy','Mifos style',NULL,NULL,NULL,NULL),(2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL),(3,'creocore-strategy','Creocore',NULL,NULL,NULL,NULL),(4,'rbi-india-strategy','RBI (India)',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -859,7 +859,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loan_guarantor` (`guarantor_id`),
|
||||
@@ -867,7 +866,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK7C885877240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FKB6F935D87179A0CB` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKB6F935D8C8D4B434` FOREIGN KEY (`product_id`) REFERENCES `m_product_loan` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `m_loan_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
@@ -1343,9 +1341,7 @@ CREATE TABLE `m_product_loan` (
|
||||
`loan_transaction_strategy_id` BIGINT DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -1687,36 +1683,6 @@ INSERT INTO `r_enum_value` VALUES ('amortization_method_enum',0,'Equal principle
|
||||
/*!40000 ALTER TABLE `r_enum_value` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = UTF8MB4 */;
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=UTF8MB4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `ref_loan_transaction_processing_strategy`
|
||||
--
|
||||
|
||||
LOCK TABLES `ref_loan_transaction_processing_strategy` WRITE;
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` VALUES (1,'mifos-standard-strategy','Mifos style',NULL,NULL,NULL,NULL),(2,'heavensfamily-strategy','Heavensfamily',NULL,NULL,NULL,NULL),(3,'creocore-strategy','Creocore',NULL,NULL,NULL,NULL),(4,'rbi-india-strategy','RBI (India)',NULL,NULL,NULL,NULL);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `rpt_sequence`
|
||||
--
|
||||
|
||||
@@ -68,7 +68,6 @@ DROP TABLE IF EXISTS `m_savings_account`;
|
||||
DROP TABLE IF EXISTS `m_savings_account_transaction`;
|
||||
DROP TABLE IF EXISTS `m_savings_product`;
|
||||
DROP TABLE IF EXISTS `m_staff`;
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
DROP TABLE IF EXISTS `x_registered_table`;
|
||||
|
||||
-- drop reporting related tables
|
||||
@@ -102,18 +101,6 @@ CREATE TABLE `m_organisation_currency` (
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
CREATE TABLE `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`createdby_id` BIGINT DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` BIGINT DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
CREATE TABLE `c_configuration` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) DEFAULT NULL,
|
||||
@@ -482,9 +469,7 @@ CREATE TABLE `m_product_loan` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unq_name` (`name`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
CREATE TABLE `m_product_loan_charge` (
|
||||
@@ -575,7 +560,6 @@ CREATE TABLE `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -591,7 +575,6 @@ CREATE TABLE `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
|
||||
@@ -19,14 +19,6 @@
|
||||
|
||||
-- currency symbols may not apply through command line on windows so use a different client like mysql workbench
|
||||
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy`
|
||||
(`id`,`code`,`name`)
|
||||
VALUES
|
||||
(1, 'mifos-standard-strategy', 'Mifos style'),
|
||||
(2, 'heavensfamily-strategy', 'Heavensfamily'),
|
||||
(3, 'creocore-strategy', 'Creocore'),
|
||||
(4, 'rbi-india-strategy', 'RBI (India)');
|
||||
|
||||
INSERT INTO `c_configuration`
|
||||
(`name`, `enabled`)
|
||||
VALUES
|
||||
|
||||
@@ -1,91 +1,5 @@
|
||||
= Modules
|
||||
|
||||
NOTE: Currently modules are a proof of concept feature in Fineract.
|
||||
We are currently working towards a fully modular codebase and will publish more here when we are ready.
|
||||
|
||||
== Custom modules
|
||||
|
||||
Creating customizations for Fineract services is easy. The method described here will work both with our future module guidelines (aka "clean room" modules) and with the intermediary solution we will put in place to avoid major refactorings.
|
||||
|
||||
The folder structure for modules is based on a convention that ensures that your extensions don't clash with Fineract's internals. This is to make sure that your downstream forks of Fineract are easy to sync. In the past we had all kinds of strategies to add custom code - including editing existing sources in `fineract-provider`. This is not recommended.
|
||||
|
||||
IMPORTANT: At the moment the only service(s) we prepared to be overridden/replaced are `org.apache.fineract.portfolio.note.service.NoteReadPlatformService` and `org.apache.fineract.portfolio.note.service.NoteWritePlatformService`. Please reach out on the developer mailing list if you need other services.
|
||||
|
||||
The recommended folder structure is very simple. If you follow this recommendation you'll get some additional benefits, e. g. you don't even have to edit `settings.gradle` to include your new custom modules. Your modules will also be automatically included in a custom Fineract Docker image build that you can use for your production deployments.
|
||||
|
||||
Let's assume your company/org is called "ACME Inc." and you are trying to (fully/partially) replace an existing Fineract service, let's say those in `org.apache.fineract.portfolio.note`. The recommended folder structure would then look something like this:
|
||||
|
||||
[plantuml, format=svg]
|
||||
----
|
||||
include::{diagramsdir}/custom-folder-structure.puml[]
|
||||
----
|
||||
|
||||
As soon as we can publish Fineract module JARs to Maven Central you'll have more freedom to setup your projects (including to setup separate Git repos). But for now please follow these instructions:
|
||||
|
||||
1. Create a folder under `custom` and name it according to your company/organisation (e. g. `acme` if your company is `ACME Inc.`); this way your custom modules can't clash even with other companies' modules
|
||||
2. Under your company folder create a folder for the `category` or `domain` your module is targeting; e. g. "loan", "client", "account" etc.
|
||||
3. Finally, setup `library` folders for the actual modules you want to create; usually that will be to replace/extend some existing service, so there could be a `service` folder, maybe even a `core` folder, e. g. if you want to add additional DTOs etc.; we have also an example for COB business steps
|
||||
4. Per `category`/`domain` you should have a `starter` library; means: a Spring Boot auto-configuration setup that makes including your module in Fineract easier ("hands-free"); the necessary parts for a auto-configuration library are a Spring Java configuration class (annotated with `@Configuration`) and a text file at `META-INF/spring.factories` in your starter resource folder:
|
||||
+
|
||||
[source,properties]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/starter/src/main/resources/META-INF/spring.factories[]
|
||||
----
|
||||
+
|
||||
Please make sure that your module libraries have proper `build.gradle` files:
|
||||
+
|
||||
[source,groovy]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/service/build.gradle[lines=19..]
|
||||
----
|
||||
+
|
||||
NOTE: You don't need to edit `settings.gradle` to add your modules/libraries. If you follow above convention they'll get included automatically.
|
||||
+
|
||||
5. The dependency.gradle file could look something like this:
|
||||
[source,groovy]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/service/dependencies.gradle[lines=19..]
|
||||
----
|
||||
|
||||
NOTE: We've included by default some basic and useful dependencies for all custom modules, like Slf4j, Lombok, the usual testing frameworks (JUnit, Cucumber, Mockito etc.)
|
||||
|
||||
IMPORTANT: Do not include your custom module in `fineract-provider`'s dependency.gradle file. This creates a circular dependency and will fail your build.
|
||||
|
||||
=== Database Migrations
|
||||
|
||||
If database migrations are needed as part of your customizations then you can add your own migration scripts. This is again based on conventions:
|
||||
|
||||
1. Create folders `db/custom-changelog` in one of your `resources` folders; we recommend using the resources folder in your starter library, but actually any of your custom libs will do.
|
||||
2. Under `db/custom-changelog` create an XML changelog file, e. g. `changelog-acme-note.xml`; you are free to choose a name for this file, but we recommend being consistent to avoid classpath conflicts.
|
||||
3. Under `db/custom-changelog` create a folder `parts` for your specific changelogs
|
||||
|
||||
[plantuml, format=svg]
|
||||
----
|
||||
include::{diagramsdir}/custom-db-migration-folder-structure.puml[]
|
||||
----
|
||||
|
||||
And here an example migration script:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/starter/src/main/resources/db/custom-changelog/0001_acme_note_initial.xml[lines=22..]
|
||||
----
|
||||
|
||||
IMPORTANT: By default custom database migration changelogs are executed in context `tenant_db`. That makes sure your changes will be applied to the tenant database (read: main database and not the tenant store database). In theory you could also target the tenant configuration database, but it's not recommended to do that.
|
||||
|
||||
=== Deployment
|
||||
|
||||
Custom modules (better: the JAR files) only need to be dropped in Fineract's `libs` folder if you run Fineract from the Spring Boot JAR file. Dynamic loading of external JARs is provided since Fineract version 1.5.0. For your convenience we've created a separate Docker image module that automatically includes your custom modules (see `custom/docker`). You can build this Docker image with
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
./gradlew :custom:docker:jibDockerBuild
|
||||
----
|
||||
|
||||
The Docker image with included custom modules is called `fineract-custom`.
|
||||
|
||||
NOTE: We'll provide soon a way to customize the Docker image parameters (image name, JVM implementation, JVM args, ports etc.).
|
||||
|
||||
|
||||
=== Outlook
|
||||
|
||||
If this *proof of concept* is accepted we could prepare Fineract's services to be replaceable. This approach works already very well even if we don't have proper JAR libraries published on Maven Central. It's an important goal to separate customized code from Fineract's internals to have soon real modules.
|
||||
NOTE: Even if we are not quite there yet with full modularity you can already create your own custom modules to extend Fineract. Please see chapter <<_custom_modules>>.
|
||||
@@ -0,0 +1,36 @@
|
||||
= Custom Business Steps
|
||||
|
||||
It very easy to add your own business steps to Fineract's default steps:
|
||||
|
||||
1. Create a custom module (e. g. `custom/acme/steps`, follow the instructions on how to create a custom module)
|
||||
2. Create a class that implements interace `org.apache.fineract.cob.COBBusinessStep`
|
||||
3. Provide the custom database migration to add the necessary information about your business step in table `m_batch_business_steps`
|
||||
|
||||
.Business Step Interface
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/cob/COBBusinessStep.java[lines=19..]
|
||||
----
|
||||
|
||||
== Business Step Implementation
|
||||
|
||||
.Custom Business Step Implementation Example
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/custom/acme/loan/cob/src/main/java/com/acme/fineract/loan/cob/AcmeNoopBusinessStep.java[lines=19..]
|
||||
----
|
||||
|
||||
As you can see this implementation is very simple and doesn't do much. There are some simple conventions though that you should follow implementing your own business steps:
|
||||
|
||||
1. Make sure the value returned by method `getEnumStyledName()` is unique; it's a good idea to choose a prefix that reflects the name of your organization (in this example `ACME_`)
|
||||
2. You have more freedom for the value returned by `getHumanReadableName()`, but it's a good idea to keep this value as unique as possible
|
||||
|
||||
== Business Step Database Migration
|
||||
|
||||
.Business Step Database Migration Example
|
||||
[source,xml]
|
||||
----
|
||||
include::{rootdir}/custom/acme/loan/cob/src/main/resources/db/custom-changelog/0001_acme_loan_cob.xml[lines=22..]
|
||||
----
|
||||
|
||||
NOTE: See also chapter about batch jobs in this documentation.
|
||||
@@ -0,0 +1,21 @@
|
||||
= Custom Database Migration
|
||||
|
||||
If database migrations are needed as part of your customizations then you can add your own migration scripts. This is again based on conventions:
|
||||
|
||||
1. Create folders `db/custom-changelog` in one of your `resources` folders; we recommend using the resources folder in your starter library, but actually any of your custom libs will do.
|
||||
2. Under `db/custom-changelog` create an XML changelog file, e. g. `changelog-acme-note.xml`; you are free to choose a name for this file, but we recommend being consistent to avoid classpath conflicts.
|
||||
3. Under `db/custom-changelog` create a folder `parts` for your specific changelogs
|
||||
|
||||
[plantuml, format=svg]
|
||||
----
|
||||
include::{diagramsdir}/custom-db-migration-folder-structure.puml[]
|
||||
----
|
||||
|
||||
And here an example migration script:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/starter/src/main/resources/db/custom-changelog/0001_acme_note_initial.xml[lines=22..]
|
||||
----
|
||||
|
||||
IMPORTANT: By default, custom database migration changelogs are executed in context `tenant_db`. That makes sure your changes will be applied to the tenant database (read: main database and not the tenant store database). In theory you could also target the tenant configuration database, but it's not recommended to do that.
|
||||
@@ -0,0 +1,12 @@
|
||||
= Deploying Custom Modules
|
||||
|
||||
Custom modules (better: the JAR files) only need to be dropped in Fineract's `libs` folder if you run Fineract from the Spring Boot JAR file. Dynamic loading of external JARs is provided since Fineract version 1.5.0. For your convenience we've created a separate Docker image module that automatically includes your custom modules (see `custom/docker`). You can build this Docker image with
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
./gradlew :custom:docker:jibDockerBuild
|
||||
----
|
||||
|
||||
The Docker image with included custom modules is called `fineract-custom`.
|
||||
|
||||
NOTE: We'll provide soon a way to customize the Docker image parameters (image name, JVM implementation, JVM args, ports etc.).
|
||||
@@ -0,0 +1,17 @@
|
||||
= Custom Modules
|
||||
|
||||
NOTE: Currently modules are a proof of concept feature in Fineract.
|
||||
|
||||
include::intro.adoc[leveloffset=+1]
|
||||
|
||||
include::service.adoc[leveloffset=+1]
|
||||
|
||||
include::business-step.adoc[leveloffset=+1]
|
||||
|
||||
include::loan-transaction-processor.adoc[leveloffset=+1]
|
||||
|
||||
include::database-migration.adoc[leveloffset=+1]
|
||||
|
||||
include::deployment.adoc[leveloffset=+1]
|
||||
|
||||
include::outlook.adoc[leveloffset=+1]
|
||||
@@ -0,0 +1,47 @@
|
||||
= Introduction
|
||||
|
||||
Creating customizations for Fineract services is easy. The method described here will work both with our future module guidelines (aka "clean room" modules) and with the intermediary solution we will put in place to avoid major refactorings.
|
||||
|
||||
The folder structure for modules is based on a convention that ensures that your extensions don't clash with Fineract's internals. This is to make sure that your downstream forks of Fineract are easy to sync. In the past we had all kinds of strategies to add custom code - including editing existing sources in `fineract-provider`. This is not recommended.
|
||||
|
||||
IMPORTANT: At the moment the only service(s) we prepared to be overridden/replaced are `org.apache.fineract.portfolio.note.service.NoteReadPlatformService` and `org.apache.fineract.portfolio.note.service.NoteWritePlatformService`. Please reach out on the developer mailing list if you need other services.
|
||||
|
||||
The recommended folder structure is very simple. If you follow this recommendation you'll get some additional benefits, e. g. you don't even have to edit `settings.gradle` to include your new custom modules. Your modules will also be automatically included in a custom Fineract Docker image build that you can use for your production deployments.
|
||||
|
||||
Let's assume your company/org is called "ACME Inc." and you are trying to (fully/partially) replace an existing Fineract service, let's say those in `org.apache.fineract.portfolio.note`. The recommended folder structure would then look something like this:
|
||||
|
||||
[plantuml, format=svg]
|
||||
----
|
||||
include::{diagramsdir}/custom-folder-structure.puml[]
|
||||
----
|
||||
|
||||
As soon as we can publish Fineract module JARs to Maven Central you'll have more freedom to setup your projects (including to setup separate Git repos). But for now please follow these instructions:
|
||||
|
||||
1. Create a folder under `custom` and name it according to your company/organisation (e. g. `acme` if your company is `ACME Inc.`); this way your custom modules can't clash even with other companies' modules
|
||||
2. Under your company folder create a folder for the `category` or `domain` your module is targeting; e. g. "loan", "client", "account" etc.
|
||||
3. Finally, setup `library` folders for the actual modules you want to create; usually that will be to replace/extend some existing service, so there could be a `service` folder, maybe even a `core` folder, e. g. if you want to add additional DTOs etc.; we have also an example for COB business steps
|
||||
4. Per `category`/`domain` you should have a `starter` library; means: a Spring Boot auto-configuration setup that makes including your module in Fineract easier ("hands-free"); the necessary parts for a auto-configuration library are a Spring Java configuration class (annotated with `@Configuration`) and a text file at `META-INF/spring.factories` in your starter resource folder:
|
||||
+
|
||||
[source,properties]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/starter/src/main/resources/META-INF/spring.factories[]
|
||||
----
|
||||
+
|
||||
Please make sure that your module libraries have proper `build.gradle` files:
|
||||
+
|
||||
[source,groovy]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/service/build.gradle[lines=19..]
|
||||
----
|
||||
+
|
||||
NOTE: You don't need to edit `settings.gradle` to add your modules/libraries. If you follow above convention they'll get included automatically.
|
||||
+
|
||||
5. The dependency.gradle file could look something like this:
|
||||
[source,groovy]
|
||||
----
|
||||
include::{rootdir}/custom/acme/note/service/dependencies.gradle[lines=19..]
|
||||
----
|
||||
|
||||
NOTE: We've included by default some basic and useful dependencies for all custom modules, like Slf4j, Lombok, the usual testing frameworks (JUnit, Cucumber, Mockito etc.)
|
||||
|
||||
IMPORTANT: Do not include your custom module in `fineract-provider`'s dependency.gradle file. This creates a circular dependency and will fail your build.
|
||||
@@ -0,0 +1,114 @@
|
||||
= Custom Loan Transaction Processors
|
||||
|
||||
Fineract has 7 built-in loan transaction processors:
|
||||
|
||||
1. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor`
|
||||
2. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.EarlyPaymentLoanRepaymentScheduleTransactionProcessor`
|
||||
3. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor`
|
||||
4. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.HeavensFamilyLoanRepaymentScheduleTransactionProcessor`
|
||||
5. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor`
|
||||
6. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor`
|
||||
7. `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor`
|
||||
|
||||
.Default Loan Transaction Processor configuration
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java[lines=38..80]
|
||||
----
|
||||
|
||||
All default processor implementations are enabled by default, but can also be prevented from being loaded into memory by a simple configuration in `application.properties`. Use the environment variables you see below in your Kubernetes and Docker Compose deployments to override the default behavior.
|
||||
|
||||
.Default Loan Transaction Processor Application Properties
|
||||
[source,properties]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/resources/application.properties[lines=64..70]
|
||||
----
|
||||
|
||||
== Implement Processors
|
||||
|
||||
.Loan Transaction Processor Interface
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/LoanRepaymentScheduleTransactionProcessor.java[lines=19..]
|
||||
----
|
||||
|
||||
.Custom Loan Transaction Processor Example
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/custom/acme/loan/processor/src/main/java/com/acme/fineract/loan/processor/AcmeLoanRepaymentScheduleTransactionProcessor.java[lines=19..]
|
||||
----
|
||||
|
||||
The example implementation doesn't do much. We are just overriding one of the default processor implementations `org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor` and give the custom processor it's own lookup code and name (descriptive text for display in UIs, e. g. when configuring a loan product). As usual it is a good idea to follow some simple conventions:
|
||||
|
||||
1. Make sure the value returned by `getCode()` is unique. Prefixing it with characters that reflect your organization name (here `acme-`) is a good idea.
|
||||
2. You have more freedom for the descriptive test returned by `getName()`, but it is still a good idea to keep the value unique to avoid confusion.
|
||||
|
||||
=== Method `getCode()`
|
||||
|
||||
Lookup value that is used to pick a loan transaction processor (see processor factory).
|
||||
|
||||
=== Method `getName()`
|
||||
|
||||
Descriptive text about the loan transaction processor that is mostly used in user interfaces.
|
||||
|
||||
=== Method `handleTransaction()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `handleWriteOff()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `handleRepaymentSchedule()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `isInterestFirstRepaymentScheduleTransactionProcessor()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `handleRefund()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `handleChargeback()`
|
||||
|
||||
TBD
|
||||
|
||||
=== Method `processTransactionsFromDerivedFields()`
|
||||
|
||||
TBD
|
||||
|
||||
== Override Processor Factory
|
||||
|
||||
The processor factory has no reference to any specific implementation of the loan transaction processor interface. All avaible implementations will be injected here (internal default and custom implementations). Processor instances can be looked up via method `determineProcessor()`. You can pass either the code of the processor or the processor's name to look it up. If a matching processor can't be found then the factory function will either return the default instance or fails with an exception depending on the configuration in `application.properties`.
|
||||
|
||||
IMPORTANT: It is preferable to use the processor code to lookup processor instances. Lookups via processor names are only done in the import service via Excel sheets (should be fixed).
|
||||
|
||||
.Loan Transaction Processor Factory Implementation
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleTransactionProcessorFactory.java[lines=19..]
|
||||
----
|
||||
|
||||
This is the default factory auto-configuration.
|
||||
|
||||
.Loan Transaction Processor Factory Auto-Configuration
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountAutoStarter.java[lines=81..87]
|
||||
----
|
||||
|
||||
If you need then you can override this, e.g. because you want to set a different default processor then you can do so in your custom module's auto-configuration.
|
||||
|
||||
.Custom Loan Transaction Processor Factory Auto-Configuration Example
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/custom/acme/loan/starter/src/main/java/com/acme/fineract/loan/starter/AcmeLoanAutoConfiguration.java[lines=36..41]
|
||||
----
|
||||
|
||||
.Processor Lookup Failure Configuration Property
|
||||
[source,properties]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/resources/application.properties[lines=71..71]
|
||||
----
|
||||
@@ -0,0 +1,3 @@
|
||||
= Outlook
|
||||
|
||||
If this *proof of concept* is accepted we could prepare more of Fineract's internal services to be replaceable. This approach works already very well even if we don't have proper JAR libraries published on Maven Central. It's an important goal to separate customized code from Fineract's internals to have soon real modules.
|
||||
@@ -0,0 +1,29 @@
|
||||
= Note Service
|
||||
|
||||
The Note service is responsible for ... TBD
|
||||
|
||||
NOTE: We chose the note service because it's interface is very simple and has not many cross dependencies.
|
||||
|
||||
== Interfaces
|
||||
|
||||
.Note Read Service Interface
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformService.java[lines=19..]
|
||||
----
|
||||
|
||||
.Note Write Service Interface
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/service/NoteReadPlatformService.java[lines=19..]
|
||||
----
|
||||
|
||||
== Auto Start Configuration
|
||||
|
||||
The rules to replace the Note services are very simple. If you provide an alternative implementation of the services then the default implementations will *not* be loaded.
|
||||
|
||||
.Note Auto Starter Configuration
|
||||
[source,java]
|
||||
----
|
||||
include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/portfolio/note/starter/NoteAutoConfiguration.java[lines=19..]
|
||||
----
|
||||
@@ -0,0 +1,5 @@
|
||||
= Custom Services
|
||||
|
||||
NOTE: We are still trying to figure out which internal services make most sense to be pluggable. Please join the discussion and let us know if you have a specific requirement.
|
||||
|
||||
include::service-note.adoc[leveloffset=+1]
|
||||
@@ -19,6 +19,7 @@
|
||||
| Michael Vorburger | mailto:mike@vorburger.ch[]
|
||||
| Aleksandar Vidakovic | mailto:aleks@apache.org[]
|
||||
| Arnold Galovics | mailto:arnold@apache.org[]
|
||||
| Adam Saghy | mailto:adamsaghy@gmail.com[]
|
||||
|===
|
||||
|
||||
//ifdef::backend-pdf[]
|
||||
@@ -34,7 +35,10 @@
|
||||
| Arnold Galovics | Database architecture section | 2022-03-11 | 1.7.0
|
||||
| Aleksandar Vidakovic | Module section | 2022-03-23 | 1.7.0
|
||||
| Aleksandar Vidakovic | Release section, file re-organisation | 2022-04-18 | 1.7.0
|
||||
| Arnold Galovics | Spring Batch | 2022-03-11 | 1.7.0
|
||||
| Aleksandar Vidakovic | AsciiDoc cheatsheet | 2022-05-09 | 1.7.0
|
||||
| Adam Saghy | Business data | 2022-06-13 | 1.7.0
|
||||
| Aleksandar Vidakovic | Custom modules and extensions | 2022-10-29 | 1.8.0
|
||||
|===
|
||||
|
||||
toc::[]
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
@@ -37,6 +37,8 @@ include::chapters/architecture/index.adoc[leveloffset=+1]
|
||||
|
||||
include::chapters/development/index.adoc[leveloffset=+1]
|
||||
|
||||
include::chapters/custom/index.adoc[leveloffset=+1]
|
||||
|
||||
include::chapters/security/index.adoc[leveloffset=+1]
|
||||
|
||||
include::chapters/testing/index.adoc[leveloffset=+1]
|
||||
|
||||
@@ -152,7 +152,7 @@ configurations {
|
||||
dependencies {
|
||||
driver 'org.mariadb.jdbc:mariadb-java-client:3.0.8'
|
||||
driver 'org.postgresql:postgresql:42.5.0'
|
||||
driver 'mysql:mysql-connector-java:8.0.30'
|
||||
driver 'mysql:mysql-connector-java:8.0.31'
|
||||
}
|
||||
|
||||
URLClassLoader loader = GroovyObject.class.classLoader
|
||||
|
||||
+22
-30
@@ -28,6 +28,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
@@ -48,28 +50,25 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanCollateralManagementData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class LoanImportHandler implements ImportHandler {
|
||||
|
||||
public static final String EMPTY_STR = "";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LoanImportHandler.class);
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public LoanImportHandler(final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
}
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
|
||||
@Override
|
||||
public Count process(final Workbook workbook, final String locale, final String dateFormat) {
|
||||
@@ -234,24 +233,17 @@ public class LoanImportHandler implements ImportHandler {
|
||||
if (ImportHandlerUtils.readAsDouble(LoanConstants.ARREARS_TOLERANCE_COL, row) != null) {
|
||||
arrearsTolerance = BigDecimal.valueOf(ImportHandlerUtils.readAsDouble(LoanConstants.ARREARS_TOLERANCE_COL, row));
|
||||
}
|
||||
String repaymentStrategy = ImportHandlerUtils.readAsString(LoanConstants.REPAYMENT_STRATEGY_COL, row);
|
||||
Long repaymentStrategyId = null;
|
||||
if (repaymentStrategy != null) {
|
||||
if (repaymentStrategy.equalsIgnoreCase("Penalties, Fees, Interest, Principal order")) {
|
||||
repaymentStrategyId = 1L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("HeavensFamily Unique")) {
|
||||
repaymentStrategyId = 2L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("Creocore Unique")) {
|
||||
repaymentStrategyId = 3L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("Overdue/Due Fee/Int,Principal")) {
|
||||
repaymentStrategyId = 4L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("Principal, Interest, Penalties, Fees Order")) {
|
||||
repaymentStrategyId = 5L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("Interest, Principal, Penalties, Fees Order")) {
|
||||
repaymentStrategyId = 6L;
|
||||
} else if (repaymentStrategy.equalsIgnoreCase("Early Repayment Strategy")) {
|
||||
repaymentStrategyId = 7L;
|
||||
}
|
||||
|
||||
String loanRepaymentScheduleTransactionProcessorStrategy = ImportHandlerUtils.readAsString(LoanConstants.REPAYMENT_STRATEGY_COL,
|
||||
row);
|
||||
|
||||
LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(loanRepaymentScheduleTransactionProcessorStrategy);
|
||||
|
||||
String repaymentStrategyCode = "mifos-standard-strategy";
|
||||
|
||||
if (loanRepaymentScheduleTransactionProcessor != null) {
|
||||
repaymentStrategyCode = loanRepaymentScheduleTransactionProcessor.getCode();
|
||||
}
|
||||
Integer graceOnPrincipalPayment = ImportHandlerUtils.readAsInt(LoanConstants.GRACE_ON_PRINCIPAL_PAYMENT_COL, row);
|
||||
Integer graceOnInterestPayment = ImportHandlerUtils.readAsInt(LoanConstants.GRACE_ON_INTEREST_PAYMENT_COL, row);
|
||||
@@ -355,7 +347,7 @@ public class LoanImportHandler implements ImportHandler {
|
||||
return LoanAccountData.importInstanceIndividual(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate,
|
||||
fundId, principal, numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTerm, loanTermFrequencyEnum,
|
||||
nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
|
||||
arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
|
||||
arrearsTolerance, repaymentStrategyCode, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
|
||||
interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, null, charges, linkAccountId, locale,
|
||||
dateFormat, loanCollateralManagementData);
|
||||
} else if (loanType.equals("jlg")) {
|
||||
@@ -364,7 +356,7 @@ public class LoanImportHandler implements ImportHandler {
|
||||
return LoanAccountData.importInstanceIndividual(loanTypeEnumOption, clientId, productId, loanOfficerId, submittedOnDate,
|
||||
fundId, principal, numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTerm, loanTermFrequencyEnum,
|
||||
nominalInterestRate, submittedOnDate, amortizationEnumOption, interestMethodEnum, interestCalculationPeriodEnum,
|
||||
arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
|
||||
arrearsTolerance, repaymentStrategyCode, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged,
|
||||
interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(), externalId, groupId, charges, linkAccountId, locale,
|
||||
dateFormat, null);
|
||||
} else {
|
||||
@@ -373,7 +365,7 @@ public class LoanImportHandler implements ImportHandler {
|
||||
return LoanAccountData.importInstanceGroup(loanTypeEnumOption, groupIdforGroupLoan, productId, loanOfficerId,
|
||||
submittedOnDate, fundId, principal, numberOfRepayments, repaidEvery, repaidEveryFrequencyEnums, loanTerm,
|
||||
loanTermFrequencyEnum, nominalInterestRate, amortizationEnumOption, interestMethodEnum,
|
||||
interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyId, graceOnPrincipalPayment,
|
||||
interestCalculationPeriodEnum, arrearsTolerance, repaymentStrategyCode, graceOnPrincipalPayment,
|
||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, firstRepaymentOnDate, row.getRowNum(),
|
||||
externalId, linkAccountId, locale, dateFormat);
|
||||
}
|
||||
@@ -426,7 +418,7 @@ public class LoanImportHandler implements ImportHandler {
|
||||
statusCell.setCellStyle(ImportHandlerUtils.getCellStyle(workbook, IndexedColors.LIGHT_GREEN));
|
||||
} catch (RuntimeException ex) {
|
||||
errorCount++;
|
||||
LOG.error("Problem occurred in importEntity function", ex);
|
||||
log.error("Problem occurred in importEntity function", ex);
|
||||
errorMessage = ImportHandlerUtils.getErrorMessage(ex);
|
||||
writeLoanErrorMessage(workbook, loanId, errorMessage, progressLevel, statusCell, errorReportCell, row);
|
||||
}
|
||||
|
||||
+2
-2
@@ -30,8 +30,8 @@ public class LoanComparatorByStatusActive implements Comparator<LoanAccountData>
|
||||
@Override
|
||||
public int compare(LoanAccountData o1, LoanAccountData o2) {
|
||||
|
||||
boolean isData1StatusActive = o1.getStatusStringValue().equals("Active");
|
||||
boolean isData2StatusActive = o2.getStatusStringValue().equals("Active");
|
||||
boolean isData1StatusActive = o1.getStatus() != null && o1.getStatus().getValue().equals("Active");
|
||||
boolean isData2StatusActive = o2.getStatus() != null && o2.getStatus().getValue().equals("Active");
|
||||
|
||||
// if both status active, these have the same rank
|
||||
if (isData1StatusActive && isData2StatusActive) {
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ public class GuarantorWorkbookPopulator extends AbstractWorkbookPopulator {
|
||||
}
|
||||
writeString(GuarantorConstants.LOOKUP_CLIENT_NAME_COL, row, loan.getClientName() + "(" + loan.getClientId() + ")");
|
||||
writeString(GuarantorConstants.LOOKUP_ACCOUNT_NO_COL, row,
|
||||
Long.parseLong(loan.getAccountNo()) + "-" + loan.getStatusStringValue());
|
||||
Long.parseLong(loan.getAccountNo()) + "-" + loan.getStatus().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -234,15 +234,15 @@ public class LoanRepaymentWorkbookPopulator extends AbstractWorkbookPopulator {
|
||||
row = loanRepaymentSheet.createRow(rowIndex++);
|
||||
writeString(LoanRepaymentConstants.LOOKUP_CLIENT_NAME_COL, row, loan.getClientName() + "(" + loan.getClientId() + ")");
|
||||
writeString(LoanRepaymentConstants.LOOKUP_CLIENT_EXTERNAL_ID, row, clientIdToClientExternalId.get(loan.getClientId()));
|
||||
writeString(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, row, loan.getAccountNo() + "-" + loan.getStatusStringValue());
|
||||
writeString(LoanRepaymentConstants.LOOKUP_ACCOUNT_NO_COL, row, loan.getAccountNo() + "-" + loan.getStatus().getValue());
|
||||
writeString(LoanRepaymentConstants.LOOKUP_PRODUCT_COL, row, loan.getLoanProductName());
|
||||
writeDouble(LoanRepaymentConstants.LOOKUP_PRINCIPAL_COL, row, loan.getPrincipal().doubleValue());
|
||||
if (loan.getTotalOutstandingAmount() != null) {
|
||||
writeBigDecimal(LoanRepaymentConstants.LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL, row, loan.getTotalOutstandingAmount());
|
||||
if (loan.getSummary() != null && loan.getSummary().getTotalOutstanding() != null) {
|
||||
writeBigDecimal(LoanRepaymentConstants.LOOKUP_TOTAL_OUTSTANDING_AMOUNT_COL, row, loan.getSummary().getTotalOutstanding());
|
||||
}
|
||||
if (loan.getDisbursementDate() != null) {
|
||||
writeDate(LoanRepaymentConstants.LOOKUP_LOAN_DISBURSEMENT_DATE_COL, row, outputFormat.format(loan.getDisbursementDate()),
|
||||
dateCellStyle, dateFormat);
|
||||
if (loan.getTimeline() != null && loan.getTimeline().getDisbursementDate() != null) {
|
||||
writeDate(LoanRepaymentConstants.LOOKUP_LOAN_DISBURSEMENT_DATE_COL, row,
|
||||
outputFormat.format(loan.getTimeline().getDisbursementDate()), dateCellStyle, dateFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -37,12 +37,14 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Primary
|
||||
@Component
|
||||
public class FromJsonHelper {
|
||||
|
||||
+6
@@ -22,9 +22,15 @@ import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
|
||||
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroMapperConfig;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@Mapper(config = AvroMapperConfig.class)
|
||||
public interface LoanAccountDataMapper {
|
||||
|
||||
// TODO: avoid prefix "is" in class attributes; I would recommend to fix this also in the Avro structures
|
||||
@Mapping(source = "loanProductLinkedToFloatingRate", target = "isLoanProductLinkedToFloatingRate")
|
||||
@Mapping(source = "floatingInterestRate", target = "isFloatingInterestRate")
|
||||
@Mapping(source = "topup", target = "isTopup")
|
||||
@Mapping(source = "interestRecalculationEnabled", target = "isInterestRecalculationEnabled")
|
||||
LoanAccountDataV1 map(LoanAccountData source);
|
||||
}
|
||||
|
||||
+44
-45
@@ -24,8 +24,9 @@ import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
|
||||
import org.apache.fineract.portfolio.calendar.domain.CalendarRemindBy;
|
||||
@@ -35,57 +36,55 @@ import org.apache.fineract.portfolio.calendar.service.CalendarEnumerations;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a Calendar.
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public final class CalendarData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final Long calendarInstanceId;
|
||||
private final Long entityId;
|
||||
private final EnumOptionData entityType;
|
||||
private Long id;
|
||||
private Long calendarInstanceId;
|
||||
private Long entityId;
|
||||
private EnumOptionData entityType;
|
||||
private String title;
|
||||
private final String description;
|
||||
private final String location;
|
||||
private final LocalDate startDate;
|
||||
private final LocalDate endDate;
|
||||
private final LocalTime meetingTime;
|
||||
private final Integer duration;
|
||||
private final EnumOptionData type;
|
||||
private final boolean repeating;
|
||||
private final String recurrence;
|
||||
private final EnumOptionData frequency;
|
||||
private final Integer interval;
|
||||
private final EnumOptionData repeatsOnDay;
|
||||
private final EnumOptionData repeatsOnNthDayOfMonth;
|
||||
private final EnumOptionData remindBy;
|
||||
private final Integer firstReminder;
|
||||
private final Integer secondReminder;
|
||||
private final Collection<LocalDate> recurringDates;
|
||||
private final Collection<LocalDate> nextTenRecurringDates;
|
||||
private final String humanReadable;
|
||||
private final LocalDate recentEligibleMeetingDate;
|
||||
private String description;
|
||||
private String location;
|
||||
private LocalDate startDate;
|
||||
private LocalDate endDate;
|
||||
private LocalTime meetingTime;
|
||||
private Integer duration;
|
||||
private EnumOptionData type;
|
||||
private boolean repeating;
|
||||
private String recurrence;
|
||||
private EnumOptionData frequency;
|
||||
private Integer interval;
|
||||
private EnumOptionData repeatsOnDay;
|
||||
private EnumOptionData repeatsOnNthDayOfMonth;
|
||||
private EnumOptionData remindBy;
|
||||
private Integer firstReminder;
|
||||
private Integer secondReminder;
|
||||
private Collection<LocalDate> recurringDates;
|
||||
private Collection<LocalDate> nextTenRecurringDates;
|
||||
private String humanReadable;
|
||||
private LocalDate recentEligibleMeetingDate;
|
||||
|
||||
private final OffsetDateTime createdDate;
|
||||
private final OffsetDateTime lastUpdatedDate;
|
||||
private final Long createdByUserId;
|
||||
private final String createdByUsername;
|
||||
private final Long lastUpdatedByUserId;
|
||||
private final String lastUpdatedByUsername;
|
||||
private final Integer repeatsOnDayOfMonth;
|
||||
private OffsetDateTime createdDate;
|
||||
private OffsetDateTime lastUpdatedDate;
|
||||
private Long createdByUserId;
|
||||
private String createdByUsername;
|
||||
private Long lastUpdatedByUserId;
|
||||
private String lastUpdatedByUsername;
|
||||
private Integer repeatsOnDayOfMonth;
|
||||
|
||||
// template related
|
||||
final List<EnumOptionData> entityTypeOptions;
|
||||
final List<EnumOptionData> calendarTypeOptions;
|
||||
final List<EnumOptionData> remindByOptions;
|
||||
final List<EnumOptionData> frequencyOptions;
|
||||
final List<EnumOptionData> repeatsOnDayOptions;
|
||||
final List<EnumOptionData> frequencyNthDayTypeOptions;
|
||||
private List<EnumOptionData> entityTypeOptions;
|
||||
private List<EnumOptionData> calendarTypeOptions;
|
||||
private List<EnumOptionData> remindByOptions;
|
||||
private List<EnumOptionData> frequencyOptions;
|
||||
private List<EnumOptionData> repeatsOnDayOptions;
|
||||
private List<EnumOptionData> frequencyNthDayTypeOptions;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
private Integer rowIndex;
|
||||
private String dateFormat;
|
||||
private String locale;
|
||||
private String centerId;
|
||||
|
||||
+2
-1
@@ -49,7 +49,7 @@ public interface LoanApiConstants {
|
||||
String rejectedOnDateParameterName = "rejectedOnDate";
|
||||
String withdrawnOnDateParameterName = "withdrawnOnDate";
|
||||
|
||||
String transactionProcessingStrategyIdParameterName = "transactionProcessingStrategyId";
|
||||
String transactionProcessingStrategyCodeParameterName = "transactionProcessingStrategyCode";
|
||||
String loanPurposeIdParameterName = "loanPurposeId";
|
||||
String loanOfficerIdParameterName = "loanOfficerId";
|
||||
String fundIdParameterName = "fundId";
|
||||
@@ -69,6 +69,7 @@ public interface LoanApiConstants {
|
||||
String interestCalculationPeriodTypeParameterName = "interestCalculationPeriodType";
|
||||
String interestTypeParameterName = "interestType";
|
||||
String amortizationTypeParameterName = "amortizationType";
|
||||
String amortizationTypeOptionsParameterName = "amortizationTypeOptions";
|
||||
String repaymentFrequencyTypeParameterName = "repaymentFrequencyType";
|
||||
String loanTermFrequencyTypeParameterName = "loanTermFrequencyType";
|
||||
String loanTermFrequencyParameterName = "loanTermFrequency";
|
||||
|
||||
+33
-16
@@ -32,6 +32,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -102,6 +103,7 @@ import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
import org.apache.fineract.portfolio.collateralmanagement.data.LoanCollateralResponseData;
|
||||
import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralManagementReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiResourceSwagger;
|
||||
import org.apache.fineract.portfolio.delinquency.data.LoanDelinquencyTagHistoryData;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||
@@ -121,6 +123,7 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.PaidInAdvanceData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTemplateTypeRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTemplateTypeException;
|
||||
@@ -191,7 +194,7 @@ import org.springframework.util.CollectionUtils;
|
||||
+ "Example Values: 0=Daily, 1=Same as repayment period\n" + "allowPartialPeriodInterestCalcualtion\n"
|
||||
+ "This value will be supported along with interestCalculationPeriodType as Same as repayment period to calculate interest for partial periods. Example: Interest charged from is 5th of April , Principal is 10000 and interest is 1% per month then the interest will be (10000 * 1%)* (25/30) , it calculates for the month first then calculates exact periods between start date and end date(can be a decimal)\n"
|
||||
+ "inArrearsTolerance\n" + "The amount that can be 'waived' at end of all loan payments because it is too small to worry about.\n"
|
||||
+ "This is also the tolerance amount assessed when determining if a loan is in arrears.\n" + "transactionProcessingStrategyId\n"
|
||||
+ "This is also the tolerance amount assessed when determining if a loan is in arrears.\n" + "transactionProcessingStrategyCode\n"
|
||||
+ "An enumeration that indicates the type of transaction processing strategy to be used. This relates to functionality that is also known as Payment Application Logic.\n"
|
||||
+ "A number of out of the box approaches exist, some are custom to specific MFIs, some are more general and indicate the order in which payments are processed.\n"
|
||||
+ "\n"
|
||||
@@ -213,7 +216,7 @@ public class LoansApiResource {
|
||||
"clientId", "group", "loanProductId", "loanProductName", "loanProductDescription", "isLoanProductLinkedToFloatingRate",
|
||||
"fundId", "fundName", "loanPurposeId", "loanPurposeName", "loanOfficerId", "loanOfficerName", "currency", "principal",
|
||||
"totalOverpaid", "inArrearsTolerance", "termFrequency", "termPeriodFrequencyType", "numberOfRepayments", "repaymentEvery",
|
||||
"interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType", "transactionProcessingStrategyId",
|
||||
"interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType", "transactionProcessingStrategyCode",
|
||||
"transactionProcessingStrategyName", "interestRateFrequencyType", "amortizationType", "interestType",
|
||||
"interestCalculationPeriodType", LoanProductConstants.ALLOW_PARTIAL_PERIOD_INTEREST_CALCUALTION_PARAM_NAME,
|
||||
"expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", "recurringMoratoriumOnPrincipalPeriods", "graceOnInterestPayment",
|
||||
@@ -345,11 +348,15 @@ public class LoansApiResource {
|
||||
if (templateType.equals("individual") || templateType.equals("jlg")) {
|
||||
|
||||
if (clientId == null) {
|
||||
newLoanAccount = newLoanAccount == null ? LoanAccountData.emptyTemplate() : newLoanAccount;
|
||||
newLoanAccount = newLoanAccount == null ? LoanAccountData.collateralTemplate(null) : newLoanAccount;
|
||||
} else {
|
||||
final LoanAccountData loanAccountClientDetails = this.loanReadPlatformService.retrieveClientDetailsTemplate(clientId);
|
||||
|
||||
officeId = loanAccountClientDetails.officeId();
|
||||
officeId = loanAccountClientDetails.getClientOfficeId();
|
||||
|
||||
if (officeId == null && loanAccountClientDetails.getGroup() != null) {
|
||||
officeId = loanAccountClientDetails.getGroup().getOfficeId();
|
||||
}
|
||||
newLoanAccount = newLoanAccount == null ? loanAccountClientDetails
|
||||
: LoanAccountData.populateClientDefaults(newLoanAccount, loanAccountClientDetails);
|
||||
}
|
||||
@@ -364,7 +371,7 @@ public class LoansApiResource {
|
||||
} else if (templateType.equals("group")) {
|
||||
|
||||
final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupDetailsTemplate(groupId);
|
||||
officeId = loanAccountGroupData.groupOfficeId();
|
||||
officeId = loanAccountGroupData.getGroup() != null ? loanAccountGroupData.getGroup().getOfficeId() : null;
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
|
||||
newLoanAccount = newLoanAccount == null ? loanAccountGroupData
|
||||
: LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData);
|
||||
@@ -373,7 +380,7 @@ public class LoansApiResource {
|
||||
} else if (templateType.equals("jlgbulk")) {
|
||||
// get group details along with members in that group
|
||||
final LoanAccountData loanAccountGroupData = this.loanReadPlatformService.retrieveGroupAndMembersDetailsTemplate(groupId);
|
||||
officeId = loanAccountGroupData.groupOfficeId();
|
||||
officeId = loanAccountGroupData.getGroup() != null ? loanAccountGroupData.getGroup().getOfficeId() : null;
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(groupId);
|
||||
newLoanAccount = newLoanAccount == null ? loanAccountGroupData
|
||||
: LoanAccountData.populateGroupDefaults(newLoanAccount, loanAccountGroupData);
|
||||
@@ -471,7 +478,8 @@ public class LoansApiResource {
|
||||
loanBasicDetails = LoanAccountData.withInterestRecalculationCalendarData(loanBasicDetails, calendarData,
|
||||
compoundingCalendarData);
|
||||
}
|
||||
if (loanBasicDetails.isMonthlyRepaymentFrequencyType()) {
|
||||
if (loanBasicDetails.getRepaymentFrequencyType() != null
|
||||
&& loanBasicDetails.getRepaymentFrequencyType().getId().intValue() == PeriodFrequencyType.MONTHS.getValue()) {
|
||||
Collection<CalendarData> loanCalendarDatas = this.calendarReadPlatformService.retrieveCalendarsByEntity(loanId,
|
||||
CalendarEntityType.LOANS.getValue(), null);
|
||||
CalendarData calendarData = null;
|
||||
@@ -542,9 +550,13 @@ public class LoansApiResource {
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.repaymentScheduleAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.repaymentScheduleAssociateParamName);
|
||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.repaymentScheduleRelatedData();
|
||||
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.getTimeline()
|
||||
.repaymentScheduleRelatedData(loanBasicDetails.getCurrency(), loanBasicDetails.getPrincipal(),
|
||||
loanBasicDetails.getApprovedPrincipal(), loanBasicDetails.getInArrearsTolerance(),
|
||||
loanBasicDetails.getFeeChargesAtDisbursementCharged());
|
||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, repaymentScheduleRelatedData,
|
||||
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(), loanBasicDetails.getTotalPaidFeeCharges());
|
||||
disbursementData, loanBasicDetails.isInterestRecalculationEnabled(),
|
||||
loanBasicDetails.getSummary() != null ? loanBasicDetails.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()) {
|
||||
@@ -553,7 +565,8 @@ public class LoansApiResource {
|
||||
}
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.originalScheduleAssociateParamName)
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled() && loanBasicDetails.isActive()) {
|
||||
&& loanBasicDetails.isInterestRecalculationEnabled()
|
||||
&& LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
|
||||
LoanScheduleData loanScheduleData = this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(loanId,
|
||||
repaymentScheduleRelatedData, disbursementData);
|
||||
@@ -597,7 +610,7 @@ public class LoansApiResource {
|
||||
|
||||
if (associationParameters.contains(DataTableApiConstant.collectionAssociateParamName)) {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.collectionAssociateParamName);
|
||||
if (loanBasicDetails.isActive()) {
|
||||
if (LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) {
|
||||
collectionData = this.loanReadPlatformService.retrieveLoanCollectionData(loanId);
|
||||
}
|
||||
}
|
||||
@@ -655,8 +668,12 @@ public class LoansApiResource {
|
||||
}
|
||||
chargeTemplate = this.loanChargeReadPlatformService.retrieveLoanChargeTemplate();
|
||||
|
||||
allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(loanBasicDetails.officeId(),
|
||||
staffInSelectedOfficeOnly);
|
||||
Long officeId = loanBasicDetails.getClientOfficeId();
|
||||
|
||||
if (officeId == null && loanBasicDetails.getGroup() != null) {
|
||||
officeId = loanBasicDetails.getGroup().getOfficeId();
|
||||
}
|
||||
allowedLoanOfficers = this.loanReadPlatformService.retrieveAllowedLoanOfficers(officeId, staffInSelectedOfficeOnly);
|
||||
|
||||
loanPurposeOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanPurpose");
|
||||
loanCollateralOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode("LoanCollateral");
|
||||
@@ -674,8 +691,8 @@ public class LoansApiResource {
|
||||
mandatoryResponseParameters.add(DataTableApiConstant.linkedAccountAssociateParamName);
|
||||
linkedAccount = this.accountAssociationsReadPlatformService.retriveLoanLinkedAssociation(loanId);
|
||||
}
|
||||
if (loanBasicDetails.groupId() != null) {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.groupId());
|
||||
if (loanBasicDetails.getGroup() != null && loanBasicDetails.getGroup().getId() != null) {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.getGroup().getId());
|
||||
}
|
||||
|
||||
if (loanBasicDetails.getProduct().isCanUseForTopup() && loanBasicDetails.getClientId() != null) {
|
||||
@@ -745,7 +762,7 @@ public class LoansApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Calculate loan repayment schedule | Submit a new Loan Application", description = "It calculates the loan repayment Schedule\n"
|
||||
+ "Submits a new loan application\n"
|
||||
+ "Mandatory Fields: clientId, productId, principal, loanTermFrequency, loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyId, expectedDisbursementDate, submittedOnDate, loanType\n"
|
||||
+ "Mandatory Fields: clientId, productId, principal, loanTermFrequency, loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyCode, expectedDisbursementDate, submittedOnDate, loanType\n"
|
||||
+ "Optional Fields: graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, linkAccountId, allowPartialPeriodInterestCalcualtion, fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing, createStandingInstructionAtDisbursement (requires linkedAccountId if set to true)\n"
|
||||
+ "Additional Mandatory Fields if interest recalculation is enabled for product and Rest frequency not same as repayment period: recalculationRestFrequencyDate\n"
|
||||
+ "Additional Mandatory Fields if interest recalculation with interest/fee compounding is enabled for product and compounding frequency not same as repayment period: recalculationCompoundingFrequencyDate\n"
|
||||
|
||||
+6
-6
@@ -958,8 +958,8 @@ final class LoansApiResourceSwagger {
|
||||
public BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
public GetLoansLoanIdInterestType interestType;
|
||||
public GetLoansLoanIdInterestCalculationPeriodType interestCalculationPeriodType;
|
||||
@Schema(example = "2")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
public GetLoansLoanIdTimeline timeline;
|
||||
public GetLoansLoanIdSummary summary;
|
||||
public GetLoansLoanIdRepaymentSchedule repaymentSchedule;
|
||||
@@ -1033,8 +1033,8 @@ final class LoansApiResourceSwagger {
|
||||
public Integer interestCalculationPeriodType;
|
||||
@Schema(example = "20 September 2011")
|
||||
public String expectedDisbursementDate;
|
||||
@Schema(example = "2")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
@Schema(example = "360", allowableValues = "1, 360, 364, 36")
|
||||
public Integer daysInYearType;
|
||||
@Schema(example = "individual")
|
||||
@@ -1155,8 +1155,8 @@ final class LoansApiResourceSwagger {
|
||||
public BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
@Schema(example = "04 March 2014")
|
||||
public String expectedDisbursementDate;
|
||||
@Schema(example = "1")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
@Schema(example = "1")
|
||||
public Long linkAccountId;
|
||||
@Schema(example = "true")
|
||||
|
||||
+14
-40
@@ -20,17 +20,23 @@ package org.apache.fineract.portfolio.loanaccount.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public final class CollectionData {
|
||||
|
||||
private final BigDecimal availableDisbursementAmount;
|
||||
private final int pastDueDays;
|
||||
private final LocalDate nextPaymentDueDate;
|
||||
private final int delinquentDays;
|
||||
private final LocalDate delinquentDate;
|
||||
private final BigDecimal delinquentAmount;
|
||||
private final LocalDate lastPaymentDate;
|
||||
private final BigDecimal lastPaymentAmount;
|
||||
private BigDecimal availableDisbursementAmount;
|
||||
private int pastDueDays;
|
||||
private LocalDate nextPaymentDueDate;
|
||||
private int delinquentDays;
|
||||
private LocalDate delinquentDate;
|
||||
private BigDecimal delinquentAmount;
|
||||
private LocalDate lastPaymentDate;
|
||||
private BigDecimal lastPaymentAmount;
|
||||
|
||||
private CollectionData(BigDecimal availableDisbursementAmount, int pastDueDays, LocalDate nextPaymentDueDate, int delinquentDays,
|
||||
LocalDate delinquentDate, BigDecimal delinquentAmount, LocalDate lastPaymentDate, BigDecimal lastPaymentAmount) {
|
||||
@@ -55,36 +61,4 @@ public final class CollectionData {
|
||||
final BigDecimal zero = BigDecimal.ZERO;
|
||||
return new CollectionData(zero, 0, null, 0, null, zero, null, zero);
|
||||
}
|
||||
|
||||
public BigDecimal getAvailableDisbursementAmount() {
|
||||
return availableDisbursementAmount;
|
||||
}
|
||||
|
||||
public int getPastDueDays() {
|
||||
return pastDueDays;
|
||||
}
|
||||
|
||||
public LocalDate getNextPaymentDueDate() {
|
||||
return nextPaymentDueDate;
|
||||
}
|
||||
|
||||
public int getDelinquentDays() {
|
||||
return delinquentDays;
|
||||
}
|
||||
|
||||
public LocalDate getDelinquentDate() {
|
||||
return delinquentDate;
|
||||
}
|
||||
|
||||
public BigDecimal getDelinquentAmount() {
|
||||
return delinquentAmount;
|
||||
}
|
||||
|
||||
public LocalDate getLastPaymentDate() {
|
||||
return lastPaymentDate;
|
||||
}
|
||||
|
||||
public BigDecimal getLastPaymentAmount() {
|
||||
return lastPaymentAmount;
|
||||
}
|
||||
}
|
||||
|
||||
+760
-1518
File diff suppressed because it is too large
Load Diff
+58
-62
@@ -133,7 +133,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCom
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
@@ -159,7 +158,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
public static final String FUND_ID = "fundId";
|
||||
public static final String LOAN_OFFICER_ID = "loanOfficerId";
|
||||
public static final String LOAN_PURPOSE_ID = "loanPurposeId";
|
||||
public static final String TRANSACTION_PROCESSING_STRATEGY_ID = "transactionProcessingStrategyId";
|
||||
public static final String TRANSACTION_PROCESSING_STRATEGY_CODE = "transactionProcessingStrategyCode";
|
||||
public static final String SUBMITTED_ON_DATE = "submittedOnDate";
|
||||
public static final String DATE_FORMAT = "dateFormat";
|
||||
public static final String LOCALE = "locale";
|
||||
@@ -226,9 +225,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
@JoinColumn(name = "loanpurpose_cv_id", nullable = true)
|
||||
private CodeValue loanPurpose;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||
@Column(name = "loan_transaction_strategy_code", nullable = false)
|
||||
private String transactionProcessingStrategyCode;
|
||||
|
||||
@Column(name = "loan_transaction_strategy_name")
|
||||
private String transactionProcessingStrategyName;
|
||||
|
||||
@Embedded
|
||||
private LoanProductRelatedDetail loanRepaymentScheduleDetail;
|
||||
@@ -431,48 +432,41 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final Integer loanType,
|
||||
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
||||
final Set<LoanCollateralManagement> collateral, final BigDecimal fixedEmiAmount,
|
||||
final String transactionProcessingStrategyCode, final LoanProductRelatedDetail loanRepaymentScheduleDetail,
|
||||
final Set<LoanCharge> loanCharges, final Set<LoanCollateralManagement> collateral, final BigDecimal fixedEmiAmount,
|
||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final LoanStatus status = null;
|
||||
final Group group = null;
|
||||
final Boolean syncDisbursementWithMeeting = null;
|
||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment);
|
||||
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategyCode, loanProduct,
|
||||
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
|
||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
}
|
||||
|
||||
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final Integer loanType,
|
||||
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
||||
final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
|
||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final LoanStatus status = null;
|
||||
final Client client = null;
|
||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||
final String transactionProcessingStrategyCode, final LoanProductRelatedDetail loanRepaymentScheduleDetail,
|
||||
final Set<LoanCharge> loanCharges, final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting,
|
||||
final BigDecimal fixedEmiAmount, final List<LoanDisbursementDetails> disbursementDetails,
|
||||
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement,
|
||||
final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List<Rate> rates,
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategyCode, loanProduct,
|
||||
loanRepaymentScheduleDetail, null, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment);
|
||||
}
|
||||
|
||||
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
||||
final Integer loanType, final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
||||
final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
|
||||
final List<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
|
||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final LoanStatus status = null;
|
||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||
final String transactionProcessingStrategyCode, final LoanProductRelatedDetail loanRepaymentScheduleDetail,
|
||||
final Set<LoanCharge> loanCharges, final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting,
|
||||
final BigDecimal fixedEmiAmount, final List<LoanDisbursementDetails> disbursementDetails,
|
||||
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement,
|
||||
final Boolean isFloatingInterestRate, final BigDecimal interestRateDifferential, final List<Rate> rates,
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategyCode, loanProduct,
|
||||
loanRepaymentScheduleDetail, null, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment);
|
||||
}
|
||||
@@ -482,7 +476,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
private Loan(final String accountNo, final Client client, final Group group, final Integer loanType, final Fund fund,
|
||||
final Staff loanOfficer, final CodeValue loanPurpose, final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
final Staff loanOfficer, final CodeValue loanPurpose, final String transactionProcessingStrategyCode,
|
||||
final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus,
|
||||
final Set<LoanCharge> loanCharges, final Set<LoanCollateralManagement> collateral, final Boolean syncDisbursementWithMeeting,
|
||||
final BigDecimal fixedEmiAmount, final List<LoanDisbursementDetails> disbursementDetails,
|
||||
@@ -509,7 +503,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
this.loanOfficer = loanOfficer;
|
||||
this.loanPurpose = loanPurpose;
|
||||
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
this.loanProduct = loanProduct;
|
||||
if (loanStatus != null) {
|
||||
this.loanStatus = loanStatus.getValue();
|
||||
@@ -677,7 +671,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
public ChangedTransactionDetail reprocessTransactions() {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
@@ -747,7 +741,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT, this);
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments = new ArrayList<>();
|
||||
LocalDate startDate = getDisbursementDate();
|
||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
||||
@@ -829,7 +823,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(loanCharge);
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||
/****
|
||||
* TODO Vishwas Currently we do not allow removing a loan charge after a loan is approved (hence there is no
|
||||
@@ -897,7 +891,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
if (!loanCharge.isDueAtDisbursement()) {
|
||||
/****
|
||||
* TODO Vishwas Currently we do not allow waiving updating loan charge after a loan is approved (hence there
|
||||
@@ -1084,7 +1078,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
// Waive of charges whose due date falls after latest 'repayment'
|
||||
// transaction dont require entire loan schedule to be reprocessed.
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||
/****
|
||||
* TODO Vishwas Currently we do not allow waiving fully paid loan charge and waiving partially paid loan
|
||||
@@ -1161,8 +1155,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
this.loanOfficer = newLoanOfficer;
|
||||
}
|
||||
|
||||
public void updateTransactionProcessingStrategy(final LoanTransactionProcessingStrategy strategy) {
|
||||
this.transactionProcessingStrategy = strategy;
|
||||
public void updateTransactionProcessingStrategy(final String transactionProcessingStrategyCode,
|
||||
final String transactionProcessingStrategyName) {
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
|
||||
}
|
||||
|
||||
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
||||
@@ -1495,9 +1491,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
actualChanges.put(LOAN_PURPOSE_ID, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(TRANSACTION_PROCESSING_STRATEGY_ID, this.transactionProcessingStrategy.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(TRANSACTION_PROCESSING_STRATEGY_ID);
|
||||
actualChanges.put(TRANSACTION_PROCESSING_STRATEGY_ID, newValue);
|
||||
if (command.isChangeInStringParameterNamed(TRANSACTION_PROCESSING_STRATEGY_CODE, transactionProcessingStrategyCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(TRANSACTION_PROCESSING_STRATEGY_CODE);
|
||||
actualChanges.put(TRANSACTION_PROCESSING_STRATEGY_CODE, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(SUBMITTED_ON_DATE, getSubmittedOnDate())) {
|
||||
@@ -2008,7 +2004,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
}
|
||||
|
||||
existingLoanCollateral = loanCollateralList.toArray(new LoanCollateralManagementData[loanCollateralList.size()]);
|
||||
existingLoanCollateral = loanCollateralList.toArray(new LoanCollateralManagementData[0]);
|
||||
|
||||
return existingLoanCollateral;
|
||||
}
|
||||
@@ -2022,7 +2018,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
loanChargesList.add(loanCharge.toCommand());
|
||||
}
|
||||
|
||||
existingLoanCharges = loanChargesList.toArray(new LoanChargeCommand[loanChargesList.size()]);
|
||||
existingLoanCharges = loanChargesList.toArray(new LoanChargeCommand[0]);
|
||||
|
||||
return existingLoanCharges;
|
||||
}
|
||||
@@ -2641,7 +2637,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
@@ -3221,7 +3217,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
|
||||
final LoanRepaymentScheduleInstallment currentInstallment = fetchLoanRepaymentScheduleInstallment(
|
||||
loanTransaction.getTransactionDate());
|
||||
@@ -3649,7 +3645,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
writeOffTransaction.reverse();
|
||||
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, this);
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
@@ -3724,7 +3720,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final AppUser currentUser, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(scheduleGeneratorDTO,
|
||||
loanRepaymentScheduleTransactionProcessor);
|
||||
|
||||
@@ -3846,7 +3842,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate);
|
||||
}
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
ChangedTransactionDetail changedTransactionDetail = closeDisbursements(scheduleGeneratorDTO,
|
||||
loanRepaymentScheduleTransactionProcessor);
|
||||
|
||||
@@ -5133,7 +5129,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
|
||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
||||
@@ -5269,7 +5265,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
public ChangedTransactionDetail processTransactions() {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction(
|
||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
||||
@@ -5498,7 +5494,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
public void processPostDisbursementTransactions() {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||
@@ -5526,7 +5522,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(generatorDTO);
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
|
||||
return loanScheduleGenerator.rescheduleNextInstallments(mc, loanApplicationTerms, this, generatorDTO.getHolidayDetailDTO(),
|
||||
loanRepaymentScheduleTransactionProcessor, generatorDTO.getRecalculateFrom());
|
||||
@@ -5544,7 +5540,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory().create(interestMethod);
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
installment = loanScheduleGenerator.calculatePrepaymentAmount(getCurrency(), onDate, loanApplicationTerms, mc, this,
|
||||
scheduleGeneratorDTO.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor);
|
||||
} else {
|
||||
@@ -5687,8 +5683,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
}
|
||||
|
||||
public LoanTransactionProcessingStrategy transactionProcessingStrategy() {
|
||||
return this.transactionProcessingStrategy;
|
||||
public String transactionProcessingStrategy() {
|
||||
return this.transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
public boolean isNpa() {
|
||||
@@ -6096,7 +6092,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
|
||||
// If is a refund
|
||||
if (adjustedTransaction == null) {
|
||||
@@ -6130,7 +6126,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final Money overpaidAmount = calculateTotalOverpayment(); // Before Transaction
|
||||
if (overpaidAmount.isGreaterThanZero()) {
|
||||
chargebackTransaction.setOverPayments(overpaidAmount);
|
||||
|
||||
+22
-39
@@ -18,56 +18,39 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.EarlyPaymentLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.HeavensFamilyLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class LoanRepaymentScheduleTransactionProcessorFactory {
|
||||
|
||||
public LoanRepaymentScheduleTransactionProcessor determineProcessor(
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy) {
|
||||
private final LoanRepaymentScheduleTransactionProcessor defaultLoanRepaymentScheduleTransactionProcessor;
|
||||
|
||||
LoanRepaymentScheduleTransactionProcessor processor = new PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor();
|
||||
private final List<LoanRepaymentScheduleTransactionProcessor> processors;
|
||||
|
||||
if (transactionProcessingStrategy != null) {
|
||||
@Value("${fineract.loan.transactionprocessor.error-not-found-fail}")
|
||||
private Boolean errorNotFoundFail;
|
||||
|
||||
if (transactionProcessingStrategy.isStandardStrategy()) {
|
||||
processor = new FineractStyleLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
public LoanRepaymentScheduleTransactionProcessor determineProcessor(final String transactionProcessingStrategy) {
|
||||
|
||||
if (transactionProcessingStrategy.isHeavensfamilyStrategy()) {
|
||||
processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
Optional<LoanRepaymentScheduleTransactionProcessor> processor = processors.stream()
|
||||
.filter(p -> p.accept(transactionProcessingStrategy)).findFirst();
|
||||
|
||||
if (transactionProcessingStrategy.isEarlyPaymentStrategy()) {
|
||||
processor = new EarlyPaymentLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
if (transactionProcessingStrategy.isCreocoreStrategy()) {
|
||||
processor = new CreocoreLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
if (transactionProcessingStrategy.isIndianRBIStrategy()) {
|
||||
processor = new RBILoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
if (transactionProcessingStrategy.isPrincipalInterestPenaltiesFeesOrderStrategy()) {
|
||||
processor = new PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
if (transactionProcessingStrategy.isInterestPrincipalPenaltiesFeesOrderStrategy()) {
|
||||
processor = new InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor();
|
||||
if (processor.isEmpty() && Boolean.TRUE.equals(errorNotFoundFail)) {
|
||||
throw new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategy);
|
||||
} else {
|
||||
return processor.orElse(defaultLoanRepaymentScheduleTransactionProcessor);
|
||||
}
|
||||
}
|
||||
|
||||
return processor;
|
||||
public List<TransactionProcessingStrategyData> getStrategies() {
|
||||
return processors.stream().map(p -> new TransactionProcessingStrategyData(null, p.getCode(), p.getName())).toList();
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -55,6 +55,11 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.imp
|
||||
*/
|
||||
public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implements LoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
@Override
|
||||
public boolean accept(String s) {
|
||||
return getCode().equalsIgnoreCase(s) || getName().equalsIgnoreCase(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides support for passing all {@link LoanTransaction}'s so it will completely re-process the entire loan
|
||||
* schedule. This is required in cases where the {@link LoanTransaction} being processed is in the past and falls
|
||||
|
||||
+6
@@ -30,6 +30,12 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
|
||||
public interface LoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
String getCode();
|
||||
|
||||
String getName();
|
||||
|
||||
boolean accept(String s);
|
||||
|
||||
void handleTransaction(LoanTransaction loanTransaction, MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments,
|
||||
Set<LoanCharge> charges);
|
||||
|
||||
|
||||
+14
@@ -40,6 +40,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
*/
|
||||
public class CreocoreLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "creocore-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Creocore Unique";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For creocore, early is defined as any date before the installment due date
|
||||
*/
|
||||
|
||||
+14
@@ -34,6 +34,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
*/
|
||||
public class EarlyPaymentLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
public static final String STRATEGY_CODE = "early-repayment-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Early Repayment Strategy";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For early/'in advance' repayments, pay off in the same way as on-time payments, interest first, principal,
|
||||
* penalties and charges.
|
||||
|
||||
+14
@@ -40,6 +40,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
@SuppressWarnings("unused")
|
||||
public class FineractStyleLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "mifos-standard-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Penalties, Fees, Interest, Principal order";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isTransactionInAdvanceOfInstallment(final int currentInstallmentIndex,
|
||||
final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate, final Money transactionAmount) {
|
||||
|
||||
+14
@@ -41,6 +41,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
@SuppressWarnings("unused")
|
||||
public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "heavensfamily-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "HeavensFamily Unique";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For late repayments, pay off in the same way as on-time payments, interest first then principal.
|
||||
*/
|
||||
|
||||
+14
@@ -35,6 +35,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
public class InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor
|
||||
extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "interest-principal-penalties-fees-order-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Interest, Principal, Penalties, Fees Order";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For early/'in advance' repayments, pay off in the same way as on-time payments, interest first, principal,
|
||||
* penalties and charges.
|
||||
|
||||
+14
@@ -35,6 +35,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
public class PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor
|
||||
extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "principal-interest-penalties-fees-order-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Principal, Interest, Penalties, Fees Order";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For early/'in advance' repayments, pay off in the same way as on-time payments, interest first, principal,
|
||||
* penalties and charges.
|
||||
|
||||
+14
@@ -43,6 +43,20 @@ import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Loa
|
||||
*/
|
||||
public class RBILoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
|
||||
private static final String STRATEGY_CODE = "rbi-india-strategy";
|
||||
|
||||
private static final String STRATEGY_NAME = "Overdue/Due Fee/Int,Principal";
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return STRATEGY_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return STRATEGY_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* For creocore, early is defined as any date before the installment due date
|
||||
*/
|
||||
|
||||
+3
-3
@@ -25,8 +25,8 @@ import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourc
|
||||
*/
|
||||
public class LoanTransactionProcessingStrategyNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public LoanTransactionProcessingStrategyNotFoundException(final Long id) {
|
||||
super("error.msg.transactions.processing.strategy.id.invalid",
|
||||
"Loan transaction processing strategy with identifier " + id + " does not exist", id);
|
||||
public LoanTransactionProcessingStrategyNotFoundException(final String code) {
|
||||
super("error.msg.transactions.processing.strategy.code.invalid",
|
||||
"Loan transaction processing strategy with code " + code + " does not exist", code);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -28,7 +28,6 @@ import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRescheduleRequestToTermVariationMapping;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper;
|
||||
@@ -132,8 +131,7 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(loan.transactionProcessingStrategy());
|
||||
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getInterestMethod());
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
|
||||
loan.setHelpers(loanLifecycleStateMachine, this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory);
|
||||
loan.setHelpers(null, this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory);
|
||||
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
||||
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||
final LoanScheduleModel loanScheduleModel = loanSchedule.getLoanScheduleModel();
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper {
|
||||
LoanApiConstants.clientIdParameterName, LoanApiConstants.groupIdParameterName, LoanApiConstants.loanTypeParameterName,
|
||||
LoanApiConstants.calendarIdParameterName, LoanApiConstants.productIdParameterName, LoanApiConstants.accountNoParameterName,
|
||||
LoanApiConstants.externalIdParameterName, LoanApiConstants.fundIdParameterName, LoanApiConstants.loanOfficerIdParameterName,
|
||||
LoanApiConstants.loanPurposeIdParameterName, LoanApiConstants.transactionProcessingStrategyIdParameterName,
|
||||
LoanApiConstants.loanPurposeIdParameterName, LoanApiConstants.transactionProcessingStrategyCodeParameterName,
|
||||
LoanApiConstants.principalParamName, LoanApiConstants.inArrearsToleranceParameterName,
|
||||
LoanApiConstants.interestRatePerPeriodParameterName, LoanApiConstants.repaymentEveryParameterName,
|
||||
LoanApiConstants.numberOfRepaymentsParameterName, LoanApiConstants.loanTermFrequencyParameterName,
|
||||
|
||||
+39
-21
@@ -32,6 +32,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
@@ -46,18 +48,22 @@ import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollatera
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollateralQuantity;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals;
|
||||
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.EqualAmortizationUnsupportedFeatureException;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
|
||||
@@ -72,8 +78,8 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
LoanApiConstants.numberOfRepaymentsParameterName, LoanApiConstants.repaymentEveryParameterName,
|
||||
LoanApiConstants.repaymentFrequencyTypeParameterName, LoanApiConstants.repaymentFrequencyNthDayTypeParameterName,
|
||||
LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName, LoanApiConstants.interestRatePerPeriodParameterName,
|
||||
LoanApiConstants.amortizationTypeParameterName, LoanApiConstants.interestTypeParameterName,
|
||||
LoanApiConstants.isFloatingInterestRate, LoanApiConstants.interestRateDifferential,
|
||||
LoanApiConstants.amortizationTypeParameterName, LoanApiConstants.amortizationTypeOptionsParameterName,
|
||||
LoanApiConstants.interestTypeParameterName, LoanApiConstants.isFloatingInterestRate, LoanApiConstants.interestRateDifferential,
|
||||
LoanApiConstants.interestCalculationPeriodTypeParameterName,
|
||||
LoanProductConstants.ALLOW_PARTIAL_PERIOD_INTEREST_CALCUALTION_PARAM_NAME,
|
||||
LoanApiConstants.interestRateFrequencyTypeParameterName, LoanApiConstants.expectedDisbursementDateParameterName,
|
||||
@@ -84,7 +90,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
LoanApiConstants.externalIdParameterName, LoanApiConstants.fundIdParameterName, LoanApiConstants.loanOfficerIdParameterName, // optional
|
||||
LoanApiConstants.loanPurposeIdParameterName, LoanApiConstants.inArrearsToleranceParameterName,
|
||||
LoanApiConstants.chargesParameterName, LoanApiConstants.collateralParameterName, // optional
|
||||
LoanApiConstants.transactionProcessingStrategyIdParameterName, // settings
|
||||
LoanApiConstants.transactionProcessingStrategyCodeParameterName, // settings
|
||||
LoanApiConstants.calendarIdParameterName, // optional
|
||||
LoanApiConstants.syncDisbursementWithMeetingParameterName, // optional
|
||||
LoanApiConstants.linkAccountIdParameterName, LoanApiConstants.disbursementDataParameterName,
|
||||
@@ -102,14 +108,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper;
|
||||
private final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper;
|
||||
|
||||
@Autowired
|
||||
public LoanApplicationCommandFromApiJsonHelper(final FromJsonHelper fromApiJsonHelper,
|
||||
final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper,
|
||||
final ClientCollateralManagementRepositoryWrapper clientCollateralManagementRepositoryWrapper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.apiJsonHelper = apiJsonHelper;
|
||||
this.clientCollateralManagementRepositoryWrapper = clientCollateralManagementRepositoryWrapper;
|
||||
}
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
|
||||
public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans, final LoanProduct loanProduct) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
@@ -388,10 +387,19 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
.notExceedingLengthOf(500);
|
||||
}
|
||||
|
||||
final Long transactionProcessingStrategyId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanApiConstants.transactionProcessingStrategyIdParameterName, element);
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyIdParameterName)
|
||||
.value(transactionProcessingStrategyId).notNull().integerGreaterThanZero();
|
||||
final String transactionProcessingStrategy = this.fromApiJsonHelper
|
||||
.extractStringNamed(LoanApiConstants.transactionProcessingStrategyCodeParameterName, element);
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName)
|
||||
.value(transactionProcessingStrategy).notNull();
|
||||
LoanRepaymentScheduleTransactionProcessor processor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategy);
|
||||
|
||||
if (processor == null) {
|
||||
Object[] values = loanRepaymentScheduleTransactionProcessorFactory.getStrategies().stream()
|
||||
.map(TransactionProcessingStrategyData::getCode).toList().toArray(new String[0]);
|
||||
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName).isOneOfTheseValues(values);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.linkAccountIdParameterName, element)) {
|
||||
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.linkAccountIdParameterName, element);
|
||||
@@ -626,12 +634,22 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
.integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.transactionProcessingStrategyIdParameterName, element)) {
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.transactionProcessingStrategyCodeParameterName, element)) {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
final Long transactionProcessingStrategyId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanApiConstants.transactionProcessingStrategyIdParameterName, element);
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyIdParameterName)
|
||||
.value(transactionProcessingStrategyId).notNull().integerGreaterThanZero();
|
||||
final String transactionProcessingStrategy = this.fromApiJsonHelper
|
||||
.extractStringNamed(LoanApiConstants.transactionProcessingStrategyCodeParameterName, element);
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName)
|
||||
.value(transactionProcessingStrategy).notNull();
|
||||
LoanRepaymentScheduleTransactionProcessor processor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategy);
|
||||
|
||||
if (processor == null) {
|
||||
Object[] values = loanRepaymentScheduleTransactionProcessorFactory.getStrategies().stream()
|
||||
.map(TransactionProcessingStrategyData::getCode).toList().toArray(new String[0]);
|
||||
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName)
|
||||
.isOneOfTheseValues(values);
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal principal = null;
|
||||
|
||||
+8
-7
@@ -128,7 +128,6 @@ import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
@@ -605,7 +604,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
productRelatedDetail.setRepayEvery(loan.loanProduct().getLoanProductRelatedDetail().getRepayEvery());
|
||||
}
|
||||
if (!transactionProcessingStrategy) {
|
||||
loan.updateTransactionProcessingStrategy(loan.loanProduct().getRepaymentStrategy());
|
||||
loan.updateTransactionProcessingStrategy(loan.loanProduct().getRepaymentStrategy(),
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory.determineProcessor(loan.loanProduct().getRepaymentStrategy())
|
||||
.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,12 +934,12 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
existingLoanApplication.updateLoanOfficerOnLoanApplication(newValue);
|
||||
}
|
||||
|
||||
final String strategyIdParamName = "transactionProcessingStrategyId";
|
||||
if (changes.containsKey(strategyIdParamName)) {
|
||||
final Long strategyId = command.longValueOfParameterNamed(strategyIdParamName);
|
||||
final LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(strategyId);
|
||||
final String strategyCodeParamName = "transactionProcessingStrategyCode";
|
||||
if (changes.containsKey(strategyCodeParamName)) {
|
||||
final String strategy = command.stringValueOfParameterNamed(strategyCodeParamName);
|
||||
|
||||
existingLoanApplication.updateTransactionProcessingStrategy(strategy);
|
||||
existingLoanApplication.updateTransactionProcessingStrategy(strategy,
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory.determineProcessor(strategy).getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+10
-22
@@ -70,10 +70,8 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTra
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidAmountOfCollaterals;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataNotAllowedException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||
@@ -82,7 +80,6 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.service.LoanSchedu
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
@@ -100,7 +97,6 @@ public class LoanAssembler {
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final GroupRepository groupRepository;
|
||||
private final FundRepository fundRepository;
|
||||
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
|
||||
private final StaffRepository staffRepository;
|
||||
private final CodeValueRepositoryWrapper codeValueRepository;
|
||||
private final LoanScheduleAssembler loanScheduleAssembler;
|
||||
@@ -143,7 +139,10 @@ public class LoanAssembler {
|
||||
final Long productId = this.fromApiJsonHelper.extractLongNamed("productId", element);
|
||||
final Long fundId = this.fromApiJsonHelper.extractLongNamed("fundId", element);
|
||||
final Long loanOfficerId = this.fromApiJsonHelper.extractLongNamed("loanOfficerId", element);
|
||||
final Long transactionProcessingStrategyId = this.fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
|
||||
final String transactionProcessingStrategyCode = this.fromApiJsonHelper.extractStringNamed("transactionProcessingStrategyCode",
|
||||
element);
|
||||
final String transactionProcessingStrategyName = this.loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategyCode).getName();
|
||||
final Long loanPurposeId = this.fromApiJsonHelper.extractLongNamed("loanPurposeId", element);
|
||||
final Boolean syncDisbursementWithMeeting = this.fromApiJsonHelper.extractBooleanNamed("syncDisbursementWithMeeting", element);
|
||||
final Boolean createStandingInstructionAtDisbursement = this.fromApiJsonHelper
|
||||
@@ -155,8 +154,6 @@ public class LoanAssembler {
|
||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.disbursementPrincipalParameterName, element);
|
||||
final Fund fund = findFundByIdIfProvided(fundId);
|
||||
final Staff loanOfficer = findLoanOfficerByIdIfProvided(loanOfficerId);
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(
|
||||
transactionProcessingStrategyId);
|
||||
CodeValue loanPurpose = null;
|
||||
if (loanPurposeId != null) {
|
||||
loanPurpose = this.codeValueRepository.findOneWithNotFoundDetection(loanPurposeId);
|
||||
@@ -272,25 +269,25 @@ public class LoanAssembler {
|
||||
}
|
||||
|
||||
loanApplication = Loan.newIndividualLoanApplicationFromGroup(accountNo, client, group, loanType.getId().intValue(), loanProduct,
|
||||
fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null,
|
||||
fund, loanOfficer, loanPurpose, transactionProcessingStrategyCode, loanProductRelatedDetail, loanCharges, null,
|
||||
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
||||
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
|
||||
loanApplication.updateTransactionProcessingStrategy(transactionProcessingStrategyCode, transactionProcessingStrategyName);
|
||||
} else if (group != null) {
|
||||
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanType.getId().intValue(), loanProduct, fund, loanOfficer,
|
||||
loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, null,
|
||||
loanPurpose, transactionProcessingStrategyCode, loanProductRelatedDetail, loanCharges, null,
|
||||
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
||||
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
|
||||
loanApplication.updateTransactionProcessingStrategy(transactionProcessingStrategyCode, transactionProcessingStrategyName);
|
||||
} else if (client != null) {
|
||||
|
||||
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanType.getId().intValue(), loanProduct, fund,
|
||||
loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral,
|
||||
loanOfficer, loanPurpose, transactionProcessingStrategyCode, loanProductRelatedDetail, loanCharges, collateral,
|
||||
fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement,
|
||||
isFloatingInterestRate, interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment);
|
||||
|
||||
loanApplication.updateTransactionProcessingStrategy(transactionProcessingStrategyCode, transactionProcessingStrategyName);
|
||||
}
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
@@ -354,15 +351,6 @@ public class LoanAssembler {
|
||||
return staff;
|
||||
}
|
||||
|
||||
public LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
||||
LoanTransactionProcessingStrategy strategy = null;
|
||||
if (transactionProcessingStrategyId != null) {
|
||||
strategy = this.loanTransactionProcessingStrategyRepository.findById(transactionProcessingStrategyId)
|
||||
.orElseThrow(() -> new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId));
|
||||
}
|
||||
return strategy;
|
||||
}
|
||||
|
||||
public void validateExpectedDisbursementForHolidayAndNonWorkingDay(final Loan loanApplication) {
|
||||
|
||||
final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled();
|
||||
|
||||
+13
-13
@@ -609,8 +609,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
+ " l.amortization_method_enum as amortizationType, l.interest_method_enum as interestType, l.is_equal_amortization as isEqualAmortization, l.interest_calculated_in_period_enum as interestCalculationPeriodType,"
|
||||
+ " l.fixed_principal_percentage_per_installment fixedPrincipalPercentagePerInstallment, "
|
||||
+ " l.allow_partial_period_interest_calcualtion as allowPartialPeriodInterestCalcualtion,"
|
||||
+ " l.loan_status_id as lifeCycleStatusId, l.loan_transaction_strategy_id as transactionStrategyId, "
|
||||
+ " lps.name as transactionStrategyName, "
|
||||
+ " l.loan_status_id as lifeCycleStatusId, l.loan_transaction_strategy_code as transactionStrategyCode, "
|
||||
+ " l.loan_transaction_strategy_name as transactionStrategyName, "
|
||||
+ " l.currency_code as currencyCode, l.currency_digits as currencyDigits, l.currency_multiplesof as inMultiplesOf, rc."
|
||||
+ sqlGenerator.escape("name")
|
||||
+ " as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, "
|
||||
@@ -676,7 +676,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
+ " left join m_appuser dbu on dbu.id = l.disbursedon_userid left join m_appuser cbu on cbu.id = l.closedon_userid"
|
||||
+ " left join m_code_value cv on cv.id = l.loanpurpose_cv_id"
|
||||
+ " left join m_code_value codev on codev.id = l.writeoff_reason_cv_id"
|
||||
+ " left join ref_loan_transaction_processing_strategy lps on lps.id = l.loan_transaction_strategy_id"
|
||||
+ " left join m_product_loan_variable_installment_config lpvi on lpvi.loan_product_id = l.product_id"
|
||||
+ " left join m_loan_topup as topup on l.id = topup.loan_id"
|
||||
+ " left join m_loan as topuploan on topuploan.id = topup.closure_loan_id";
|
||||
@@ -814,7 +813,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final int interestRateFrequencyTypeInt = JdbcSupport.getInteger(rs, "interestRateFrequencyType");
|
||||
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(interestRateFrequencyTypeInt);
|
||||
|
||||
final Long transactionStrategyId = JdbcSupport.getLong(rs, "transactionStrategyId");
|
||||
final String transactionStrategyCode = rs.getString("transactionStrategyCode");
|
||||
final String transactionStrategyName = rs.getString("transactionStrategyName");
|
||||
|
||||
final int amortizationTypeInt = JdbcSupport.getInteger(rs, "amortizationType");
|
||||
@@ -996,7 +995,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
isLoanProductLinkedToFloatingRate, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
|
||||
currencyData, proposedPrincipal, principal, approvedPrincipal, netDisbursalAmount, totalOverpaid, inArrearsTolerance,
|
||||
termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, null, null,
|
||||
transactionStrategyId, transactionStrategyName, amortizationType, interestRatePerPeriod, interestRateFrequencyType,
|
||||
transactionStrategyCode, transactionStrategyName, amortizationType, interestRatePerPeriod, interestRateFrequencyType,
|
||||
annualInterestRate, interestType, isFloatingInterestRate, interestRateDifferential, interestCalculationPeriodType,
|
||||
allowPartialPeriodInterestCalcualtion, expectedFirstRepaymentOnDate, graceOnPrincipalPayment,
|
||||
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate,
|
||||
@@ -1932,14 +1931,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
public LoanTransactionData retrieveLoanWriteoffTemplate(final Long loanId) {
|
||||
|
||||
final LoanAccountData loan = this.retrieveOne(loanId);
|
||||
final BigDecimal outstandingLoanBalance = null;
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WRITEOFF);
|
||||
final BigDecimal unrecognizedIncomePortion = null;
|
||||
final BigDecimal totalOutstanding = loan.getSummary() != null ? loan.getSummary().getTotalOutstanding() : null;
|
||||
final List<CodeValueData> writeOffReasonOptions = new ArrayList<>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(LoanApiConstants.WRITEOFFREASONS));
|
||||
LoanTransactionData loanTransactionData = new LoanTransactionData(null, null, null, transactionType, null, loan.getCurrency(),
|
||||
DateUtils.getBusinessLocalDate(), loan.getTotalOutstandingAmount(), loan.getNetDisbursalAmount(), null, null, null, null,
|
||||
null, null, null, null, outstandingLoanBalance, unrecognizedIncomePortion, false);
|
||||
DateUtils.getBusinessLocalDate(), totalOutstanding, loan.getNetDisbursalAmount(), null, null, null, null, null, null, null,
|
||||
null, null, null, false);
|
||||
loanTransactionData.setWriteOffReasonOptions(writeOffReasonOptions);
|
||||
return loanTransactionData;
|
||||
}
|
||||
@@ -2246,10 +2244,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final Collection<InterestRatePeriodData> intRates = this.floatingRatesReadPlatformService
|
||||
.retrieveInterestRatePeriods(loanData.getLoanProductId());
|
||||
for (final InterestRatePeriodData rate : intRates) {
|
||||
if (rate.getFromDate().compareTo(loanData.getDisbursementDate()) > 0 && loanData.isFloatingInterestRate()) {
|
||||
if (loanData.getTimeline() != null && rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) > 0
|
||||
&& loanData.isFloatingInterestRate()) {
|
||||
updateInterestRatePeriodData(rate, loanData);
|
||||
intRatePeriodData.add(rate);
|
||||
} else if (rate.getFromDate().compareTo(loanData.getDisbursementDate()) <= 0) {
|
||||
} else if (loanData.getTimeline() != null
|
||||
&& rate.getFromDate().compareTo(loanData.getTimeline().getDisbursementDate()) <= 0) {
|
||||
updateInterestRatePeriodData(rate, loanData);
|
||||
intRatePeriodData.add(rate);
|
||||
break;
|
||||
@@ -2275,8 +2275,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
rate.setEffectiveInterestRate(effectiveInterestRate);
|
||||
|
||||
if (rate.getFromDate().compareTo(loan.getDisbursementDate()) < 0) {
|
||||
rate.setFromDate(loan.getDisbursementDate());
|
||||
if (loan.getTimeline() != null && rate.getFromDate().compareTo(loan.getTimeline().getDisbursementDate()) < 0) {
|
||||
rate.setFromDate(loan.getTimeline().getDisbursementDate());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.starter;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.CreocoreLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.EarlyPaymentLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.HeavensFamilyLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.RBILoanRepaymentScheduleTransactionProcessor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class LoanAccountAutoStarter {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.creocore.enabled")
|
||||
public CreocoreLoanRepaymentScheduleTransactionProcessor creocoreLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new CreocoreLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.early-repayment.enabled")
|
||||
public EarlyPaymentLoanRepaymentScheduleTransactionProcessor earlyPaymentLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new EarlyPaymentLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.mifos-standard.enabled")
|
||||
public FineractStyleLoanRepaymentScheduleTransactionProcessor fineractStyleLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new FineractStyleLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.heavensfamily.enabled")
|
||||
public HeavensFamilyLoanRepaymentScheduleTransactionProcessor heavensFamilyLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new HeavensFamilyLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.interest-principal-penalties-fees.enabled")
|
||||
public InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor interestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new InterestPrincipalPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.principal-interest-penalties-fees.enabled")
|
||||
public PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor principalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty("fineract.loan.transactionprocessor.rbi-india.enabled")
|
||||
public RBILoanRepaymentScheduleTransactionProcessor rbiLoanRepaymentScheduleTransactionProcessor() {
|
||||
return new RBILoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LoanRepaymentScheduleTransactionProcessorFactory.class)
|
||||
public LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory(
|
||||
PrincipalInterestPenaltyFeesOrderLoanRepaymentScheduleTransactionProcessor defaultLoanRepaymentScheduleTransactionProcessor,
|
||||
List<LoanRepaymentScheduleTransactionProcessor> processors) {
|
||||
return new LoanRepaymentScheduleTransactionProcessorFactory(defaultLoanRepaymentScheduleTransactionProcessor, processors);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -115,7 +115,7 @@ public interface LoanProductConstants {
|
||||
String allowAttributeOverridesParamName = "allowAttributeOverrides";
|
||||
String amortizationTypeParamName = "amortizationType";
|
||||
String interestTypeParamName = "interestType";
|
||||
String transactionProcessingStrategyIdParamName = "transactionProcessingStrategyId";
|
||||
String transactionProcessingStrategyCodeParamName = "transactionProcessingStrategyCode";
|
||||
String interestCalculationPeriodTypeParamName = "interestCalculationPeriodType";
|
||||
String inArrearsToleranceParamName = "inArrearsTolerance";
|
||||
String repaymentEveryParamName = "repaymentEvery";
|
||||
|
||||
+2
-2
@@ -99,7 +99,7 @@ public class LoanProductsApiResource {
|
||||
"recurringMoratoriumOnPrincipalPeriods", "graceOnInterestPayment", "graceOnInterestCharged", "interestRatePerPeriod",
|
||||
"minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "annualInterestRate", "amortizationType",
|
||||
"interestType", "interestCalculationPeriodType", LoanProductConstants.ALLOW_PARTIAL_PERIOD_INTEREST_CALCUALTION_PARAM_NAME,
|
||||
"inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "charges", "accountingRule",
|
||||
"inArrearsTolerance", "transactionProcessingStrategyCode", "transactionProcessingStrategyName", "charges", "accountingRule",
|
||||
"externalId", "accountingMappings", "paymentChannelToFundSourceMappings", "fundOptions", "paymentTypeOptions",
|
||||
"currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "amortizationTypeOptions",
|
||||
"interestTypeOptions", "interestCalculationPeriodTypeOptions", "transactionProcessingStrategyOptions", "chargeOptions",
|
||||
@@ -178,7 +178,7 @@ public class LoanProductsApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create a Loan Product", description = "Depending of the Accounting Rule (accountingRule) selected, additional fields with details of the appropriate Ledger Account identifiers would need to be passed in.\n"
|
||||
+ "\n" + "Refer MifosX Accounting Specs Draft for more details regarding the significance of the selected accounting rule\n\n"
|
||||
+ "Mandatory Fields: name, shortName, currencyCode, digitsAfterDecimal, inMultiplesOf, principal, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyId, accountingRule, isInterestRecalculationEnabled, daysInYearType, daysInMonthType\n\n"
|
||||
+ "Mandatory Fields: name, shortName, currencyCode, digitsAfterDecimal, inMultiplesOf, principal, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyCode, accountingRule, isInterestRecalculationEnabled, daysInYearType, daysInMonthType\n\n"
|
||||
+ "Optional Fields: inArrearsTolerance, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, graceOnArrearsAgeing, charges, paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, penaltyToIncomeAccountMappings, includeInBorrowerCycle, useBorrowerCycle,principalVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle, multiDisburseLoan,maxTrancheCount, outstandingLoanBalance,overdueDaysForNPA,holdGuaranteeFunds, principalThresholdForLastInstalment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, installmentAmountInMultiplesOf, allowAttributeOverrides, allowPartialPeriodInterestCalcualtion\n\n"
|
||||
+ "Additional Mandatory Fields for Cash(2) based accounting: fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId, writeOffAccountId, transfersInSuspenseAccountId, overpaymentLiabilityAccountId\n\n"
|
||||
+ "Additional Mandatory Fields for periodic (3) and upfront (4)accrual accounting: fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId, writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId, receivablePenaltyAccountId, transfersInSuspenseAccountId, overpaymentLiabilityAccountId\n\n"
|
||||
|
||||
+7
-7
@@ -109,8 +109,8 @@ final class LoanProductsApiResourceSwagger {
|
||||
public Integer interestType;
|
||||
@Schema(example = "1")
|
||||
public Integer interestCalculationPeriodType;
|
||||
@Schema(example = "1")
|
||||
public Long transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
@Schema(example = "false")
|
||||
public Boolean isLinkedToFloatingInterestRates;
|
||||
@Schema(example = "false")
|
||||
@@ -227,7 +227,7 @@ final class LoanProductsApiResourceSwagger {
|
||||
@Schema(example = "true")
|
||||
public boolean interestType;
|
||||
@Schema(example = "true")
|
||||
public boolean transactionProcessingStrategyId;
|
||||
public boolean transactionProcessingStrategyCode;
|
||||
@Schema(example = "true")
|
||||
public boolean interestCalculationPeriodType;
|
||||
@Schema(example = "true")
|
||||
@@ -503,8 +503,8 @@ final class LoanProductsApiResourceSwagger {
|
||||
public BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
public GetLoanProductsInterestType interestType;
|
||||
public GetLoansProductsInterestCalculationPeriodType interestCalculationPeriodType;
|
||||
@Schema(example = "1")
|
||||
public Long transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategy;
|
||||
@Schema(example = "Mifos style")
|
||||
public String transactionProcessingStrategyName;
|
||||
@Schema(example = "[]")
|
||||
@@ -1211,8 +1211,8 @@ final class LoanProductsApiResourceSwagger {
|
||||
public BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
public GetLoanProductsTemplateResponse.GetLoanProductsInterestTemplateType interestType;
|
||||
public GetLoanProductsResponse.GetLoansProductsInterestCalculationPeriodType interestCalculationPeriodType;
|
||||
@Schema(example = "1")
|
||||
public Long transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
@Schema(example = "Mifos style")
|
||||
public String transactionProcessingStrategyName;
|
||||
@Schema(example = "[]")
|
||||
|
||||
+14
-14
@@ -107,7 +107,7 @@ public class LoanProductData implements Serializable {
|
||||
private final EnumOptionData interestCalculationPeriodType;
|
||||
private final Boolean allowPartialPeriodInterestCalculation;
|
||||
private final BigDecimal inArrearsTolerance;
|
||||
private final Long transactionProcessingStrategyId;
|
||||
private final String transactionProcessingStrategyCode;
|
||||
private final String transactionProcessingStrategyName;
|
||||
private final Integer graceOnPrincipalPayment;
|
||||
private final Integer recurringMoratoriumOnPrincipalPeriods;
|
||||
@@ -228,7 +228,7 @@ public class LoanProductData implements Serializable {
|
||||
final Boolean allowPartialPeriodInterestCalcualtion = null;
|
||||
final Long fundId = null;
|
||||
final String fundName = null;
|
||||
final Long transactionProcessingStrategyId = null;
|
||||
final String transactionProcessingStrategyCode = null;
|
||||
final String transactionProcessingStrategyName = null;
|
||||
final Integer graceOnPrincipalPayment = null;
|
||||
final Integer recurringMoratoriumOnPrincipalPeriods = null;
|
||||
@@ -281,7 +281,7 @@ public class LoanProductData implements Serializable {
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
|
||||
amortizationType, interestType, interestCalculationPeriodType, allowPartialPeriodInterestCalcualtion, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
transactionProcessingStrategyCode, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType,
|
||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
||||
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||
@@ -331,7 +331,7 @@ public class LoanProductData implements Serializable {
|
||||
final Boolean allowPartialPeriodInterestCalcualtion = null;
|
||||
final Long fundId = null;
|
||||
final String fundName = null;
|
||||
final Long transactionProcessingStrategyId = null;
|
||||
final String transactionProcessingStrategyCode = null;
|
||||
final String transactionProcessingStrategyName = null;
|
||||
final Integer graceOnPrincipalPayment = null;
|
||||
final Integer recurringMoratoriumOnPrincipalPeriods = null;
|
||||
@@ -386,7 +386,7 @@ public class LoanProductData implements Serializable {
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
|
||||
amortizationType, interestType, interestCalculationPeriodType, allowPartialPeriodInterestCalcualtion, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
transactionProcessingStrategyCode, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType,
|
||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
||||
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||
@@ -441,7 +441,7 @@ public class LoanProductData implements Serializable {
|
||||
final Boolean allowPartialPeriodInterestCalcualtion = null;
|
||||
final Long fundId = null;
|
||||
final String fundName = null;
|
||||
final Long transactionProcessingStrategyId = null;
|
||||
final String transactionProcessingStrategyCode = null;
|
||||
final String transactionProcessingStrategyName = null;
|
||||
|
||||
final Integer graceOnPrincipalPayment = null;
|
||||
@@ -498,7 +498,7 @@ public class LoanProductData implements Serializable {
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
|
||||
amortizationType, interestType, interestCalculationPeriodType, allowPartialPeriodInterestCalcualtion, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
transactionProcessingStrategyCode, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType,
|
||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
||||
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
||||
@@ -547,7 +547,7 @@ public class LoanProductData implements Serializable {
|
||||
final Boolean allowPartialPeriodInterestCalcualtion = null;
|
||||
final Long fundId = null;
|
||||
final String fundName = null;
|
||||
final Long transactionProcessingStrategyId = null;
|
||||
final String transactionProcessingStrategyCode = null;
|
||||
final String transactionProcessingStrategyName = null;
|
||||
|
||||
final Integer graceOnPrincipalPayment = null;
|
||||
@@ -604,7 +604,7 @@ public class LoanProductData implements Serializable {
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
|
||||
amortizationType, interestType, interestCalculationPeriodType, allowPartialPeriodInterestCalcualtion, fundId, fundName,
|
||||
transactionProcessingStrategyId, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
transactionProcessingStrategyCode, transactionProcessingStrategyName, graceOnPrincipalPayment,
|
||||
recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged, charges, accountingType,
|
||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
||||
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
||||
@@ -638,7 +638,7 @@ public class LoanProductData implements Serializable {
|
||||
final BigDecimal maxInterestRatePerPeriod, final BigDecimal annualInterestRate, final EnumOptionData repaymentFrequencyType,
|
||||
final EnumOptionData interestRateFrequencyType, final EnumOptionData amortizationType, final EnumOptionData interestType,
|
||||
final EnumOptionData interestCalculationPeriodType, final Boolean allowPartialPeriodInterestCalculation, final Long fundId,
|
||||
final String fundName, final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName,
|
||||
final String fundName, final String transactionProcessingStrategyCode, final String transactionProcessingStrategyName,
|
||||
final Integer graceOnPrincipalPayment, final Integer recurringMoratoriumOnPrincipalPeriods,
|
||||
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final Collection<ChargeData> charges,
|
||||
final EnumOptionData accountingType, final boolean includeInBorrowerCycle, boolean useBorrowerCycle, final LocalDate startDate,
|
||||
@@ -703,7 +703,7 @@ public class LoanProductData implements Serializable {
|
||||
this.allowPartialPeriodInterestCalculation = allowPartialPeriodInterestCalculation;
|
||||
this.fundId = fundId;
|
||||
this.fundName = fundName;
|
||||
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
|
||||
this.charges = charges;
|
||||
this.accountingRule = accountingType;
|
||||
@@ -858,10 +858,10 @@ public class LoanProductData implements Serializable {
|
||||
if (this.transactionProcessingStrategyOptions != null && this.transactionProcessingStrategyOptions.size() == 1) {
|
||||
final List<TransactionProcessingStrategyData> listOfOptions = new ArrayList<>(this.transactionProcessingStrategyOptions);
|
||||
|
||||
this.transactionProcessingStrategyId = listOfOptions.get(0).id();
|
||||
this.transactionProcessingStrategyName = listOfOptions.get(0).name();
|
||||
this.transactionProcessingStrategyCode = listOfOptions.get(0).getCode();
|
||||
this.transactionProcessingStrategyName = listOfOptions.get(0).getName();
|
||||
} else {
|
||||
this.transactionProcessingStrategyId = productData.transactionProcessingStrategyId;
|
||||
this.transactionProcessingStrategyCode = productData.transactionProcessingStrategyCode;
|
||||
this.transactionProcessingStrategyName = productData.transactionProcessingStrategyName;
|
||||
}
|
||||
|
||||
|
||||
+4
-14
@@ -19,28 +19,18 @@
|
||||
package org.apache.fineract.portfolio.loanproduct.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a transaction strategy option for a loan.
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public final class TransactionProcessingStrategyData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String code;
|
||||
private final String name;
|
||||
|
||||
public TransactionProcessingStrategyData(final Long id, final String code, final String name) {
|
||||
this.id = id;
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-22
@@ -82,9 +82,11 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
@JoinColumn(name = "fund_id")
|
||||
private Fund fund;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "loan_transaction_strategy_id")
|
||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||
@Column(name = "loan_transaction_strategy_code", nullable = false)
|
||||
private String transactionProcessingStrategyCode;
|
||||
|
||||
@Column(name = "loan_transaction_strategy_name")
|
||||
private String transactionProcessingStrategyName;
|
||||
|
||||
@Column(name = "name", nullable = false, unique = true)
|
||||
private String name;
|
||||
@@ -200,7 +202,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
@JoinColumn(name = "delinquency_bucket_id")
|
||||
private DelinquencyBucket delinquencyBucket;
|
||||
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final String loanTransactionProcessingStrategy,
|
||||
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator, FloatingRate floatingRate,
|
||||
final List<Rate> productRates) {
|
||||
|
||||
@@ -568,8 +570,8 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.loanProductMinMaxConstraints = null;
|
||||
}
|
||||
|
||||
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name,
|
||||
final String shortName, final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||
public LoanProduct(final Fund fund, final String transactionProcessingStrategyCode, final String name, final String shortName,
|
||||
final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
@@ -599,7 +601,7 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
final boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType,
|
||||
final Integer overAppliedNumber) {
|
||||
this.fund = fund;
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
this.name = name.trim();
|
||||
this.shortName = shortName.trim();
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
@@ -743,12 +745,16 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.fund = fund;
|
||||
}
|
||||
|
||||
public void update(final LoanTransactionProcessingStrategy strategy) {
|
||||
this.transactionProcessingStrategy = strategy;
|
||||
public void setTransactionProcessingStrategyCode(final String transactionProcessingStrategyCode) {
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
public LoanTransactionProcessingStrategy getRepaymentStrategy() {
|
||||
return this.transactionProcessingStrategy;
|
||||
public void setTransactionProcessingStrategyName(final String transactionProcessingStrategyName) {
|
||||
this.transactionProcessingStrategyName = transactionProcessingStrategyName;
|
||||
}
|
||||
|
||||
public String getRepaymentStrategy() {
|
||||
return this.transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
public boolean hasCurrencyCodeOf(final String currencyCode) {
|
||||
@@ -884,14 +890,10 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
actualChanges.put(fundIdParamName, newValue);
|
||||
}
|
||||
|
||||
Long existingStrategyId = null;
|
||||
if (this.transactionProcessingStrategy != null) {
|
||||
existingStrategyId = this.transactionProcessingStrategy.getId();
|
||||
}
|
||||
final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId";
|
||||
if (command.isChangeInLongParameterNamed(transactionProcessingStrategyParamName, existingStrategyId)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(transactionProcessingStrategyParamName);
|
||||
actualChanges.put(transactionProcessingStrategyParamName, newValue);
|
||||
final String transactionProcessingStrategyCodeParamName = "transactionProcessingStrategyCode";
|
||||
if (command.isChangeInStringParameterNamed(transactionProcessingStrategyCodeParamName, this.transactionProcessingStrategyCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(transactionProcessingStrategyCodeParamName);
|
||||
actualChanges.put(transactionProcessingStrategyCodeParamName, newValue);
|
||||
}
|
||||
|
||||
final String chargesParamName = "charges";
|
||||
@@ -1035,11 +1037,11 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
if (command.parsedJson().getAsJsonObject().getAsJsonObject(LoanProductConstants.allowAttributeOverridesParamName)
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyIdParamName)
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyCodeParamName)
|
||||
.getAsBoolean() != this.loanConfigurableAttributes.getTransactionProcessingStrategyBoolean()) {
|
||||
this.loanConfigurableAttributes.setTransactionProcessingStrategyId(
|
||||
this.loanConfigurableAttributes.setTransactionProcessingStrategyCode(
|
||||
command.parsedJson().getAsJsonObject().getAsJsonObject(LoanProductConstants.allowAttributeOverridesParamName)
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyIdParamName).getAsBoolean());
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyCodeParamName).getAsBoolean());
|
||||
}
|
||||
|
||||
if (command.parsedJson().getAsJsonObject().getAsJsonObject(LoanProductConstants.allowAttributeOverridesParamName)
|
||||
|
||||
+11
-11
@@ -43,8 +43,8 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
@Column(name = "interest_method_enum")
|
||||
private Boolean interestType;
|
||||
|
||||
@Column(name = "loan_transaction_strategy_id")
|
||||
private Boolean transactionProcessingStrategyId;
|
||||
@Column(name = "loan_transaction_strategy_code")
|
||||
private Boolean transactionProcessingStrategyCode;
|
||||
|
||||
@Column(name = "interest_calculated_in_period_enum")
|
||||
private Boolean interestCalculationPeriodType;
|
||||
@@ -62,7 +62,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
private Boolean graceOnArrearsAgeing;
|
||||
|
||||
private static final String[] supportedLoanConfigurableAttributes = { LoanProductConstants.amortizationTypeParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyIdParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyCodeParamName,
|
||||
LoanProductConstants.interestCalculationPeriodTypeParamName, LoanProductConstants.inArrearsToleranceParamName,
|
||||
LoanProductConstants.repaymentEveryParamName, LoanProductConstants.graceOnPrincipalAndInterestPaymentParamName,
|
||||
LoanProductConstants.GRACE_ON_ARREARS_AGEING_PARAMETER_NAME };
|
||||
@@ -77,7 +77,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
.getAsJsonPrimitive(LoanProductConstants.interestTypeParamName).getAsBoolean();
|
||||
final Boolean transactionProcessingStrategy = command.parsedJson().getAsJsonObject()
|
||||
.getAsJsonObject(LoanProductConstants.allowAttributeOverridesParamName)
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyIdParamName).getAsBoolean();
|
||||
.getAsJsonPrimitive(LoanProductConstants.transactionProcessingStrategyCodeParamName).getAsBoolean();
|
||||
final Boolean interestCalcPeriod = command.parsedJson().getAsJsonObject()
|
||||
.getAsJsonObject(LoanProductConstants.allowAttributeOverridesParamName)
|
||||
.getAsJsonPrimitive(LoanProductConstants.interestCalculationPeriodTypeParamName).getAsBoolean();
|
||||
@@ -116,7 +116,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
arrearsTolerance, repaymentEvery, graceOnPrincipalAndInterestPayment, graceOnArrearsAging);
|
||||
}
|
||||
|
||||
public LoanProductConfigurableAttributes(Boolean amortization, Boolean interestMethod, Boolean transactionProcessingStrategy,
|
||||
public LoanProductConfigurableAttributes(Boolean amortization, Boolean interestMethod, Boolean transactionProcessingStrategyCode,
|
||||
Boolean interestCalcPeriod, Boolean arrearsTolerance, Boolean repaymentEvery, Boolean graceOnPrincipalAndInterestPayment,
|
||||
Boolean graceOnArrearsAging) {
|
||||
this.amortizationType = amortization;
|
||||
@@ -126,7 +126,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
this.interestCalculationPeriodType = interestCalcPeriod;
|
||||
this.graceOnPrincipalAndInterestPayment = graceOnPrincipalAndInterestPayment;
|
||||
this.repaymentEvery = repaymentEvery;
|
||||
this.transactionProcessingStrategyId = transactionProcessingStrategy;
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
protected LoanProductConfigurableAttributes() {
|
||||
@@ -150,7 +150,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
}
|
||||
|
||||
public Boolean getTransactionProcessingStrategyBoolean() {
|
||||
return transactionProcessingStrategyId;
|
||||
return transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
public Boolean getInterestCalcPeriodBoolean() {
|
||||
@@ -185,8 +185,8 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
this.interestType = interestType;
|
||||
}
|
||||
|
||||
public void setTransactionProcessingStrategyId(Boolean transactionProcessingStrategyId) {
|
||||
this.transactionProcessingStrategyId = transactionProcessingStrategyId;
|
||||
public void setTransactionProcessingStrategyCode(Boolean transactionProcessingStrategyCode) {
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
public void setInterestCalculationPeriodType(Boolean interestCalculationPeriodType) {
|
||||
@@ -223,7 +223,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
|
||||
return Objects.equals(loanProduct, that.loanProduct) && Objects.equals(amortizationType, that.amortizationType)
|
||||
&& Objects.equals(interestType, that.interestType)
|
||||
&& Objects.equals(transactionProcessingStrategyId, that.transactionProcessingStrategyId)
|
||||
&& Objects.equals(transactionProcessingStrategyCode, that.transactionProcessingStrategyCode)
|
||||
&& Objects.equals(interestCalculationPeriodType, that.interestCalculationPeriodType)
|
||||
&& Objects.equals(inArrearsTolerance, that.inArrearsTolerance) && Objects.equals(repaymentEvery, that.repaymentEvery)
|
||||
&& Objects.equals(graceOnPrincipalAndInterestPayment, that.graceOnPrincipalAndInterestPayment)
|
||||
@@ -232,7 +232,7 @@ public class LoanProductConfigurableAttributes extends AbstractPersistableCustom
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(loanProduct, amortizationType, interestType, transactionProcessingStrategyId, interestCalculationPeriodType,
|
||||
return Objects.hash(loanProduct, amortizationType, interestType, transactionProcessingStrategyCode, interestCalculationPeriodType,
|
||||
inArrearsTolerance, repaymentEvery, graceOnPrincipalAndInterestPayment, graceOnArrearsAgeing);
|
||||
}
|
||||
}
|
||||
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
|
||||
@Entity
|
||||
@Table(name = "ref_loan_transaction_processing_strategy")
|
||||
public class LoanTransactionProcessingStrategy extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "code", unique = true)
|
||||
private String code;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "sort_order")
|
||||
private Integer sortOrder; // Don't change this name as this property name
|
||||
// is used as sort order while retrieving this
|
||||
// objects
|
||||
|
||||
protected LoanTransactionProcessingStrategy() {
|
||||
//
|
||||
}
|
||||
|
||||
public TransactionProcessingStrategyData toData() {
|
||||
return new TransactionProcessingStrategyData(getId(), this.code, this.name);
|
||||
}
|
||||
|
||||
public boolean isStandardStrategy() {
|
||||
return "mifos-standard-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isHeavensfamilyStrategy() {
|
||||
return "heavensfamily-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isEarlyPaymentStrategy() {
|
||||
return "early-repayment-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isCreocoreStrategy() {
|
||||
return "creocore-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isIndianRBIStrategy() {
|
||||
return "rbi-india-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isPrincipalInterestPenaltiesFeesOrderStrategy() {
|
||||
return "principal-interest-penalties-fees-order-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
|
||||
public boolean isInterestPrincipalPenaltiesFeesOrderStrategy() {
|
||||
return "interest-principal-penalties-fees-order-strategy".equalsIgnoreCase(this.code);
|
||||
}
|
||||
}
|
||||
+27
-14
@@ -32,6 +32,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.LoanProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
@@ -43,7 +45,10 @@ import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
||||
@@ -53,9 +58,10 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductValueConditionType;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.EqualAmortizationUnsupportedFeatureException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public final class LoanProductDataValidator {
|
||||
|
||||
@@ -78,7 +84,7 @@ public final class LoanProductDataValidator {
|
||||
public static final String INTEREST_TYPE = "interestType";
|
||||
public static final String INTEREST_CALCULATION_PERIOD_TYPE = "interestCalculationPeriodType";
|
||||
public static final String IN_ARREARS_TOLERANCE = "inArrearsTolerance";
|
||||
public static final String TRANSACTION_PROCESSING_STRATEGY_ID = "transactionProcessingStrategyId";
|
||||
public static final String TRANSACTION_PROCESSING_STRATEGY_CODE = "transactionProcessingStrategyCode";
|
||||
public static final String GRACE_ON_PRINCIPAL_PAYMENT = "graceOnPrincipalPayment";
|
||||
public static final String GRACE_ON_INTEREST_PAYMENT = "graceOnInterestPayment";
|
||||
public static final String GRACE_ON_INTEREST_CHARGED = "graceOnInterestCharged";
|
||||
@@ -102,7 +108,7 @@ public final class LoanProductDataValidator {
|
||||
NUMBER_OF_REPAYMENTS, MIN_NUMBER_OF_REPAYMENTS, MAX_NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY_TYPE, INTEREST_RATE_PER_PERIOD,
|
||||
MIN_INTEREST_RATE_PER_PERIOD, MAX_INTEREST_RATE_PER_PERIOD, INTEREST_RATE_FREQUENCY_TYPE, AMORTIZATION_TYPE, INTEREST_TYPE,
|
||||
INTEREST_CALCULATION_PERIOD_TYPE, LoanProductConstants.ALLOW_PARTIAL_PERIOD_INTEREST_CALCUALTION_PARAM_NAME,
|
||||
IN_ARREARS_TOLERANCE, TRANSACTION_PROCESSING_STRATEGY_ID, GRACE_ON_PRINCIPAL_PAYMENT, "recurringMoratoriumOnPrincipalPeriods",
|
||||
IN_ARREARS_TOLERANCE, TRANSACTION_PROCESSING_STRATEGY_CODE, GRACE_ON_PRINCIPAL_PAYMENT, "recurringMoratoriumOnPrincipalPeriods",
|
||||
GRACE_ON_INTEREST_PAYMENT, GRACE_ON_INTEREST_CHARGED, "charges", ACCOUNTING_RULE, INCLUDE_IN_BORROWER_CYCLE, "startDate",
|
||||
"closeDate", "externalId", IS_LINKED_TO_FLOATING_INTEREST_RATES, FLOATING_RATES_ID, INTEREST_RATE_DIFFERENTIAL,
|
||||
MIN_DIFFERENTIAL_LENDING_RATE, DEFAULT_DIFFERENTIAL_LENDING_RATE, MAX_DIFFERENTIAL_LENDING_RATE,
|
||||
@@ -149,7 +155,7 @@ public final class LoanProductDataValidator {
|
||||
LoanProductConstants.OVER_APPLIED_NUMBER, LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME));
|
||||
|
||||
private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { LoanProductConstants.amortizationTypeParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyIdParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyCodeParamName,
|
||||
LoanProductConstants.interestCalculationPeriodTypeParamName, LoanProductConstants.inArrearsToleranceParamName,
|
||||
LoanProductConstants.repaymentEveryParamName, LoanProductConstants.graceOnPrincipalAndInterestPaymentParamName,
|
||||
LoanProductConstants.GRACE_ON_ARREARS_AGEING_PARAMETER_NAME };
|
||||
@@ -161,10 +167,7 @@ public final class LoanProductDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public LoanProductDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
@@ -310,9 +313,19 @@ public final class LoanProductDataValidator {
|
||||
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(IN_ARREARS_TOLERANCE, element);
|
||||
baseDataValidator.reset().parameter(IN_ARREARS_TOLERANCE).value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
|
||||
final Long transactionProcessingStrategyId = this.fromApiJsonHelper.extractLongNamed(TRANSACTION_PROCESSING_STRATEGY_ID, element);
|
||||
baseDataValidator.reset().parameter(TRANSACTION_PROCESSING_STRATEGY_ID).value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
final String transactionProcessingStrategyCode = this.fromApiJsonHelper.extractStringNamed(TRANSACTION_PROCESSING_STRATEGY_CODE,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(TRANSACTION_PROCESSING_STRATEGY_CODE).value(transactionProcessingStrategyCode).notNull();
|
||||
|
||||
LoanRepaymentScheduleTransactionProcessor processor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategyCode);
|
||||
|
||||
if (processor == null) {
|
||||
Object[] values = loanRepaymentScheduleTransactionProcessorFactory.getStrategies().stream()
|
||||
.map(TransactionProcessingStrategyData::getCode).toList().toArray(new String[0]);
|
||||
|
||||
baseDataValidator.reset().parameter(TRANSACTION_PROCESSING_STRATEGY_CODE).isOneOfTheseValues(values);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME, element)) {
|
||||
final Long delinquencyBucketId = this.fromApiJsonHelper.extractLongNamed(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME,
|
||||
@@ -1077,10 +1090,10 @@ public final class LoanProductDataValidator {
|
||||
baseDataValidator.reset().parameter(REPAYMENT_FREQUENCY_TYPE).value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(TRANSACTION_PROCESSING_STRATEGY_ID, element)) {
|
||||
final Long transactionProcessingStrategyId = this.fromApiJsonHelper.extractLongNamed(TRANSACTION_PROCESSING_STRATEGY_ID,
|
||||
if (this.fromApiJsonHelper.parameterExists(TRANSACTION_PROCESSING_STRATEGY_CODE, element)) {
|
||||
final String transactionProcessingStrategyCode = this.fromApiJsonHelper.extractStringNamed(TRANSACTION_PROCESSING_STRATEGY_CODE,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(TRANSACTION_PROCESSING_STRATEGY_ID).value(transactionProcessingStrategyId).notNull()
|
||||
baseDataValidator.reset().parameter(TRANSACTION_PROCESSING_STRATEGY_CODE).value(transactionProcessingStrategyCode).notNull()
|
||||
.integerGreaterThanZero();
|
||||
}
|
||||
|
||||
|
||||
+5
-21
@@ -34,15 +34,15 @@ import static org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations
|
||||
import static org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations.repaymentFrequencyType;
|
||||
import static org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations.rescheduleStrategyType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.common.domain.DayOfWeekType;
|
||||
import org.apache.fineract.portfolio.common.domain.NthDayType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.TransactionProcessingStrategyData;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||
@@ -51,22 +51,14 @@ import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCom
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanPreClosureInterestCalculationStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductValueConditionType;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlatformService {
|
||||
|
||||
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanDropdownReadPlatformServiceImpl(
|
||||
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository) {
|
||||
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
|
||||
}
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveLoanAmortizationTypeOptions() {
|
||||
@@ -125,15 +117,7 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat
|
||||
|
||||
@Override
|
||||
public Collection<TransactionProcessingStrategyData> retrieveTransactionProcessingStrategies() {
|
||||
|
||||
final Collection<TransactionProcessingStrategyData> strategyOptions = new ArrayList<>();
|
||||
Sort sort = Sort.by("sortOrder");
|
||||
final List<LoanTransactionProcessingStrategy> strategies = this.loanTransactionProcessingStrategyRepository.findAll(sort);
|
||||
for (final LoanTransactionProcessingStrategy strategy : strategies) {
|
||||
strategyOptions.add(strategy.toData());
|
||||
}
|
||||
|
||||
return strategyOptions;
|
||||
return loanRepaymentScheduleTransactionProcessorFactory.getStrategies();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-5
@@ -202,7 +202,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
}
|
||||
|
||||
public String loanProductSchema() {
|
||||
return "lp.id as id, lp.fund_id as fundId, f.name as fundName, lp.loan_transaction_strategy_id as transactionStrategyId, ltps.name as transactionStrategyName, "
|
||||
return "lp.id as id, lp.fund_id as fundId, f.name as fundName, lp.loan_transaction_strategy_code as transactionStrategyCode, lp.loan_transaction_strategy_name as transactionStrategyName, "
|
||||
+ "lp.name as name, lp.short_name as shortName, lp.description as description, "
|
||||
+ "lp.principal_amount as principal, lp.min_principal_amount as minPrincipal, lp.max_principal_amount as maxPrincipal, lp.currency_code as currencyCode, lp.currency_digits as currencyDigits, lp.currency_multiplesof as inMultiplesOf, "
|
||||
+ "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.min_nominal_interest_rate_per_period as minInterestRatePerPeriod, lp.max_nominal_interest_rate_per_period as maxInterestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, "
|
||||
@@ -236,7 +236,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
+ "lp.account_moves_out_of_npa_only_on_arrears_completion as accountMovesOutOfNPAOnlyOnArrearsCompletion, "
|
||||
+ "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol, lp.external_id as externalId, "
|
||||
+ "lca.id as lcaId, lca.amortization_method_enum as amortizationBoolean, lca.interest_method_enum as interestMethodConfigBoolean, "
|
||||
+ "lca.loan_transaction_strategy_id as transactionProcessingStrategyBoolean,lca.interest_calculated_in_period_enum as interestCalcPeriodBoolean, lca.arrearstolerance_amount as arrearsToleranceBoolean, "
|
||||
+ "lca.loan_transaction_strategy_code as transactionProcessingStrategyBoolean,lca.interest_calculated_in_period_enum as interestCalcPeriodBoolean, lca.arrearstolerance_amount as arrearsToleranceBoolean, "
|
||||
+ "lca.repay_every as repaymentFrequencyBoolean, lca.moratorium as graceOnPrincipalAndInterestBoolean, lca.grace_on_arrears_ageing as graceOnArrearsAgingBoolean, "
|
||||
+ "lp.is_linked_to_floating_interest_rates as isLinkedToFloatingInterestRates, "
|
||||
+ "lfr.floating_rates_id as floatingRateId, " + "fr.name as floatingRateName, "
|
||||
@@ -251,7 +251,6 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
+ " from m_product_loan lp " + " left join m_fund f on f.id = lp.fund_id "
|
||||
+ " left join m_product_loan_recalculation_details lpr on lpr.product_id=lp.id "
|
||||
+ " left join m_product_loan_guarantee_details lpg on lpg.loan_product_id=lp.id "
|
||||
+ " left join ref_loan_transaction_processing_strategy ltps on ltps.id = lp.loan_transaction_strategy_id"
|
||||
+ " left join m_product_loan_configurable_attributes lca on lca.loan_product_id = lp.id "
|
||||
+ " left join m_product_loan_floating_rates as lfr on lfr.loan_product_id = lp.id "
|
||||
+ " left join m_floating_rates as fr on lfr.floating_rates_id = fr.id "
|
||||
@@ -270,7 +269,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final String description = rs.getString("description");
|
||||
final Long fundId = JdbcSupport.getLong(rs, "fundId");
|
||||
final String fundName = rs.getString("fundName");
|
||||
final Long transactionStrategyId = JdbcSupport.getLong(rs, "transactionStrategyId");
|
||||
final String transactionStrategyCode = rs.getString("transactionStrategyCode");
|
||||
final String transactionStrategyName = rs.getString("transactionStrategyName");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
@@ -487,7 +486,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType,
|
||||
allowPartialPeriodInterestCalcualtion, fundId, fundName, transactionStrategyId, transactionStrategyName,
|
||||
allowPartialPeriodInterestCalcualtion, fundId, fundName, transactionStrategyCode, transactionStrategyName,
|
||||
graceOnPrincipalPayment, recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, graceOnInterestCharged,
|
||||
this.charges, accountingRuleType, includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId,
|
||||
principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle,
|
||||
|
||||
+14
-49
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.PersistenceException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.service.ProductToGLAccountMappingWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
@@ -45,14 +46,12 @@ import org.apache.fineract.portfolio.floatingrates.domain.FloatingRateRepository
|
||||
import org.apache.fineract.portfolio.fund.domain.Fund;
|
||||
import org.apache.fineract.portfolio.fund.domain.FundRepository;
|
||||
import org.apache.fineract.portfolio.fund.exception.FundNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductCannotBeModifiedDueToNonClosedLoansException;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductDateException;
|
||||
@@ -62,13 +61,13 @@ import org.apache.fineract.portfolio.rate.domain.Rate;
|
||||
import org.apache.fineract.portfolio.rate.domain.RateRepositoryWrapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanProductWritePlatformService {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LoanProductWritePlatformServiceJpaRepositoryImpl.class);
|
||||
@@ -77,7 +76,6 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
private final LoanProductRepository loanProductRepository;
|
||||
private final AprCalculator aprCalculator;
|
||||
private final FundRepository fundRepository;
|
||||
private final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository;
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final RateRepositoryWrapper rateRepository;
|
||||
private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService;
|
||||
@@ -86,32 +84,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final DelinquencyBucketRepository delinquencyBucketRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final LoanProductDataValidator fromApiJsonDeserializer, final LoanProductRepository loanProductRepository,
|
||||
final AprCalculator aprCalculator, final FundRepository fundRepository,
|
||||
final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository,
|
||||
final ChargeRepositoryWrapper chargeRepository, final RateRepositoryWrapper rateRepository,
|
||||
final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService,
|
||||
final FineractEntityAccessUtil fineractEntityAccessUtil, final FloatingRateRepositoryWrapper floatingRateRepository,
|
||||
final LoanRepositoryWrapper loanRepositoryWrapper, final BusinessEventNotifierService businessEventNotifierService,
|
||||
final DelinquencyBucketRepository delinquencyBucketRepository) {
|
||||
this.context = context;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.loanProductRepository = loanProductRepository;
|
||||
this.aprCalculator = aprCalculator;
|
||||
this.fundRepository = fundRepository;
|
||||
this.loanTransactionProcessingStrategyRepository = loanTransactionProcessingStrategyRepository;
|
||||
this.chargeRepository = chargeRepository;
|
||||
this.rateRepository = rateRepository;
|
||||
this.accountMappingWritePlatformService = accountMappingWritePlatformService;
|
||||
this.fineractEntityAccessUtil = fineractEntityAccessUtil;
|
||||
this.floatingRateRepository = floatingRateRepository;
|
||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
this.delinquencyBucketRepository = delinquencyBucketRepository;
|
||||
}
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -126,9 +99,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
final Fund fund = findFundByIdIfProvided(command.longValueOfParameterNamed("fundId"));
|
||||
|
||||
final Long transactionProcessingStrategyId = command.longValueOfParameterNamed("transactionProcessingStrategyId");
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(
|
||||
transactionProcessingStrategyId);
|
||||
final String loanTransactionProcessingStrategyCode = command.stringValueOfParameterNamed("transactionProcessingStrategyCode");
|
||||
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
final List<Charge> charges = assembleListOfProductCharges(command, currencyCode);
|
||||
@@ -139,9 +110,11 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
floatingRate = this.floatingRateRepository
|
||||
.findOneWithNotFoundDetection(command.longValueOfParameterNamed("floatingRatesId"));
|
||||
}
|
||||
final LoanProduct loanProduct = LoanProduct.assembleFromJson(fund, loanTransactionProcessingStrategy, charges, command,
|
||||
final LoanProduct loanProduct = LoanProduct.assembleFromJson(fund, loanTransactionProcessingStrategyCode, charges, command,
|
||||
this.aprCalculator, floatingRate, rates);
|
||||
loanProduct.updateLoanProductInRelatedClasses();
|
||||
loanProduct.setTransactionProcessingStrategyName(
|
||||
loanRepaymentScheduleTransactionProcessorFactory.determineProcessor(loanTransactionProcessingStrategyCode).getName());
|
||||
|
||||
if (command.parameterExists("delinquencyBucketId")) {
|
||||
DelinquencyBucket delinquencyBucket = this.delinquencyBucketRepository
|
||||
@@ -177,15 +150,6 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
|
||||
}
|
||||
|
||||
private LoanTransactionProcessingStrategy findStrategyByIdIfProvided(final Long transactionProcessingStrategyId) {
|
||||
LoanTransactionProcessingStrategy strategy = null;
|
||||
if (transactionProcessingStrategyId != null) {
|
||||
return this.loanTransactionProcessingStrategyRepository.findById(transactionProcessingStrategyId)
|
||||
.orElseThrow(() -> new LoanTransactionProcessingStrategyNotFoundException(transactionProcessingStrategyId));
|
||||
}
|
||||
return strategy;
|
||||
}
|
||||
|
||||
private Fund findFundByIdIfProvided(final Long fundId) {
|
||||
Fund fund = null;
|
||||
if (fundId != null) {
|
||||
@@ -232,11 +196,12 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
product.setDelinquencyBucket(delinquencyBucket);
|
||||
}
|
||||
|
||||
if (changes.containsKey("transactionProcessingStrategyId")) {
|
||||
final Long transactionProcessingStrategyId = (Long) changes.get("transactionProcessingStrategyId");
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(
|
||||
transactionProcessingStrategyId);
|
||||
product.update(loanTransactionProcessingStrategy);
|
||||
if (changes.containsKey("transactionProcessingStrategyCode")) {
|
||||
final String transactionProcessingStrategyCode = (String) changes.get("transactionProcessingStrategyCode");
|
||||
final String transactionProcessingStrategyName = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(transactionProcessingStrategyCode).getName();
|
||||
product.setTransactionProcessingStrategyCode(transactionProcessingStrategyCode);
|
||||
product.setTransactionProcessingStrategyName(transactionProcessingStrategyName);
|
||||
}
|
||||
|
||||
if (changes.containsKey("charges")) {
|
||||
|
||||
+2
-2
@@ -204,9 +204,9 @@ public class SelfLoansApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Calculate Loan Repayment Schedule | Submit a new Loan Application", description = "Calculate Loan Repayment Schedule:\n\n"
|
||||
+ "Calculates Loan Repayment Schedule\n\n"
|
||||
+ "Mandatory Fields: productId, principal, loanTermFrequency, loanTermFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, expectedDisbursementDate, transactionProcessingStrategyId\n\n"
|
||||
+ "Mandatory Fields: productId, principal, loanTermFrequency, loanTermFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, expectedDisbursementDate, transactionProcessingStrategyCode\n\n"
|
||||
+ "Submit a new Loan Application:\n\n"
|
||||
+ "Mandatory Fields: clientId, productId, principal, loanTermFrequency, loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyId, expectedDisbursementDate, submittedOnDate, loanType\n\n"
|
||||
+ "Mandatory Fields: clientId, productId, principal, loanTermFrequency, loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, amortizationType, interestType, interestCalculationPeriodType, transactionProcessingStrategyCode, expectedDisbursementDate, submittedOnDate, loanType\n\n"
|
||||
+ "Additional Mandatory Fields if interest recalculation is enabled for product and Rest frequency not same as repayment period: recalculationRestFrequencyDate\n\n"
|
||||
+ "Additional Mandatory Fields if interest recalculation with interest/fee compounding is enabled for product and compounding frequency not same as repayment period: recalculationCompoundingFrequencyDate\n\n"
|
||||
+ "Additional Mandatory Field if Entity-Datatable Check is enabled for the entity of type loan: datatables\n\n"
|
||||
|
||||
+6
-6
@@ -482,8 +482,8 @@ final class SelfLoansApiResourceSwagger {
|
||||
public GetLoansLoanIdAmortizationType amortizationType;
|
||||
public GetLoansLoanIdInterestType interestType;
|
||||
public GetLoansLoanIdInterestCalculationPeriodType interestCalculationPeriodType;
|
||||
@Schema(example = "2")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
public GetLoansLoanIdTimeline timeline;
|
||||
public GetLoansLoanIdSummary summary;
|
||||
}
|
||||
@@ -694,8 +694,8 @@ final class SelfLoansApiResourceSwagger {
|
||||
public Integer interestType;
|
||||
@Schema(example = "1")
|
||||
public Integer interestCalculationPeriodType;
|
||||
@Schema(example = "1")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
@Schema(example = "10 Jun 2013")
|
||||
public String expectedDisbursementDate;
|
||||
@Schema(example = "10 Jun 2013")
|
||||
@@ -758,8 +758,8 @@ final class SelfLoansApiResourceSwagger {
|
||||
public Integer amortizationType;
|
||||
@Schema(example = "04 March 2014")
|
||||
public String expectedDisbursementDate;
|
||||
@Schema(example = "1")
|
||||
public Integer transactionProcessingStrategyId;
|
||||
@Schema(example = "mifos-standard-strategy")
|
||||
public String transactionProcessingStrategyCode;
|
||||
}
|
||||
|
||||
@Schema(description = "PutSelfLoansLoanIdResponse")
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ import org.springframework.stereotype.Component;
|
||||
+ "The minimum number of days allowed between a Loan disbursal and its first repayment.\n" + "principalThresholdForLastInstalment\n"
|
||||
+ "Field represents percentage of current instalment principal amount for comparing against principal outstanding to add another repayment instalment. If the outstanding principal amount is less then calculated amount, remaining outstanding amount will be added to current instalment. Default value for multi disburse loan is 50% and non-multi disburse loan is 0%\n"
|
||||
+ "canDefineInstallmentAmount\n" + "if provided as true, then fixed instalment amount can be provided from loan account.\n"
|
||||
+ "transactionProcessingStrategyId\n"
|
||||
+ "transactionProcessingStrategyCode\n"
|
||||
+ "An enumeration that indicates the type of transaction processing strategy to be used. This relates to functionality that is also known as Payment Application Logic.\n"
|
||||
+ "A number of out of the box approaches exist, some are custom to specific MFIs, some are more general and indicate the order in which payments are processed.\n"
|
||||
+ "\n"
|
||||
|
||||
@@ -61,6 +61,15 @@ fineract.events.external.producer.jms.broker-url=${FINERACT_EXTERNAL_EVENTS_PROD
|
||||
|
||||
fineract.idempotency-key-header-name=${FINERACT_IDEMPOTENCY_KEY_HEADER_NAME:Idempotency-Key}
|
||||
|
||||
fineract.loan.transactionprocessor.creocore.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_CREOCORE_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.early-repayment.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_EARLY_REPAYMENT_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.mifos-standard.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_MIFOS_STANDARD_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.heavensfamily.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_HEAVENSFAMILY_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.interest-principal-penalties-fees.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_INTEREST_PRINCIPAL_PENALTIES_FEES_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.principal-interest-penalties-fees.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_PRINCIPAL_INTEREST_PENALTIES_FEES_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.rbi-india.enabled=${FINERACT_LOAN_TRANSACTIONPROCESSOR_RBI_INDIA_ENABLED:true}
|
||||
fineract.loan.transactionprocessor.error-not-found-fail=${FINERACT_LOAN_TRANSACTIONPROCESSOR_ERROR_NOT_FOUND_FAIL:true}
|
||||
|
||||
# Logging pattern for the console
|
||||
logging.pattern.console=${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(%replace([%X{correlationId}]){'\\[\\]', ''}) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}}
|
||||
|
||||
|
||||
@@ -83,4 +83,5 @@
|
||||
<include file="parts/0061_add_idempotency_key_to_command_source.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0062_add_fraud_attribute_to_loan.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0063_add_permissions_for_external_event_configuration.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0064_refactor_loan_transaction_strategy.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<addColumn tableName="m_loan">
|
||||
<column defaultValue="-" name="loan_transaction_strategy_code" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column defaultValue="-" name="loan_transaction_strategy_name" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="mifos-standard-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Penalties, Fees, Interest, Principal order" />
|
||||
<where>loan_transaction_strategy_id = 1</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="heavensfamily-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="HeavensFamily Unique" />
|
||||
<where>loan_transaction_strategy_id = 2</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="creocore-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Creocore Unique" />
|
||||
<where>loan_transaction_strategy_id = 3</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="rbi-india-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Overdue/Due Fee/Int,Principal" />
|
||||
<where>loan_transaction_strategy_id = 4</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="principal-interest-penalties-fees-order-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Principal, Interest, Penalties, Fees Order" />
|
||||
<where>loan_transaction_strategy_id = 5</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="interest-principal-penalties-fees-order-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Interest, Principal, Penalties, Fees Order" />
|
||||
<where>loan_transaction_strategy_id = 6</where>
|
||||
</update>
|
||||
<update tableName="m_loan">
|
||||
<column name="loan_transaction_strategy_code" value="early-repayment-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Early Repayment Strategy" />
|
||||
<where>loan_transaction_strategy_id = 7</where>
|
||||
</update>
|
||||
<dropForeignKeyConstraint baseTableName="m_loan" constraintName="FK_loan_ltp_strategy" />
|
||||
<!--
|
||||
<dropColumn tableName="m_loan_product" columnName="loan_transaction_strategy_id" />
|
||||
-->
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2">
|
||||
<addColumn tableName="m_product_loan">
|
||||
<column defaultValue="-" name="loan_transaction_strategy_code" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column defaultValue="-" name="loan_transaction_strategy_name" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="mifos-standard-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Penalties, Fees, Interest, Principal order" />
|
||||
<where>loan_transaction_strategy_id = 1</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="heavensfamily-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="HeavensFamily Unique" />
|
||||
<where>loan_transaction_strategy_id = 2</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="creocore-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Creocore Unique" />
|
||||
<where>loan_transaction_strategy_id = 3</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="rbi-india-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Overdue/Due Fee/Int,Principal" />
|
||||
<where>loan_transaction_strategy_id = 4</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="principal-interest-penalties-fees-order-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Principal, Interest, Penalties, Fees Order" />
|
||||
<where>loan_transaction_strategy_id = 5</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="interest-principal-penalties-fees-order-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Interest, Principal, Penalties, Fees Order" />
|
||||
<where>loan_transaction_strategy_id = 6</where>
|
||||
</update>
|
||||
<update tableName="m_product_loan">
|
||||
<column name="loan_transaction_strategy_code" value="early-repayment-strategy" />
|
||||
<column name="loan_transaction_strategy_name" value="Early Repayment Strategy" />
|
||||
<where>loan_transaction_strategy_id = 7</where>
|
||||
</update>
|
||||
<dropForeignKeyConstraint baseTableName="m_product_loan" constraintName="FK_ltp_strategy" />
|
||||
<!--
|
||||
<dropColumn tableName="m_product_loan" columnName="loan_transaction_strategy_id" />
|
||||
-->
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="3">
|
||||
<renameColumn tableName="m_product_loan_configurable_attributes" oldColumnName="loan_transaction_strategy_id" newColumnName="loan_transaction_strategy_code" columnDataType="BOOLEAN" />
|
||||
</changeSet>
|
||||
<!--
|
||||
<changeSet author="fineract" id="4">
|
||||
<dropTable tableName="ref_loan_transaction_processing_strategy" />
|
||||
</changeSet>
|
||||
-->
|
||||
</databaseChangeLog>
|
||||
@@ -2266,7 +2266,6 @@ CREATE TABLE IF NOT EXISTS `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -2284,7 +2283,6 @@ CREATE TABLE IF NOT EXISTS `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -3971,9 +3969,7 @@ CREATE TABLE IF NOT EXISTS `m_product_loan` (
|
||||
UNIQUE KEY `unq_short_name` (`short_name`),
|
||||
UNIQUE KEY `external_id_UNIQUE` (`external_id`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
-- Dumping data for table fineract_default.m_product_loan: ~0 rows (approximately)
|
||||
@@ -5494,30 +5490,6 @@ INSERT INTO `ppi_scores` (`id`, `score_from`, `score_to`) VALUES
|
||||
/*!40000 ALTER TABLE `ppi_scores` ENABLE KEYS */;
|
||||
|
||||
|
||||
-- Dumping structure for table fineract_default.ref_loan_transaction_processing_strategy
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
CREATE TABLE IF NOT EXISTS `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`sort_order` INT DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
-- Dumping data for table fineract_default.ref_loan_transaction_processing_strategy: ~7 rows (approximately)
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` (`id`, `code`, `name`, `sort_order`) VALUES
|
||||
(1, 'mifos-standard-strategy', 'Penalties, Fees, Interest, Principal order', 1),
|
||||
(2, 'heavensfamily-strategy', 'HeavensFamily Unique', 6),
|
||||
(3, 'creocore-strategy', 'Creocore Unique', 7),
|
||||
(4, 'rbi-india-strategy', 'Overdue/Due Fee/Int,Principal', 2),
|
||||
(5, 'principal-interest-penalties-fees-order-strategy', 'Principal, Interest, Penalties, Fees Order', 3),
|
||||
(6, 'interest-principal-penalties-fees-order-strategy', 'Interest, Principal, Penalties, Fees Order', 4),
|
||||
(7, 'early-repayment-strategy', 'Early Repayment Strategy', 5);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
|
||||
|
||||
-- Dumping structure for table fineract_default.rpt_sequence
|
||||
DROP TABLE IF EXISTS `rpt_sequence`;
|
||||
CREATE TABLE IF NOT EXISTS `rpt_sequence` (
|
||||
|
||||
+3
-31
@@ -2406,7 +2406,6 @@ CREATE TABLE IF NOT EXISTS `m_loan` (
|
||||
KEY `FKB6F935D87179A0CB` (`client_id`),
|
||||
KEY `FKB6F935D8C8D4B434` (`product_id`),
|
||||
KEY `FK7C885877240145` (`fund_id`),
|
||||
KEY `FK_loan_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
KEY `FK_m_loan_m_staff` (`loan_officer_id`),
|
||||
KEY `group_id` (`group_id`),
|
||||
KEY `FK_m_loanpurpose_codevalue` (`loanpurpose_cv_id`),
|
||||
@@ -2424,7 +2423,6 @@ CREATE TABLE IF NOT EXISTS `m_loan` (
|
||||
CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
CONSTRAINT `FK_loan_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`),
|
||||
CONSTRAINT `FK_m_loan_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `FK_m_loanpurpose_codevalue` FOREIGN KEY (`loanpurpose_cv_id`) REFERENCES `m_code_value` (`id`),
|
||||
CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`),
|
||||
@@ -4104,7 +4102,7 @@ INSERT INTO `m_portfolio_command_source` (`id`, `action_name`, `entity_name`, `o
|
||||
(24, 'CREATE', 'USER', 1, NULL, NULL, NULL, NULL, '/users/template', 5, NULL, '{"sendPasswordToEmail":true,"officeId":1,"username":"janej","firstname":"Jane","lastname":"J","email":"janej@123.com","roles":["1"]}', 1, '2014-03-07 20:07:48', NULL, NULL, 1, NULL, NULL),
|
||||
(25, 'CREATE', 'STAFF', 3, NULL, NULL, NULL, NULL, '/staff/template', 3, NULL, '{"isLoanOfficer":true,"officeId":3,"firstname":"John","lastname":"K"}', 1, '2014-03-07 20:08:28', NULL, NULL, 1, NULL, NULL),
|
||||
(26, 'CREATE', 'FUND', NULL, NULL, NULL, NULL, NULL, '/funds/template', 1, NULL, '{"name":"Loan from Central Bank"}', 1, '2014-03-10 10:11:50', NULL, NULL, 1, NULL, NULL),
|
||||
(27, 'CREATE', 'LOANPRODUCT', NULL, NULL, NULL, NULL, NULL, '/loanproducts/template', 1, NULL, '{"currencyCode":"USD","includeInBorrowerCycle":"false","useBorrowerCycle":"false","digitsAfterDecimal":"2","inMultiplesOf":"0","repaymentFrequencyType":1,"interestRateFrequencyType":3,"amortizationType":1,"interestType":1,"interestCalculationPeriodType":1,"transactionProcessingStrategyId":1,"principalVariationsForBorrowerCycle":[],"interestRateVariationsForBorrowerCycle":[],"numberOfRepaymentVariationsForBorrowerCycle":[],"multiDisburseLoan":false,"fundSourceAccountId":31,"loanPortfolioAccountId":32,"transfersInSuspenseAccountId":33,"interestOnLoanAccountId":36,"incomeFromFeeAccountId":37,"incomeFromPenaltyAccountId":38,"writeOffAccountId":41,"overpaymentLiabilityAccountId":30,"accountingRule":"2","name":"Income Generating Loan","shortName":"IGL","fundId":1,"minPrincipal":"10000","principal":"10000","maxPrincipal":"10000","minNumberOfRepayments":"25","numberOfRepayments":"25","maxNumberOfRepayments":"25","repaymentEvery":"1","minInterestRatePerPeriod":"26","interestRatePerPeriod":"26","maxInterestRatePerPeriod":"26","paymentChannelToFundSourceMappings":[],"feeToIncomeAccountMappings":[],"penaltyToIncomeAccountMappings":[],"charges":[],"dateFormat":"dd MMMM yyyy","locale":"en","startDate":"01 January 2010"}', 1, '2014-03-10 10:16:39', NULL, NULL, 1, NULL, NULL),
|
||||
(27, 'CREATE', 'LOANPRODUCT', NULL, NULL, NULL, NULL, NULL, '/loanproducts/template', 1, NULL, '{"currencyCode":"USD","includeInBorrowerCycle":"false","useBorrowerCycle":"false","digitsAfterDecimal":"2","inMultiplesOf":"0","repaymentFrequencyType":1,"interestRateFrequencyType":3,"amortizationType":1,"interestType":1,"interestCalculationPeriodType":1,"transactionProcessingStrategyCode":"mifos-standard-strategy","principalVariationsForBorrowerCycle":[],"interestRateVariationsForBorrowerCycle":[],"numberOfRepaymentVariationsForBorrowerCycle":[],"multiDisburseLoan":false,"fundSourceAccountId":31,"loanPortfolioAccountId":32,"transfersInSuspenseAccountId":33,"interestOnLoanAccountId":36,"incomeFromFeeAccountId":37,"incomeFromPenaltyAccountId":38,"writeOffAccountId":41,"overpaymentLiabilityAccountId":30,"accountingRule":"2","name":"Income Generating Loan","shortName":"IGL","fundId":1,"minPrincipal":"10000","principal":"10000","maxPrincipal":"10000","minNumberOfRepayments":"25","numberOfRepayments":"25","maxNumberOfRepayments":"25","repaymentEvery":"1","minInterestRatePerPeriod":"26","interestRatePerPeriod":"26","maxInterestRatePerPeriod":"26","paymentChannelToFundSourceMappings":[],"feeToIncomeAccountMappings":[],"penaltyToIncomeAccountMappings":[],"charges":[],"dateFormat":"dd MMMM yyyy","locale":"en","startDate":"01 January 2010"}', 1, '2014-03-10 10:16:39', NULL, NULL, 1, NULL, NULL),
|
||||
(28, 'CREATE', 'SAVINGSPRODUCT', NULL, NULL, NULL, NULL, NULL, '/savingsproducts/template', 1, NULL, '{"currencyCode":"USD","digitsAfterDecimal":2,"interestCompoundingPeriodType":1,"interestPostingPeriodType":4,"interestCalculationType":1,"interestCalculationDaysInYearType":365,"savingsReferenceAccountId":31,"overdraftPortfolioControlId":32,"savingsControlAccountId":30,"incomeFromFeeAccountId":36,"incomeFromPenaltyAccountId":37,"incomeFromInterestId":38,"interestOnSavingsAccountId":41,"writeOffAccountId":42,"accountingRule":"2","name":"Voluntary savings","shortName":"VS","description":"Save money","inMultiplesOf":"0","nominalAnnualInterestRate":"9.5","minRequiredOpeningBalance":"1000","lockinPeriodFrequency":"1","lockinPeriodFrequencyType":1,"withdrawalFeeForTransfers":"false","paymentChannelToFundSourceMappings":[],"feeToIncomeAccountMappings":[],"penaltyToIncomeAccountMappings":[],"charges":[],"locale":"en","transfersInSuspenseAccountId":30}', 1, '2014-03-10 10:21:16', NULL, NULL, 1, NULL, NULL),
|
||||
(29, 'UPDATE', 'SAVINGSPRODUCT', NULL, NULL, NULL, NULL, NULL, '/savingsproducts/1', 1, NULL, '{"shortName":"VS","penaltyToIncomeAccountMappings":"[]","paymentChannelToFundSourceMappings":"[]","feeToIncomeAccountMappings":"[]"}', 1, '2014-03-10 10:21:51', NULL, NULL, 1, NULL, NULL),
|
||||
(30, 'CREATE', 'CODEVALUE', NULL, NULL, NULL, NULL, NULL, '/codes/3/codevalues/template', 10, NULL, '{"name":"Cattle Rearing","position":"104"}', 1, '2014-03-10 10:27:02', NULL, NULL, 1, NULL, NULL),
|
||||
@@ -4145,7 +4143,7 @@ INSERT INTO `m_portfolio_command_source` (`id`, `action_name`, `entity_name`, `o
|
||||
(65, 'UPDATE', 'GLACCOUNT', NULL, NULL, NULL, NULL, NULL, '/glaccounts/2', 2, NULL, '{"usage":1}', 1, '2014-05-01 16:25:56', NULL, NULL, 1, NULL, NULL),
|
||||
(66, 'UPDATE', 'LOANPRODUCT', NULL, NULL, NULL, NULL, NULL, '/loanproducts/1', 1, NULL, '{"inMultiplesOf":0,"penaltyToIncomeAccountMappings":"[]","paymentChannelToFundSourceMappings":"[]","feeToIncomeAccountMappings":"[]"}', 1, '2014-05-01 16:26:06', NULL, NULL, 1, NULL, NULL),
|
||||
(67, 'UPDATE', 'LOANPRODUCT', NULL, NULL, NULL, NULL, NULL, '/loanproducts/1', 1, NULL, '{"inMultiplesOf":0,"overpaymentLiabilityAccountId":2,"penaltyToIncomeAccountMappings":"[]","paymentChannelToFundSourceMappings":"[]","transfersInSuspenseAccountId":17,"feeToIncomeAccountMappings":"[]"}', 1, '2014-05-01 16:26:37', NULL, NULL, 1, NULL, NULL),
|
||||
(68, 'CREATE', 'LOAN', 2, NULL, 8, 1, NULL, '/loans', 1, NULL, '{"clientId":"8","productId":1,"disbursementData":[],"fundId":1,"principal":10000,"loanTermFrequency":25,"loanTermFrequencyType":1,"numberOfRepayments":25,"repaymentEvery":1,"repaymentFrequencyType":1,"interestRatePerPeriod":26,"amortizationType":1,"interestType":1,"interestCalculationPeriodType":1,"transactionProcessingStrategyId":1,"locale":"en","dateFormat":"dd MMMM yyyy","loanType":"individual","expectedDisbursementDate":"16 June 2014","submittedOnDate":"02 June 2014","charges":[{"chargeId":1,"amount":500}]}', 1, '2014-06-11 09:17:45', NULL, NULL, 1, NULL, NULL),
|
||||
(68, 'CREATE', 'LOAN', 2, NULL, 8, 1, NULL, '/loans', 1, NULL, '{"clientId":"8","productId":1,"disbursementData":[],"fundId":1,"principal":10000,"loanTermFrequency":25,"loanTermFrequencyType":1,"numberOfRepayments":25,"repaymentEvery":1,"repaymentFrequencyType":1,"interestRatePerPeriod":26,"amortizationType":1,"interestType":1,"interestCalculationPeriodType":1,"transactionProcessingStrategyCode":"mifos-standard-strategy","locale":"en","dateFormat":"dd MMMM yyyy","loanType":"individual","expectedDisbursementDate":"16 June 2014","submittedOnDate":"02 June 2014","charges":[{"chargeId":1,"amount":500}]}', 1, '2014-06-11 09:17:45', NULL, NULL, 1, NULL, NULL),
|
||||
(69, 'APPROVE', 'LOAN', 2, NULL, 8, 1, NULL, '/loans/1', 1, NULL, '{"status":{"id":200,"code":"loanStatusType.approved","value":"Approved","pendingApproval":false,"waitingForDisbursal":true,"active":false,"closedObligationsMet":false,"closedWrittenOff":false,"closedRescheduled":false,"closed":false,"overpaid":false},"locale":"en","dateFormat":"dd MMMM yyyy","approvedOnDate":"11 June 2014"}', 1, '2014-06-11 09:18:16', NULL, NULL, 1, NULL, NULL),
|
||||
(70, 'CREATE', 'FINANCIALACTIVITYACCOUNT', NULL, NULL, NULL, NULL, NULL, '/organizationglaccounts/template', 2, NULL, '{"financialActivityId":100,"glAccountId":33}', 1, '2014-06-16 16:54:20', NULL, NULL, 1, NULL, NULL),
|
||||
(71, 'UPDATE', 'FINANCIALACTIVITYACCOUNT', NULL, NULL, NULL, NULL, NULL, '/organizationglaccounts/2', 2, NULL, '{"glAccountId":32}', 1, '2014-06-16 16:57:17', NULL, NULL, 1, NULL, NULL),
|
||||
@@ -4216,9 +4214,7 @@ CREATE TABLE IF NOT EXISTS `m_product_loan` (
|
||||
UNIQUE KEY `unq_short_name` (`short_name`),
|
||||
UNIQUE KEY `external_id_UNIQUE` (`external_id`),
|
||||
KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
KEY `FK_ltp_strategy` (`loan_transaction_strategy_id`),
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`),
|
||||
CONSTRAINT `FK_ltp_strategy` FOREIGN KEY (`loan_transaction_strategy_id`) REFERENCES `ref_loan_transaction_processing_strategy` (`id`)
|
||||
CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `m_fund` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
-- Dumping data for table mifostenant-reference.m_product_loan: ~1 rows (approximately)
|
||||
@@ -5751,30 +5747,6 @@ INSERT INTO `ppi_scores` (`id`, `score_from`, `score_to`) VALUES
|
||||
/*!40000 ALTER TABLE `ppi_scores` ENABLE KEYS */;
|
||||
|
||||
|
||||
-- Dumping structure for table mifostenant-reference.ref_loan_transaction_processing_strategy
|
||||
DROP TABLE IF EXISTS `ref_loan_transaction_processing_strategy`;
|
||||
CREATE TABLE IF NOT EXISTS `ref_loan_transaction_processing_strategy` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`code` varchar(100) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`sort_order` INT DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `ltp_strategy_code` (`code`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=UTF8MB4;
|
||||
|
||||
-- Dumping data for table mifostenant-reference.ref_loan_transaction_processing_strategy: ~7 rows (approximately)
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` DISABLE KEYS */;
|
||||
INSERT INTO `ref_loan_transaction_processing_strategy` (`id`, `code`, `name`, `sort_order`) VALUES
|
||||
(1, 'mifos-standard-strategy', 'Penalties, Fees, Interest, Principal order', 1),
|
||||
(2, 'heavensfamily-strategy', 'HeavensFamily Unique', 6),
|
||||
(3, 'creocore-strategy', 'Creocore Unique', 7),
|
||||
(4, 'rbi-india-strategy', 'Overdue/Due Fee/Int,Principal', 2),
|
||||
(5, 'principal-interest-penalties-fees-order-strategy', 'Principal, Interest, Penalties, Fees Order', 3),
|
||||
(6, 'interest-principal-penalties-fees-order-strategy', 'Interest, Principal, Penalties, Fees Order', 4),
|
||||
(7, 'early-repayment-strategy', 'Early Repayment Strategy', 5);
|
||||
/*!40000 ALTER TABLE `ref_loan_transaction_processing_strategy` ENABLE KEYS */;
|
||||
|
||||
|
||||
-- Dumping structure for table mifostenant-reference.rpt_sequence
|
||||
DROP TABLE IF EXISTS `rpt_sequence`;
|
||||
CREATE TABLE IF NOT EXISTS `rpt_sequence` (
|
||||
|
||||
@@ -4740,7 +4740,7 @@ Content-Type: application/json Request Body:
|
||||
\"amortizationType\": 1,
|
||||
\"interestType\": 0,
|
||||
\"interestCalculationPeriodType\": 1,
|
||||
\"transactionProcessingStrategyId\": 1,
|
||||
\"transactionProcessingStrategyCode\": \"mifos-standard-strategy\",
|
||||
\"expectedDisbursementDate\": \"10 Jun 2013\",
|
||||
\"submittedOnDate\": \"10 Jun 2013\"
|
||||
}"
|
||||
@@ -10339,7 +10339,7 @@ GET https://DomainName/fineract-provider/api/v1/groups/{groupId}/glimaccounts
|
||||
</td>
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>transactionProcessingStrategyId</td>
|
||||
<td>transactionProcessingStrategyCode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
@@ -10541,7 +10541,7 @@ GET https://DomainName/api/v1/loans/template?templateType=individual&clientId=1&
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"timeline": {
|
||||
"expectedDisbursementDate": [
|
||||
2013,
|
||||
@@ -10973,7 +10973,7 @@ GET https://DomainName/api/v1/loans/{loanId}
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"timeline": {
|
||||
"submittedOnDate": [
|
||||
2012,
|
||||
@@ -11265,7 +11265,7 @@ GET https://DomainName/fineract-provider/api/v1/loans
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"timeline": {
|
||||
"submittedOnDate": [
|
||||
2012,
|
||||
@@ -11417,7 +11417,7 @@ No Request Body:
|
||||
"interestCalculationPeriodType": 0,
|
||||
"amortizationType": 1,
|
||||
"expectedDisbursementDate": "04 March 2014",
|
||||
"transactionProcessingStrategyId": 1
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -11449,7 +11449,7 @@ No Request Body:
|
||||
repaymentFrequencyType, interestRatePerPeriod,
|
||||
amortizationType, interestType,
|
||||
interestCalculationPeriodType, expectedDisbursementDate,
|
||||
transactionProcessingStrategyId</td>
|
||||
transactionProcessingStrategyCode</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -11476,7 +11476,7 @@ Request Body:
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"expectedDisbursementDate": "20 September 2011",
|
||||
"transactionProcessingStrategyId": 2
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -11598,7 +11598,7 @@ Request Body:
|
||||
loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery,
|
||||
repaymentFrequencyType, interestRatePerPeriod,
|
||||
amortizationType, interestType,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyId,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyCode,
|
||||
expectedDisbursementDate, submittedOnDate, loanType</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -11663,7 +11663,7 @@ Request Body:
|
||||
"amortizationType": 1,
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"expectedDisbursementDate": "10 Jun 2013",
|
||||
"submittedOnDate": "10 Jun 2013",
|
||||
"linkAccountId" : "1",
|
||||
@@ -12222,7 +12222,7 @@ Content-Type: application/json
|
||||
</tr>
|
||||
<tr class=alt>
|
||||
<td>interestRatePerPeriod, expectedDisbursementDate, clientId, groupId, productId, totalLoan, loanType, interestType,
|
||||
principal, charges, transactionProcessingStrategyId, submittedOnDate, amortizationType, repaymentFrequencyType,
|
||||
principal, charges, transactionProcessingStrategyCode, submittedOnDate, amortizationType, repaymentFrequencyType,
|
||||
loanTermFrequencyType, loanTermFrequency, repaymentEvery, numberOfRepayments, interestCalculationPeriodType,
|
||||
isParentAccount, locale,dateFormat</td>
|
||||
</tr>
|
||||
@@ -12250,7 +12250,7 @@ Request Body:
|
||||
"locale":"en_GB",
|
||||
"principal":"1000.00",
|
||||
"charges":[],
|
||||
"transactionProcessingStrategyId":"1",
|
||||
"transactionProcessingStrategyCode":"mifos-standard-strategy",
|
||||
"submittedOnDate":"10 June 2020",
|
||||
"amortizationType":"1",
|
||||
"repaymentFrequencyType":"2",
|
||||
@@ -15740,7 +15740,7 @@ Request Body:
|
||||
|
||||
|
||||
<tr class=alt>
|
||||
<td>transactionProcessingStrategyId</td>
|
||||
<td>transactionProcessingStrategyCode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
@@ -15986,7 +15986,7 @@ GET https://DomainName/api/v1/loanproducts
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"principalVariationsForBorrowerCycle": [],
|
||||
"interestRateVariationsForBorrowerCycle": [],
|
||||
@@ -16989,7 +16989,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"charges": [],
|
||||
"principalVariationsForBorrowerCycle": [
|
||||
@@ -17162,7 +17162,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
|
||||
<td>name, shortName, currencyCode, digitsAfterDecimal, inMultiplesOf, principal,
|
||||
numberOfRepayments, repaymentEvery, repaymentFrequencyType,
|
||||
interestRatePerPeriod, interestRateFrequencyType, amortizationType, interestType,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyId,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyCode,
|
||||
accountingRule, isInterestRecalculationEnabled, daysInYearType, daysInMonthType</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -17277,7 +17277,7 @@ Request Body:
|
||||
"amortizationType":1,
|
||||
"interestType":0,
|
||||
"interestCalculationPeriodType":1,
|
||||
"transactionProcessingStrategyId":1,
|
||||
"transactionProcessingStrategyCode":"mifos-standard-strategy",
|
||||
"principalVariationsForBorrowerCycle":[],
|
||||
"interestRateVariationsForBorrowerCycle":[],
|
||||
"numberOfRepaymentVariationsForBorrowerCycle":[
|
||||
@@ -17299,7 +17299,7 @@ Request Body:
|
||||
"allowAttributeOverrides":
|
||||
{amortizationType : true,
|
||||
interestType : true,
|
||||
transactionProcessingStrategyId : false,
|
||||
transactionProcessingStrategyCode : false,
|
||||
interestCalculationPeriodType : true,
|
||||
inArrearsTolerance : false,
|
||||
repaymentEvery : true,
|
||||
@@ -17355,7 +17355,7 @@ Request Body:
|
||||
"numberOfRepayments": "12",
|
||||
"repaymentEvery": "1",
|
||||
"repaymentFrequencyType": 2,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"interestRatePerPeriod": "1.75",
|
||||
"interestRateFrequencyType": 2,
|
||||
"amortizationType": 1,
|
||||
@@ -17422,7 +17422,7 @@ Request Body:
|
||||
"numberOfRepayments": "12",
|
||||
"repaymentEvery": "1",
|
||||
"repaymentFrequencyType": 2,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"interestRatePerPeriod": "1.75",
|
||||
"interestRateFrequencyType": 2,
|
||||
"amortizationType": 1,
|
||||
@@ -47942,7 +47942,7 @@ GET https://DomainName/api/v1/self/loans/template?templateType=individual&client
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"timeline": {
|
||||
"expectedDisbursementDate": [
|
||||
2013,
|
||||
@@ -48192,7 +48192,7 @@ GET https://DomainName/api/v1/self/loans/template?templateType=individual&client
|
||||
repaymentFrequencyType, interestRatePerPeriod,
|
||||
amortizationType, interestType,
|
||||
interestCalculationPeriodType, expectedDisbursementDate,
|
||||
transactionProcessingStrategyId</td>
|
||||
transactionProcessingStrategyCode</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -48219,7 +48219,7 @@ Request Body:
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"expectedDisbursementDate": "20 September 2011",
|
||||
"transactionProcessingStrategyId": 2
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -48343,7 +48343,7 @@ Request Body:
|
||||
loanTermFrequencyType, loanType, numberOfRepayments, repaymentEvery,
|
||||
repaymentFrequencyType, interestRatePerPeriod,
|
||||
amortizationType, interestType,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyId,
|
||||
interestCalculationPeriodType, transactionProcessingStrategyCode,
|
||||
expectedDisbursementDate, submittedOnDate, loanType</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -48400,7 +48400,7 @@ Request Body:
|
||||
"amortizationType": 1,
|
||||
"interestType": 0,
|
||||
"interestCalculationPeriodType": 1,
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"expectedDisbursementDate": "10 Jun 2013",
|
||||
"submittedOnDate": "10 Jun 2013",
|
||||
"linkAccountId" : "1",
|
||||
@@ -48553,7 +48553,7 @@ GET https://DomainName/api/v1/self/loans/{loanId}
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 2,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"timeline": {
|
||||
"submittedOnDate": [
|
||||
2012,
|
||||
@@ -48722,7 +48722,7 @@ No Request Body:
|
||||
"interestCalculationPeriodType": 0,
|
||||
"amortizationType": 1,
|
||||
"expectedDisbursementDate": "04 March 2014",
|
||||
"transactionProcessingStrategyId": 1
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy"
|
||||
}
|
||||
</code>
|
||||
<code class="method-response">
|
||||
@@ -51635,7 +51635,7 @@ No Request Body:
|
||||
|
||||
|
||||
<tr class=alt>
|
||||
<td>transactionProcessingStrategyId</td>
|
||||
<td>transactionProcessingStrategyCode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=fielddesc>
|
||||
@@ -51929,7 +51929,7 @@ GET https://DomainName/api/v1/self/loanproducts/{productId}?clientId={clientId}
|
||||
"code": "interestCalculationPeriodType.same.as.repayment.period",
|
||||
"value": "Same as repayment period"
|
||||
},
|
||||
"transactionProcessingStrategyId": 1,
|
||||
"transactionProcessingStrategyCode": "mifos-standard-strategy",
|
||||
"transactionProcessingStrategyName": "Mifos style",
|
||||
"charges": [],
|
||||
"principalVariationsForBorrowerCycle": [
|
||||
|
||||
@@ -51,6 +51,15 @@ fineract.events.external.producer.jms.enabled=${FINERACT_EXTERNAL_EVENTS_PRODUCE
|
||||
fineract.events.external.producer.jms.event-queue-name=${FINERACT_EXTERNAL_EVENTS_PRODUCER_JMS_QUEUE_NAME:JMS-event-queue}
|
||||
fineract.events.external.producer.jms.broker-url=${FINERACT_EXTERNAL_EVENTS_PRODUCER_JMS_BROKER_URL:tcp://127.0.0.1:61616}
|
||||
|
||||
fineract.loan.transactionprocessor.creocore.enabled=true
|
||||
fineract.loan.transactionprocessor.early-repayment.enabled=true
|
||||
fineract.loan.transactionprocessor.mifos-standard.enabled=true
|
||||
fineract.loan.transactionprocessor.heavensfamily.enabled=true
|
||||
fineract.loan.transactionprocessor.interest-principal-penalties-fees.enabled=true
|
||||
fineract.loan.transactionprocessor.principal-interest-penalties-fees.enabled=true
|
||||
fineract.loan.transactionprocessor.rbi-india.enabled=true
|
||||
fineract.loan.transactionprocessor.error-not-found-fail=true
|
||||
|
||||
|
||||
management.health.jms.enabled=false
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ configurations {
|
||||
driver
|
||||
}
|
||||
dependencies {
|
||||
driver 'mysql:mysql-connector-java:8.0.30'
|
||||
driver 'mysql:mysql-connector-java:8.0.31'
|
||||
}
|
||||
|
||||
cargo {
|
||||
|
||||
@@ -37,7 +37,7 @@ configurations {
|
||||
driver
|
||||
}
|
||||
dependencies {
|
||||
driver 'mysql:mysql-connector-java:8.0.30'
|
||||
driver 'mysql:mysql-connector-java:8.0.31'
|
||||
}
|
||||
|
||||
cargo {
|
||||
|
||||
+2
-2
@@ -6299,7 +6299,7 @@ public class ClientLoanIntegrationTest {
|
||||
private void validateIfValuesAreNotOverridden(Integer loanID, Integer loanProductID) {
|
||||
String loanProductDetails = this.loanTransactionHelper.getLoanProductDetails(this.requestSpec, this.responseSpec, loanProductID);
|
||||
String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, loanID);
|
||||
List<String> comparisonAttributes = Arrays.asList("amortizationType", "interestType", "transactionProcessingStrategyId",
|
||||
List<String> comparisonAttributes = Arrays.asList("amortizationType", "interestType", "transactionProcessingStrategyCode",
|
||||
"interestCalculationPeriodType", "repaymentFrequencyType", "graceOnPrincipalPayment", "graceOnInterestPayment",
|
||||
"inArrearsTolerance", "graceOnArrearsAgeing");
|
||||
|
||||
@@ -6313,7 +6313,7 @@ public class ClientLoanIntegrationTest {
|
||||
private JsonObject createLoanProductConfigurationDetail(JsonObject loanProductConfiguration, Boolean bool) {
|
||||
loanProductConfiguration.addProperty("amortizationType", bool);
|
||||
loanProductConfiguration.addProperty("interestType", bool);
|
||||
loanProductConfiguration.addProperty("transactionProcessingStrategyId", bool);
|
||||
loanProductConfiguration.addProperty("transactionProcessingStrategyCode", bool);
|
||||
loanProductConfiguration.addProperty("interestCalculationPeriodType", bool);
|
||||
loanProductConfiguration.addProperty("inArrearsTolerance", bool);
|
||||
loanProductConfiguration.addProperty("repaymentEvery", bool);
|
||||
|
||||
+3
-2
@@ -275,7 +275,8 @@ public final class BatchHelper {
|
||||
+ "\"loanTermFrequencyType\": 2, \"loanType\": \"individual\", \"numberOfRepayments\": 10,"
|
||||
+ "\"repaymentEvery\": 1, \"repaymentFrequencyType\": 2, \"interestRatePerPeriod\": 10,"
|
||||
+ "\"amortizationType\": 1, \"interestType\": 0, \"interestCalculationPeriodType\": 1,"
|
||||
+ "\"transactionProcessingStrategyId\": 1, \"expectedDisbursementDate\": \"" + dateString + "\",";
|
||||
+ "\"transactionProcessingStrategyCode\": \"mifos-standard-strategy\", \"expectedDisbursementDate\": \"" + dateString
|
||||
+ "\",";
|
||||
|
||||
if (clientCollateralId != null) {
|
||||
body = body + "\"collateral\": [{\"clientCollateralId\": \"" + clientCollateralId + "\", \"quantity\": \"1\"}],";
|
||||
@@ -313,7 +314,7 @@ public final class BatchHelper {
|
||||
+ "\"loanTermFrequencyType\": 2, \"loanType\": \"individual\", \"numberOfRepayments\": 10,"
|
||||
+ "\"repaymentEvery\": 1, \"repaymentFrequencyType\": 2, \"interestRatePerPeriod\": 10,"
|
||||
+ "\"amortizationType\": 1, \"interestType\": 0, \"interestCalculationPeriodType\": 1,"
|
||||
+ "\"transactionProcessingStrategyId\": 1, \"expectedDisbursementDate\": \"10 Jun 2013\","
|
||||
+ "\"transactionProcessingStrategyCode\": \"mifos-standard-strategy\", \"expectedDisbursementDate\": \"10 Jun 2013\","
|
||||
+ "\"submittedOnDate\": \"10 Jun 2013\"}", clientId, productId);
|
||||
|
||||
br.setBody(body);
|
||||
|
||||
+7
-7
@@ -39,9 +39,9 @@ public class LoanApplicationTestBuilder {
|
||||
private static final String EQUAL_INSTALLMENTS = "1";
|
||||
private static final String CALCULATION_PERIOD_SAME_AS_REPAYMENT_PERIOD = "1";
|
||||
private static final String LOCALE = "en_GB";
|
||||
public static final String DEFAULT_STRATEGY = "1";
|
||||
public static final String RBI_INDIA_STRATEGY = "4";
|
||||
public static final String INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY = "6";
|
||||
public static final String DEFAULT_STRATEGY = "mifos-standard-strategy";
|
||||
public static final String RBI_INDIA_STRATEGY = "rbi-india-strategy";
|
||||
public static final String INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY = "interest-principal-penalties-fees-order-strategy";
|
||||
|
||||
private String externalId = null;
|
||||
private String principal = "10,000";
|
||||
@@ -56,7 +56,7 @@ public class LoanApplicationTestBuilder {
|
||||
private String interestType = FLAT_BALANCE;
|
||||
private String amortizationType = EQUAL_PRINCIPAL_PAYMENTS;
|
||||
private String interestCalculationPeriodType = CALCULATION_PERIOD_SAME_AS_REPAYMENT_PERIOD;
|
||||
private String transactionProcessingID = DEFAULT_STRATEGY;
|
||||
private String transactionProcessingCode = DEFAULT_STRATEGY;
|
||||
private String expectedDisbursmentDate = "";
|
||||
private String submittedOnDate = "";
|
||||
private String loanType = "individual";
|
||||
@@ -147,7 +147,7 @@ public class LoanApplicationTestBuilder {
|
||||
map.put("fixedPrincipalPercentagePerInstallment", fixedPrincipalPercentagePerInstallment);
|
||||
map.put("interestType", this.interestType);
|
||||
map.put("interestCalculationPeriodType", this.interestCalculationPeriodType);
|
||||
map.put("transactionProcessingStrategyId", this.transactionProcessingID);
|
||||
map.put("transactionProcessingStrategyCode", this.transactionProcessingCode);
|
||||
map.put("expectedDisbursementDate", this.expectedDisbursmentDate);
|
||||
map.put("submittedOnDate", this.submittedOnDate);
|
||||
map.put("loanType", this.loanType);
|
||||
@@ -335,8 +335,8 @@ public class LoanApplicationTestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanApplicationTestBuilder withRepaymentStrategy(final String transactionProcessingStrategy) {
|
||||
this.transactionProcessingID = transactionProcessingStrategy;
|
||||
public LoanApplicationTestBuilder withRepaymentStrategy(final String transactionProcessingStrategyCode) {
|
||||
this.transactionProcessingCode = transactionProcessingStrategyCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -40,11 +40,11 @@ public class LoanProductTestBuilder {
|
||||
private static final String EQUAL_INSTALLMENTS = "1";
|
||||
private static final String DECLINING_BALANCE = "0";
|
||||
private static final String FLAT_BALANCE = "1";
|
||||
public static final String DEFAULT_STRATEGY = "1";
|
||||
public static final String INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY = "6";
|
||||
// private static final String HEAVENS_FAMILY_STRATEGY ="2";
|
||||
// private static final String CREO_CORE_STRATEGY ="3";
|
||||
public static final String RBI_INDIA_STRATEGY = "4";
|
||||
public static final String DEFAULT_STRATEGY = "mifos-standard-strategy";
|
||||
public static final String INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY = "interest-principal-penalties-fees-order-strategy";
|
||||
// private static final String HEAVENS_FAMILY_STRATEGY ="heavensfamily-strategy";
|
||||
// private static final String CREO_CORE_STRATEGY ="creocore-strategy";
|
||||
public static final String RBI_INDIA_STRATEGY = "rbi-india-strategy";
|
||||
|
||||
public static final String RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD = "1";
|
||||
public static final String RECALCULATION_FREQUENCY_TYPE_DAILY = "2";
|
||||
@@ -83,7 +83,7 @@ public class LoanProductTestBuilder {
|
||||
private String overdueDaysForNPA = "5";
|
||||
private String interestCalculationPeriodType = CALCULATION_PERIOD_SAME_AS_REPAYMENT_PERIOD;
|
||||
private String inArrearsTolerance = "0";
|
||||
private String transactionProcessingStrategy = DEFAULT_STRATEGY;
|
||||
private String transactionProcessingStrategyCode = DEFAULT_STRATEGY;
|
||||
private String accountingRule = NONE;
|
||||
private final String currencyCode = USD;
|
||||
private String amortizationType = EQUAL_INSTALLMENTS;
|
||||
@@ -166,7 +166,7 @@ public class LoanProductTestBuilder {
|
||||
map.put("interestType", this.interestType);
|
||||
map.put("interestCalculationPeriodType", this.interestCalculationPeriodType);
|
||||
map.put("inArrearsTolerance", this.inArrearsTolerance);
|
||||
map.put("transactionProcessingStrategyId", this.transactionProcessingStrategy);
|
||||
map.put("transactionProcessingStrategyCode", this.transactionProcessingStrategyCode);
|
||||
map.put("accountingRule", this.accountingRule);
|
||||
map.put("minPrincipal", this.minPrincipal);
|
||||
map.put("maxPrincipal", this.maxPrincipal);
|
||||
@@ -488,7 +488,7 @@ public class LoanProductTestBuilder {
|
||||
}
|
||||
|
||||
public LoanProductTestBuilder withRepaymentStrategy(final String transactionProcessingStrategy) {
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.transactionProcessingStrategyCode = transactionProcessingStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -850,7 +850,7 @@ public class LoanTransactionHelper {
|
||||
map.put("interestType", "0");
|
||||
map.put("interestCalculationPeriodType", "1");
|
||||
map.put("expectedDisbursementDate", "20 September 2011");
|
||||
map.put("transactionProcessingStrategyId", "1");
|
||||
map.put("transactionProcessingStrategyCode", "mifos-standard-strategy");
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ configurations {
|
||||
driver
|
||||
}
|
||||
dependencies {
|
||||
driver 'mysql:mysql-connector-java:8.0.30'
|
||||
driver 'mysql:mysql-connector-java:8.0.31'
|
||||
}
|
||||
|
||||
cargo {
|
||||
|
||||
@@ -37,7 +37,7 @@ configurations {
|
||||
driver
|
||||
}
|
||||
dependencies {
|
||||
driver 'mysql:mysql-connector-java:8.0.30'
|
||||
driver 'mysql:mysql-connector-java:8.0.31'
|
||||
}
|
||||
|
||||
cargo {
|
||||
|
||||
Reference in New Issue
Block a user