From 998c9bb3b242b2b6659f5e999d446d8612d4491d Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 27 Feb 2013 01:27:18 +0000 Subject: [PATCH] MIFOSX-175: WIP - adding loan summary fields to loan table and resultant refactor of loan schedule and loan summary retrieval code. --- .../0001a-mifosplatform-core-ddl-latest.sql | 25 +- .../ceda/bk_ceda_trial.sql | 281 ++++--- mifosng-db/patches/15-loan-derived-fields.sql | 43 + .../core/domain/JdbcSupport.java | 86 +- .../loanaccount/api/LoansApiResource.java | 10 +- .../loanaccount/data/LoanAccountData.java | 89 +- .../loanaccount/data/LoanSummaryData.java | 101 +++ ...RepaymentScheduleTransactionProcessor.java | 2 +- ...RepaymentScheduleTransactionProcessor.java | 2 +- .../portfolio/loanaccount/domain/Loan.java | 593 +++++++------ .../LoanRepaymentScheduleInstallment.java | 76 +- ...anRepaymentScheduleProcessingWrapper.java} | 20 +- ...ntScheduleTransactionProcessorFactory.java | 55 +- .../domain/LoanSummaryWrapper.java | 215 +++++ .../loanschedule/data/LoanScheduleData.java | 279 +------ .../data/LoanSchedulePeriodData.java | 782 ++++++++---------- ...entsAmortizationLoanScheduleGenerator.java | 32 +- ...ipalAmortizationLoanScheduleGenerator.java | 228 ++--- .../FlatMethodLoanScheduleGenerator.java | 32 +- ...WritePlatformServiceJpaRepositoryImpl.java | 11 +- .../loanaccount/service/LoanAssembler.java | 17 +- .../service/LoanReadPlatformServiceImpl.java | 364 ++++---- .../LoanSchedulePeriodDataWrapper.java | 198 ----- ...WritePlatformServiceJpaRepositoryImpl.java | 20 +- 24 files changed, 1864 insertions(+), 1697 deletions(-) create mode 100644 mifosng-db/patches/15-loan-derived-fields.sql create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanSummaryData.java rename mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/{LoanScheduleWrapper.java => LoanRepaymentScheduleProcessingWrapper.java} (88%) create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummaryWrapper.java delete mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanSchedulePeriodDataWrapper.java diff --git a/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql b/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql index f645abfbf..da27bcc4f 100644 --- a/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql +++ b/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql @@ -540,7 +540,6 @@ CREATE TABLE `m_loan` ( `repay_every` smallint(5) NOT NULL, `repayment_period_frequency_enum` smallint(5) NOT NULL, `amortization_method_enum` smallint(5) NOT NULL, - `total_charges_due_at_disbursement_derived` decimal(19,6) DEFAULT NULL, `interest_calculated_from_date` date DEFAULT NULL, `expected_disbursedon_date` date DEFAULT NULL, `expected_firstrepaymenton_date` date DEFAULT NULL, @@ -560,6 +559,30 @@ CREATE TABLE `m_loan` ( `writtenoffon_date` date DEFAULT NULL, `closedon_date` date DEFAULT NULL, `closedon_userid` bigint(20) DEFAULT NULL, + `total_charges_due_at_disbursement_derived` decimal(19,6) DEFAULT NULL, + `principal_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `principal_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `principal_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `principal_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `interest_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `fee_charges_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `penalty_charges_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0, + `first_overdue_installment_date_derived` DATE NULL, `createdby_id` bigint(20) DEFAULT NULL, `created_date` datetime DEFAULT NULL, `lastmodified_date` datetime DEFAULT NULL, diff --git a/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql b/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql index 565be4db2..b155b76ef 100644 --- a/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql +++ b/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql @@ -1,6 +1,6 @@ -- MySQL dump 10.13 Distrib 5.1.60, for Win32 (ia32) -- --- Host: localhost Database: mifostenant-default +-- Host: localhost Database: mifostenant-ceda -- ------------------------------------------------------ -- Server version 5.1.60-community @@ -36,7 +36,7 @@ CREATE TABLE `acc_gl_account` ( UNIQUE KEY `acc_gl_code` (`gl_code`), KEY `FK_ACC_0000000001` (`parent_id`), CONSTRAINT `FK_ACC_0000000001` FOREIGN KEY (`parent_id`) REFERENCES `acc_gl_account` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=98 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -45,6 +45,7 @@ CREATE TABLE `acc_gl_account` ( LOCK TABLES `acc_gl_account` WRITE; /*!40000 ALTER TABLE `acc_gl_account` DISABLE KEYS */; +INSERT INTO `acc_gl_account` VALUES (1,'Petty Cash Balances',NULL,'11100',0,1,2,1,NULL),(2,'Cash in Valut 1',NULL,'11101',0,1,1,1,NULL),(3,'Bank Balances',NULL,'11200',0,1,2,1,NULL),(4,'Centenary Opening Account',NULL,'11201',0,1,1,1,NULL),(5,'Centenary Expense Account',NULL,'11202',0,1,1,1,NULL),(6,'Centenary USD Account',NULL,'11203',0,1,1,1,NULL),(7,'Loans and Advances',NULL,'13100',0,1,2,1,NULL),(8,'Loans to Clients',NULL,'13101',0,1,1,1,NULL),(9,'Outstanding Interest',NULL,'13102',0,1,1,1,NULL),(10,'Outstanding Late Payment Interest',NULL,'13103',0,1,1,1,NULL),(11,'Outstanding Bank Fees to be collected',NULL,'13104',0,1,1,1,NULL),(12,'WriteOff Accounts',NULL,'13200',0,1,2,1,NULL),(13,'Write-offs (use for funds coming in)',NULL,'13201',0,1,1,1,NULL),(14,'Write-offs outstanding principal',NULL,'13202',0,1,1,1,NULL),(15,'Write-offs outstanding interest',NULL,'13203',0,1,1,1,NULL),(16,'Write-offs collected bank fees',NULL,'13204',0,1,1,1,NULL),(17,'Write-offs hardware/furniture',NULL,'13205',0,1,1,1,NULL),(18,'Fixed Assets',NULL,'14100',0,1,2,1,NULL),(19,'Office Equipment',NULL,'14101',0,1,1,1,NULL),(20,'Suspense Items (unidentified deposits)',NULL,'15000',0,1,2,1,NULL),(21,'Assets',NULL,'10000',0,1,2,1,NULL),(22,'Liabilities',NULL,'20000',0,1,2,2,NULL),(23,'Shares Account',NULL,'26100',0,1,2,2,NULL),(24,'Shares Captial',NULL,'26101',0,1,1,2,NULL),(25,'Donated Equity',NULL,'26300',0,1,2,2,NULL),(26,'Donated Equity Ameropa Foundation',NULL,'26301',0,1,1,2,NULL),(27,'Donated Equity e.h',NULL,'26302',0,1,1,2,NULL),(28,'Overpaid Amounts',NULL,'27000',0,1,2,2,NULL),(29,'Loss Provision',NULL,'28000',0,1,2,2,NULL),(30,'Provision Outstanding Principal',NULL,'28001',0,1,1,2,NULL),(31,'Provision Oustanding Interest',NULL,'28002',0,1,1,2,NULL),(32,'Income',NULL,'30000',0,1,2,4,NULL),(33,'Interest Income from Loans',NULL,'31100',0,1,2,4,NULL),(34,'Interest on Loans',NULL,'31101',0,1,1,4,NULL),(35,'Late Payment Interest',NULL,'31102',0,1,1,4,NULL),(36,'Income from Micro credit & Lending Activities',NULL,'31300',0,1,2,4,NULL),(37,'Collected Bank Fees Receivable',NULL,'6201',0,1,1,4,NULL),(38,'Deposits from Loans Write Off',NULL,'31400',0,1,2,4,NULL),(39,'Expenditure',NULL,'40000',0,1,2,5,NULL),(40,'Office Expenditure Account',NULL,'42100',0,1,2,5,NULL),(41,'Water Charges',NULL,'42102',0,1,1,5,NULL),(42,'Electricity Charges',NULL,'42103',0,1,1,5,NULL),(43,'Printing and Stationary',NULL,'42105',0,1,1,5,NULL),(44,'Office Rent',NULL,'42107',0,1,1,5,NULL),(45,'Marketing Expense',NULL,'42109',0,1,1,5,NULL),(46,'Office utilities',NULL,'42112',0,1,1,5,'(supplies, toiletries, kitchen)'),(47,'Furniture',NULL,'42113',0,1,1,5,NULL),(48,'CEDA Meeting Expense',NULL,'42114',0,1,1,5,NULL),(49,'Employee Personal Expsense Account',NULL,'42200',0,1,2,5,NULL),(50,'Salary Alice',NULL,'42201',0,1,1,5,NULL),(51,'Salary Irene',NULL,'42202',0,1,1,5,NULL),(52,'Salary Richard',NULL,'42203',0,1,1,5,NULL),(53,'Salary Loan Officer TBA',NULL,'42204',0,1,1,5,NULL),(54,'Medical Insurance Alice & Family',NULL,'42205',0,1,1,5,NULL),(55,'Medical Insurance Irene',NULL,'42206',0,1,1,5,NULL),(56,'Medical Insurance Richard',NULL,'42207',0,1,1,5,NULL),(57,'Medical Insurance Loan Officer TBA',NULL,'42208',0,1,1,5,NULL),(58,'PAYE all employees',NULL,'42209',0,1,1,5,NULL),(59,'NSSF all employees',NULL,'42210',0,1,1,5,NULL),(60,'Lunch Allowances all employees',NULL,'42211',0,1,1,5,NULL),(61,'IT software and maintenance',NULL,'42300',0,1,2,5,NULL),(62,'Mifos maintenance contract 12 months',NULL,'42301',0,1,1,5,NULL),(63,'VPS Contract 12 months',NULL,'42302',0,1,1,5,NULL),(64,'Bulk SMS Service',NULL,'42303',0,1,1,5,NULL),(65,'Support Accounting Software',NULL,'42304',0,1,1,5,NULL),(66,'Mifos Instance Setup',NULL,'42305',0,1,1,5,NULL),(67,'Misc support expense',NULL,'42306',0,1,1,5,NULL),(68,'Warid Mobile Line',NULL,'42307',0,1,1,5,NULL),(69,'Landline',NULL,'42308',0,1,1,5,NULL),(70,'Modem Alice',NULL,'42309',0,1,1,5,NULL),(71,'Modem Irene',NULL,'42310',0,1,1,5,NULL),(72,'Modem Richard',NULL,'42311',0,1,1,5,NULL),(73,'Repairs',NULL,'42312',0,1,1,5,NULL),(74,'Airtime Expenses',NULL,'42400',0,1,2,5,NULL),(75,'Airtime Alice',NULL,'42401',0,1,1,5,NULL),(76,'Airtime Richard',NULL,'42402',0,1,1,5,NULL),(77,'Airtime Loan Office TBA',NULL,'42403',0,1,1,5,NULL),(78,'Special Airtime Alice',NULL,'42404',0,1,1,5,NULL),(79,'Transportation',NULL,'42500',0,1,2,5,NULL),(80,'Flat monthly transportation cost',NULL,'42501',0,1,1,5,NULL),(81,'Faciliation cost for Richard',NULL,'42502',0,1,1,5,NULL),(82,'Faciliation cost for Loan Officer TBA',NULL,'42503',0,1,1,5,NULL),(83,'Consultancy Expenses',NULL,'42600',0,1,2,5,NULL),(84,'Audit Fees',NULL,'42601',0,1,1,5,NULL),(85,'Legal Fees',NULL,'42602',0,1,1,5,NULL),(86,'Miscellaneous Expenses Account',NULL,'42700',0,1,2,5,NULL),(87,'MFI License',NULL,'42703',0,1,1,5,NULL),(88,'Sundy Expenses',NULL,'42704',0,1,1,5,NULL),(89,'Bank Fees',NULL,'42800',0,1,2,5,NULL),(90,'Bank Charges Operating Account',NULL,'42801',0,1,1,5,NULL),(91,'Bank Charges Expense Account',NULL,'42802',0,1,1,5,NULL),(92,'E.H Account',NULL,'42900',0,1,2,5,NULL),(93,'Airtime',NULL,'42901',0,1,1,5,NULL),(94,'Modem',NULL,'42902',0,1,1,5,NULL),(95,'Meals',NULL,'42903',0,1,1,5,NULL),(96,'Transportation',NULL,'42904',0,1,1,5,NULL),(97,'Miscellaneous',NULL,'42905',0,1,1,5,NULL); /*!40000 ALTER TABLE `acc_gl_account` ENABLE KEYS */; UNLOCK TABLES; @@ -147,7 +148,7 @@ CREATE TABLE `acc_product_mapping` ( `product_type` smallint(5) DEFAULT NULL, `financial_account_type` smallint(5) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -156,6 +157,7 @@ CREATE TABLE `acc_product_mapping` ( LOCK TABLES `acc_product_mapping` WRITE; /*!40000 ALTER TABLE `acc_product_mapping` DISABLE KEYS */; +INSERT INTO `acc_product_mapping` VALUES (1,4,1,1,1),(2,8,1,1,2),(3,34,1,1,3),(4,37,1,1,4),(5,35,1,1,5),(6,97,1,1,6); /*!40000 ALTER TABLE `acc_product_mapping` ENABLE KEYS */; UNLOCK TABLES; @@ -185,93 +187,124 @@ INSERT INTO `c_configuration` VALUES (1,'maker-checker',0); UNLOCK TABLES; -- --- Table structure for table `extra_client_details` +-- Table structure for table `client additional data` -- -DROP TABLE IF EXISTS `extra_client_details`; +DROP TABLE IF EXISTS `client additional data`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `extra_client_details` ( +CREATE TABLE `client additional data` ( `client_id` bigint(20) NOT NULL, - `Business Description` varchar(100) DEFAULT NULL, - `Years in Business` int(11) DEFAULT NULL, - `Gender_cd` int(11) DEFAULT NULL, - `Education_cv` varchar(60) DEFAULT NULL, - `Next Visit` date DEFAULT NULL, - `Highest Rate Paid` decimal(19,6) DEFAULT NULL, - `Comment` text, + `Gender_cd` int(11) NOT NULL, + `Date of Birth` date NOT NULL, + `Home address` text NOT NULL, + `Telephone number` varchar(20) NOT NULL, + `Telephone number (2nd)` varchar(20) NOT NULL, + `Email address` varchar(50) NOT NULL, + `EducationLevel_cd` int(11) NOT NULL, + `MaritalStatus_cd` int(11) NOT NULL, + `Number of children` int(11) NOT NULL, + `Citizenship` varchar(50) NOT NULL, + `PovertyStatus_cd` int(11) NOT NULL, + `YesNo_cd_Employed` int(11) NOT NULL, + `FieldOfEmployment_cd_Field of employment` int(11) DEFAULT NULL, + `Employer name` varchar(50) DEFAULT NULL, + `Number of years` int(11) DEFAULT NULL, + `Monthly salary` decimal(19,6) DEFAULT NULL, + `YesNo_cd_Self employed` int(11) NOT NULL, + `FieldOfEmployment_cd_Field of self-employment` int(11) DEFAULT NULL, + `Business address` text, + `Number of employees` int(11) DEFAULT NULL, + `Monthly salaries paid` decimal(19,6) DEFAULT NULL, + `Monthly net income of business activity` decimal(19,6) DEFAULT NULL, + `Monthly rent` decimal(19,6) DEFAULT NULL, + `Other income generating activities` varchar(100) DEFAULT NULL, + `YesNo_cd_Bookkeeping` int(11) DEFAULT NULL, + `YesNo_cd_Loans with other institutions` int(11) NOT NULL, + `From whom` varchar(100) DEFAULT NULL, + `Amount` decimal(19,6) DEFAULT NULL, + `Interest rate pa` decimal(19,6) DEFAULT NULL, + `Number of people depending on overal income` int(11) NOT NULL, + `YesNo_cd_Bank account` int(11) NOT NULL, + `YesNo_cd_Business plan provided` int(11) NOT NULL, + `YesNo_cd_Access to internet` int(11) DEFAULT NULL, + `Introduced by` varchar(100) DEFAULT NULL, + `Known to introducer since` varchar(100) NOT NULL, + `Last visited by` varchar(100) DEFAULT NULL, + `Last visited on` date NOT NULL, PRIMARY KEY (`client_id`), - CONSTRAINT `FK_extra_client_details` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) + CONSTRAINT `FK_client_additional_data` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `extra_client_details` +-- Dumping data for table `client additional data` -- -LOCK TABLES `extra_client_details` WRITE; -/*!40000 ALTER TABLE `extra_client_details` DISABLE KEYS */; -/*!40000 ALTER TABLE `extra_client_details` ENABLE KEYS */; +LOCK TABLES `client additional data` WRITE; +/*!40000 ALTER TABLE `client additional data` DISABLE KEYS */; +/*!40000 ALTER TABLE `client additional data` ENABLE KEYS */; UNLOCK TABLES; -- --- Table structure for table `extra_family_details` +-- Table structure for table `impact measurement` -- -DROP TABLE IF EXISTS `extra_family_details`; +DROP TABLE IF EXISTS `impact measurement`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `extra_family_details` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `client_id` bigint(20) NOT NULL, - `Name` varchar(40) DEFAULT NULL, - `Date of Birth` date DEFAULT NULL, - `Points Score` int(11) DEFAULT NULL, - `Education_cd_Highest` int(11) DEFAULT NULL, - `Other Notes` text, - PRIMARY KEY (`id`), - KEY `FK_Extra Family Details Data_1` (`client_id`), - CONSTRAINT `FK_family_details` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `extra_family_details` --- - -LOCK TABLES `extra_family_details` WRITE; -/*!40000 ALTER TABLE `extra_family_details` DISABLE KEYS */; -/*!40000 ALTER TABLE `extra_family_details` ENABLE KEYS */; -UNLOCK TABLES; - --- --- Table structure for table `extra_loan_details` --- - -DROP TABLE IF EXISTS `extra_loan_details`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `extra_loan_details` ( +CREATE TABLE `impact measurement` ( `loan_id` bigint(20) NOT NULL, - `Business Description` varchar(100) DEFAULT NULL, - `Years in Business` int(11) DEFAULT NULL, - `Gender_cd` int(11) DEFAULT NULL, - `Education_cv` varchar(60) DEFAULT NULL, - `Next Visit` date DEFAULT NULL, - `Highest Rate Paid` decimal(19,6) DEFAULT NULL, - `Comment` text, + `YesNo_cd_RepaidOnSchedule` int(11) NOT NULL, + `ReasonNotRepaidOnSchedule` text, + `How was Loan Amount Invested` text NOT NULL, + `Additional Income Generated` decimal(19,6) NOT NULL, + `Additional Income Used For` text NOT NULL, + `YesNo_cd_NewJobsCreated` int(11) NOT NULL, + `Number of Jobs Created` bigint(20) DEFAULT NULL, PRIMARY KEY (`loan_id`), - CONSTRAINT `FK_extra_loan_details` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) + CONSTRAINT `FK_impact measurement` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `extra_loan_details` +-- Dumping data for table `impact measurement` -- -LOCK TABLES `extra_loan_details` WRITE; -/*!40000 ALTER TABLE `extra_loan_details` DISABLE KEYS */; -/*!40000 ALTER TABLE `extra_loan_details` ENABLE KEYS */; +LOCK TABLES `impact measurement` WRITE; +/*!40000 ALTER TABLE `impact measurement` DISABLE KEYS */; +/*!40000 ALTER TABLE `impact measurement` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `loan additional data` +-- + +DROP TABLE IF EXISTS `loan additional data`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `loan additional data` ( + `loan_id` bigint(20) NOT NULL, + `PurposeOfLoan_cd` int(11) NOT NULL, + `CollateralType_cd` int(11) NOT NULL, + `Collateral notes` text NOT NULL, + `YesNo_cd_Guarantor` int(11) NOT NULL, + `Guarantor name` varchar(100) DEFAULT NULL, + `Guarantor relation` varchar(100) DEFAULT NULL, + `Guarantor address` varchar(100) DEFAULT NULL, + `Guarantor telephone number` varchar(20) DEFAULT NULL, + PRIMARY KEY (`loan_id`), + CONSTRAINT `FK_loan_additional_data` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `loan additional data` +-- + +LOCK TABLES `loan additional data` WRITE; +/*!40000 ALTER TABLE `loan additional data` DISABLE KEYS */; +/*!40000 ALTER TABLE `loan additional data` ENABLE KEYS */; UNLOCK TABLES; -- @@ -299,7 +332,7 @@ CREATE TABLE `m_appuser` ( UNIQUE KEY `username_org` (`username`), KEY `FKB3D587CE0DD567A` (`office_id`), CONSTRAINT `FKB3D587CE0DD567A` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -308,7 +341,7 @@ CREATE TABLE `m_appuser` ( LOCK TABLES `m_appuser` WRITE; /*!40000 ALTER TABLE `m_appuser` DISABLE KEYS */; -INSERT INTO `m_appuser` VALUES (1,0,1,'mifos','App','Administrator','5787039480429368bf94732aacc771cd0a3ea02bcf504ffe1185ab94213bc63a','demomfi@mifos.org','\0','','','',''); +INSERT INTO `m_appuser` VALUES (1,0,1,'admin','App','Administrator','5787039480429368bf94732aacc771cd0a3ea02bcf504ffe1185ab94213bc63a','demomfi@mifos.org','\0','','','',''),(2,0,1,'keithwoodlock','Keith','Woodlock','4f607e9b6cffbe7d3db92d4bfa3391c7aa751727b4ea29d08fddf9dd72e6e7e3','keithwoodlock@gmail.com','\0','','','',''); /*!40000 ALTER TABLE `m_appuser` ENABLE KEYS */; UNLOCK TABLES; @@ -336,7 +369,7 @@ CREATE TABLE `m_appuser_role` ( LOCK TABLES `m_appuser_role` WRITE; /*!40000 ALTER TABLE `m_appuser_role` DISABLE KEYS */; -INSERT INTO `m_appuser_role` VALUES (1,1); +INSERT INTO `m_appuser_role` VALUES (1,1),(2,1); /*!40000 ALTER TABLE `m_appuser_role` ENABLE KEYS */; UNLOCK TABLES; @@ -360,7 +393,7 @@ CREATE TABLE `m_charge` ( `is_deleted` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -369,6 +402,7 @@ CREATE TABLE `m_charge` ( LOCK TABLES `m_charge` WRITE; /*!40000 ALTER TABLE `m_charge` DISABLE KEYS */; +INSERT INTO `m_charge` VALUES (1,'Bank Fee (per installment)','UGX',1,2,1,'1500.000000',0,1,0); /*!40000 ALTER TABLE `m_charge` ENABLE KEYS */; UNLOCK TABLES; @@ -397,7 +431,7 @@ CREATE TABLE `m_client` ( UNIQUE KEY `external_id` (`external_id`), KEY `FKCE00CAB3E0DD567A` (`office_id`), CONSTRAINT `FKCE00CAB3E0DD567A` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -406,6 +440,7 @@ CREATE TABLE `m_client` ( LOCK TABLES `m_client` WRITE; /*!40000 ALTER TABLE `m_client` DISABLE KEYS */; +INSERT INTO `m_client` VALUES (1,'000000001',2,NULL,'Kampala','first','Client',NULL,'Kampala first Client',NULL,'2011-02-01',0); /*!40000 ALTER TABLE `m_client` ENABLE KEYS */; UNLOCK TABLES; @@ -458,7 +493,7 @@ CREATE TABLE `m_code` ( `is_system_defined` tinyint(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `code_name` (`code_name`) -) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -467,7 +502,7 @@ CREATE TABLE `m_code` ( LOCK TABLES `m_code` WRITE; /*!40000 ALTER TABLE `m_code` DISABLE KEYS */; -INSERT INTO `m_code` VALUES (1,'Customer Identifier',1),(2,'LoanCollateral',1),(3,'LoanPurpose',1),(4,'Gender',1),(5,'YesNo',1),(6,'Education',1); +INSERT INTO `m_code` VALUES (1,'Customer Identifier',1),(2,'LoanCollateral',1),(3,'LoanPurpose',1),(4,'Gender',1),(5,'YesNo',1),(6,'FieldOfEmployment',0),(7,'EducationLevel',0),(8,'MaritalStatus',0),(9,'PovertyStatus',0); /*!40000 ALTER TABLE `m_code` ENABLE KEYS */; UNLOCK TABLES; @@ -487,7 +522,7 @@ CREATE TABLE `m_code_value` ( UNIQUE KEY `code_value` (`code_id`,`code_value`), KEY `FKCFCEA42640BE071Z` (`code_id`), CONSTRAINT `FKCFCEA42640BE071Z` FOREIGN KEY (`code_id`) REFERENCES `m_code` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -496,7 +531,7 @@ CREATE TABLE `m_code_value` ( LOCK TABLES `m_code_value` WRITE; /*!40000 ALTER TABLE `m_code_value` DISABLE KEYS */; -INSERT INTO `m_code_value` VALUES (1,1,'Passport',1),(2,1,'Id',1),(3,1,'Drivers License',2),(4,1,'Any Other Id Type',3),(5,4,'option.Male',1),(6,4,'option.Female',5),(7,5,'option.Yes',1),(8,5,'option.No',7),(9,6,'Primary',1),(10,6,'Secondary',9),(11,6,'University',10); +INSERT INTO `m_code_value` VALUES (1,1,'Passport',1),(2,1,'Id',1),(3,1,'Drivers License',2),(4,1,'Any Other Id Type',3),(5,6,'option.Banker',1),(6,6,'option.SoftwareDeveloper',5),(7,7,'option.University',1),(8,7,'option.Secondary',7),(9,7,'option.Primary',8),(10,8,'option.Married',1),(11,8,'option.Single',10),(12,8,'option.Divorced',11),(13,8,'option.Widow',12),(14,9,'option.PovertyStatus.Band1',1),(15,9,'option.PovertyStatus.Band2',14),(16,9,'option.PovertyStatus.Band3',15),(17,2,'option.House',1),(18,2,'option.Television',17),(19,2,'option.Gold',18),(20,3,'option.Agriculture',1),(21,3,'option.Manufacturing',20),(22,3,'option.HousingImprovement',21),(23,4,'option.Male',1),(24,4,'option.Female',23),(25,5,'option.Yes',1),(26,5,'option.No',25); /*!40000 ALTER TABLE `m_code_value` ENABLE KEYS */; UNLOCK TABLES; @@ -856,7 +891,6 @@ CREATE TABLE `m_loan` ( `repay_every` smallint(5) NOT NULL, `repayment_period_frequency_enum` smallint(5) NOT NULL, `amortization_method_enum` smallint(5) NOT NULL, - `total_charges_due_at_disbursement_derived` decimal(19,6) DEFAULT NULL, `interest_calculated_from_date` date DEFAULT NULL, `expected_disbursedon_date` date DEFAULT NULL, `expected_firstrepaymenton_date` date DEFAULT NULL, @@ -876,10 +910,39 @@ CREATE TABLE `m_loan` ( `writtenoffon_date` date DEFAULT NULL, `closedon_date` date DEFAULT NULL, `closedon_userid` bigint(20) DEFAULT NULL, - `createdby_id` bigint(20) DEFAULT NULL, - `created_date` datetime DEFAULT NULL, - `lastmodified_date` datetime DEFAULT NULL, - `lastmodifiedby_id` bigint(20) DEFAULT NULL, + `total_charges_due_at_disbursement_derived` decimal(19,6) DEFAULT NULL, + `principal_disbursed_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `principal_repaid_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `principal_writtenoff_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `principal_outstanding_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `principal_overdue_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_charged_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_repaid_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_waived_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_writtenoff_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_outstanding_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `interest_overdue_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_charged_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_repaid_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_waived_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_writtenoff_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_outstanding_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `fee_charges_overdue_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_charged_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_repaid_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_waived_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_writtenoff_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_outstanding_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `penalty_charges_overdue_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_expected_repayment_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_repayment_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_expected_costofloan_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_costofloan_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_waived_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_writtenoff_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `total_outstanding_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', + `overdue_since_date_derived` date DEFAULT NULL, + `total_overdue_derived` decimal(19,6) NOT NULL DEFAULT '0.000000', PRIMARY KEY (`id`), UNIQUE KEY `loan_account_no_UNIQUE` (`account_no`), UNIQUE KEY `loan_externalid_UNIQUE` (`external_id`), @@ -896,20 +959,20 @@ CREATE TABLE `m_loan` ( KEY `FK_withdrawnon_userid` (`withdrawnon_userid`), KEY `FK_closedon_userid` (`closedon_userid`), KEY `FK_disbursedon_userid` (`disbursedon_userid`), - CONSTRAINT `FKB6F935D87179A0CB` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`), - CONSTRAINT `m_loan_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`), - CONSTRAINT `FKB6F935D8C8D4B434` FOREIGN KEY (`product_id`) REFERENCES `m_product_loan` (`id`), 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_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_submittedon_userid` FOREIGN KEY (`submittedon_userid`) REFERENCES `m_appuser` (`id`), - CONSTRAINT `FK_approvedon_userid` FOREIGN KEY (`approvedon_userid`) REFERENCES `m_appuser` (`id`), CONSTRAINT `FK_rejectedon_userid` FOREIGN KEY (`rejectedon_userid`) REFERENCES `m_appuser` (`id`), + CONSTRAINT `FK_submittedon_userid` FOREIGN KEY (`submittedon_userid`) REFERENCES `m_appuser` (`id`), CONSTRAINT `FK_withdrawnon_userid` FOREIGN KEY (`withdrawnon_userid`) REFERENCES `m_appuser` (`id`), - CONSTRAINT `FK_disbursedon_userid` FOREIGN KEY (`disbursedon_userid`) REFERENCES `m_appuser` (`id`), - CONSTRAINT `FK_closedon_userid` FOREIGN KEY (`closedon_userid`) REFERENCES `m_appuser` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CONSTRAINT `m_loan_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `m_group` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -918,6 +981,7 @@ CREATE TABLE `m_loan` ( LOCK TABLES `m_loan` WRITE; /*!40000 ALTER TABLE `m_loan` DISABLE KEYS */; +INSERT INTO `m_loan` VALUES (1,'000000001',NULL,1,NULL,1,NULL,2,22,2,200,'UGX',2,'1000000.000000',NULL,'24.000000',3,'24.000000',1,1,12,2,12,1,2,1,NULL,'2011-02-08',NULL,'2012-02-08','2012-02-08','2011-02-01',1,'2011-02-04',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000','0.000000',NULL,'0.000000'); /*!40000 ALTER TABLE `m_loan` ENABLE KEYS */; UNLOCK TABLES; @@ -949,7 +1013,7 @@ CREATE TABLE `m_loan_charge` ( KEY `m_loan_charge_ibfk_2` (`loan_id`), CONSTRAINT `m_loan_charge_ibfk_1` FOREIGN KEY (`charge_id`) REFERENCES `m_charge` (`id`), CONSTRAINT `m_loan_charge_ibfk_2` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -958,6 +1022,7 @@ CREATE TABLE `m_loan_charge` ( LOCK TABLES `m_loan_charge` WRITE; /*!40000 ALTER TABLE `m_loan_charge` DISABLE KEYS */; +INSERT INTO `m_loan_charge` VALUES (1,1,1,0,2,'2011-08-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(2,1,1,0,2,'2011-05-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(3,1,1,0,2,'2011-10-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(4,1,1,0,2,'2011-07-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(5,1,1,0,2,'2011-04-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(6,1,1,0,2,'2011-11-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(7,1,1,0,2,'2011-06-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(8,1,1,0,2,'2011-12-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(9,1,1,0,2,'2011-09-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(10,1,1,0,2,'2011-03-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(11,1,1,0,2,'2012-01-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0),(12,1,1,0,2,'2012-02-08',1,NULL,NULL,'1500.000000','0.000000',NULL,NULL,'1500.000000',0); /*!40000 ALTER TABLE `m_loan_charge` ENABLE KEYS */; UNLOCK TABLES; @@ -978,7 +1043,7 @@ CREATE TABLE `m_loan_collateral` ( KEY `FK_collateral_code_value` (`type_cv_id`), CONSTRAINT `FK_collateral_m_loan` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`), CONSTRAINT `FK_collateral_code_value` FOREIGN KEY (`type_cv_id`) REFERENCES `m_code_value` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -987,6 +1052,7 @@ CREATE TABLE `m_loan_collateral` ( LOCK TABLES `m_loan_collateral` WRITE; /*!40000 ALTER TABLE `m_loan_collateral` DISABLE KEYS */; +INSERT INTO `m_loan_collateral` VALUES (1,1,19,' collateral example 1.'),(2,1,18,'collateral example notes 2. '); /*!40000 ALTER TABLE `m_loan_collateral` ENABLE KEYS */; UNLOCK TABLES; @@ -1012,7 +1078,7 @@ CREATE TABLE `m_loan_officer_assignment_history` ( KEY `fk_m_loan_officer_assignment_history_0002` (`loan_officer_id`), CONSTRAINT `fk_m_loan_officer_assignment_history_0001` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`), CONSTRAINT `fk_m_loan_officer_assignment_history_0002` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1021,6 +1087,7 @@ CREATE TABLE `m_loan_officer_assignment_history` ( LOCK TABLES `m_loan_officer_assignment_history` WRITE; /*!40000 ALTER TABLE `m_loan_officer_assignment_history` DISABLE KEYS */; +INSERT INTO `m_loan_officer_assignment_history` VALUES (1,1,2,'2011-02-04',NULL,1,'2013-02-26 21:33:45','2013-02-26 21:33:45',1); /*!40000 ALTER TABLE `m_loan_officer_assignment_history` ENABLE KEYS */; UNLOCK TABLES; @@ -1060,7 +1127,7 @@ CREATE TABLE `m_loan_repayment_schedule` ( PRIMARY KEY (`id`), KEY `FK488B92AA40BE0710` (`loan_id`), CONSTRAINT `FK488B92AA40BE0710` FOREIGN KEY (`loan_id`) REFERENCES `m_loan` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1069,6 +1136,7 @@ CREATE TABLE `m_loan_repayment_schedule` ( LOCK TABLES `m_loan_repayment_schedule` WRITE; /*!40000 ALTER TABLE `m_loan_repayment_schedule` DISABLE KEYS */; +INSERT INTO `m_loan_repayment_schedule` VALUES (1,1,'2011-02-08','2011-03-08',1,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(2,1,'2011-03-08','2011-04-08',2,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(3,1,'2011-04-08','2011-05-08',3,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(4,1,'2011-05-08','2011-06-08',4,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(5,1,'2011-06-08','2011-07-08',5,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(6,1,'2011-07-08','2011-08-08',6,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(7,1,'2011-08-08','2011-09-08',7,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(8,1,'2011-09-08','2011-10-08',8,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(9,1,'2011-10-08','2011-11-08',9,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(10,1,'2011-11-08','2011-12-08',10,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(11,1,'2011-12-08','2012-01-08',11,'83333.330000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL),(12,1,'2012-01-08','2012-02-08',12,'83333.370000',NULL,NULL,'20000.000000',NULL,NULL,'1500.000000',NULL,NULL,NULL,NULL,NULL,NULL,NULL,'\0',1,'2013-02-26 21:30:40','2013-02-26 21:30:40',1,NULL); /*!40000 ALTER TABLE `m_loan_repayment_schedule` ENABLE KEYS */; UNLOCK TABLES; @@ -1171,7 +1239,7 @@ CREATE TABLE `m_office` ( UNIQUE KEY `externalid_org` (`external_id`), KEY `FK2291C477E2551DCC` (`parent_id`), CONSTRAINT `FK2291C477E2551DCC` FOREIGN KEY (`parent_id`) REFERENCES `m_office` (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1180,7 +1248,7 @@ CREATE TABLE `m_office` ( LOCK TABLES `m_office` WRITE; /*!40000 ALTER TABLE `m_office` DISABLE KEYS */; -INSERT INTO `m_office` VALUES (1,NULL,'.','1','Head Office','2009-01-01'); +INSERT INTO `m_office` VALUES (1,NULL,'.','1','CEDA Microfinance Ltd.','2009-01-01'),(2,1,'.2.','2','Uganda (Kampala)','2009-01-01'); /*!40000 ALTER TABLE `m_office` ENABLE KEYS */; UNLOCK TABLES; @@ -1232,7 +1300,7 @@ CREATE TABLE `m_organisation_currency` ( `display_symbol` varchar(10) DEFAULT NULL, `internationalized_name_code` varchar(50) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1241,7 +1309,7 @@ CREATE TABLE `m_organisation_currency` ( LOCK TABLES `m_organisation_currency` WRITE; /*!40000 ALTER TABLE `m_organisation_currency` DISABLE KEYS */; -INSERT INTO `m_organisation_currency` VALUES (21,'USD',2,'US Dollar','$','currency.USD'); +INSERT INTO `m_organisation_currency` VALUES (22,'UGX',2,'Uganda Shilling','USh','currency.UGX'); /*!40000 ALTER TABLE `m_organisation_currency` ENABLE KEYS */; UNLOCK TABLES; @@ -1270,7 +1338,7 @@ CREATE TABLE `m_permission` ( LOCK TABLES `m_permission` WRITE; /*!40000 ALTER TABLE `m_permission` DISABLE KEYS */; -INSERT INTO `m_permission` VALUES (1,'special','ALL_FUNCTIONS',NULL,NULL,0),(2,'special','ALL_FUNCTIONS_READ',NULL,NULL,0),(3,'special','CHECKER_SUPER_USER',NULL,NULL,0),(4,'special','REPORTING_SUPER_USER',NULL,NULL,0),(5,'authorisation','READ_PERMISSION','PERMISSION','READ',0),(6,'authorisation','PERMISSIONS_ROLE','ROLE','PERMISSIONS',1),(7,'authorisation','CREATE_ROLE','ROLE','CREATE',1),(8,'authorisation','CREATE_ROLE_CHECKER','ROLE','CREATE',1),(9,'authorisation','READ_ROLE','ROLE','READ',0),(10,'authorisation','UPDATE_ROLE','ROLE','UPDATE',1),(11,'authorisation','UPDATE_ROLE_CHECKER','ROLE','UPDATE',1),(12,'authorisation','DELETE_ROLE','ROLE','DELETE',1),(13,'authorisation','DELETE_ROLE_CHECKER','ROLE','DELETE',1),(14,'authorisation','CREATE_USER','USER','CREATE',1),(15,'authorisation','CREATE_USER_CHECKER','USER','CREATE',1),(16,'authorisation','READ_USER','USER','READ',0),(17,'authorisation','UPDATE_USER','USER','UPDATE',1),(18,'authorisation','UPDATE_USER_CHECKER','USER','UPDATE',1),(19,'authorisation','DELETE_USER','USER','DELETE',1),(20,'authorisation','DELETE_USER_CHECKER','USER','DELETE',1),(21,'configuration','READ_CONFIGURATION','CONFIGURATION','READ',1),(22,'configuration','UPDATE_CONFIGURATION','CONFIGURATION','UPDATE',1),(23,'configuration','UPDATE_CONFIGURATION_CHECKER','CONFIGURATION','UPDATE',1),(24,'configuration','READ_CODE','CODE','READ',0),(25,'configuration','CREATE_CODE','CODE','CREATE',1),(26,'configuration','CREATE_CODE_CHECKER','CODE','CREATE',1),(27,'configuration','UPDATE_CODE','CODE','UPDATE',1),(28,'configuration','UPDATE_CODE_CHECKER','CODE','UPDATE',1),(29,'configuration','DELETE_CODE','CODE','DELETE',1),(30,'configuration','DELETE_CODE_CHECKER','CODE','DELETE',1),(31,'configuration','READ_CODEVALUE','CODEVALUE','READ',0),(32,'configuration','CREATE_CODEVALUE','CODEVALUE','CREATE',1),(33,'configuration','CREATE_CODEVALUE_CHECKER','CODEVALUE','CREATE',1),(34,'configuration','UPDATE_CODEVALUE','CODEVALUE','UPDATE',1),(35,'configuration','UPDATE_CODEVALUE_CHECKER','CODEVALUE','UPDATE',1),(36,'configuration','DELETE_CODEVALUE','CODEVALUE','DELETE',1),(37,'configuration','DELETE_CODEVALUE_CHECKER','CODEVALUE','DELETE',1),(38,'configuration','READ_CURRENCY','CURRENCY','READ',0),(39,'configuration','UPDATE_CURRENCY','CURRENCY','UPDATE',1),(40,'configuration','UPDATE_CURRENCY_CHECKER','CURRENCY','UPDATE',1),(41,'configuration','UPDATE_PERMISSION','PERMISSION','UPDATE',1),(42,'configuration','UPDATE_PERMISSION_CHECKER','PERMISSION','UPDATE',1),(43,'configuration','READ_DATATABLE','DATATABLE','READ',0),(44,'configuration','REGISTER_DATATABLE','DATATABLE','REGISTER',1),(45,'configuration','REGISTER_DATATABLE_CHECKER','DATATABLE','REGISTER',1),(46,'configuration','DEREGISTER_DATATABLE','DATATABLE','DEREGISTER',1),(47,'configuration','DEREGISTER_DATATABLE_CHECKER','DATATABLE','DEREGISTER',1),(48,'configuration','READ_AUDIT','AUDIT','READ',0),(49,'organisation','READ_MAKERCHECKER','MAKERCHECKER','READ',0),(50,'organisation','READ_CHARGE','CHARGE','READ',0),(51,'organisation','CREATE_CHARGE','CHARGE','CREATE',1),(52,'organisation','CREATE_CHARGE_CHECKER','CHARGE','CREATE',1),(53,'organisation','UPDATE_CHARGE','CHARGE','UPDATE',1),(54,'organisation','UPDATE_CHARGE_CHECKER','CHARGE','UPDATE',1),(55,'organisation','DELETE_CHARGE','CHARGE','DELETE',1),(56,'organisation','DELETE_CHARGE_CHECKER','CHARGE','DELETE',1),(57,'organisation','READ_FUND','FUND','READ',0),(58,'organisation','CREATE_FUND','FUND','CREATE',1),(59,'organisation','CREATE_FUND_CHECKER','FUND','CREATE',1),(60,'organisation','UPDATE_FUND','FUND','UPDATE',1),(61,'organisation','UPDATE_FUND_CHECKER','FUND','UPDATE',1),(62,'organisation','DELETE_FUND','FUND','DELETE',1),(63,'organisation','DELETE_FUND_CHECKER','FUND','DELETE',1),(64,'organisation','READ_LOANPRODUCT','LOANPRODUCT','READ',0),(65,'organisation','CREATE_LOANPRODUCT','LOANPRODUCT','CREATE',1),(66,'organisation','CREATE_LOANPRODUCT_CHECKER','LOANPRODUCT','CREATE',1),(67,'organisation','UPDATE_LOANPRODUCT','LOANPRODUCT','UPDATE',1),(68,'organisation','UPDATE_LOANPRODUCT_CHECKER','LOANPRODUCT','UPDATE',1),(69,'organisation','DELETE_LOANPRODUCT','LOANPRODUCT','DELETE',1),(70,'organisation','DELETE_LOANPRODUCT_CHECKER','LOANPRODUCT','DELETE',1),(71,'organisation','READ_OFFICE','OFFICE','READ',0),(72,'organisation','CREATE_OFFICE','OFFICE','CREATE',1),(73,'organisation','CREATE_OFFICE_CHECKER','OFFICE','CREATE',1),(74,'organisation','UPDATE_OFFICE','OFFICE','UPDATE',1),(75,'organisation','UPDATE_OFFICE_CHECKER','OFFICE','UPDATE',1),(76,'organisation','READ_OFFICETRANSACTION','OFFICETRANSACTION','READ',0),(77,'organisation','DELETE_OFFICE_CHECKER','OFFICE','DELETE',1),(78,'organisation','CREATE_OFFICETRANSACTION','OFFICETRANSACTION','CREATE',1),(79,'organisation','CREATE_OFFICETRANSACTION_CHECKER','OFFICETRANSACTION','CREATE',1),(80,'organisation','DELETE_OFFICETRANSACTION','OFFICETRANSACTION','DELETE',1),(81,'organisation','DELETE_OFFICETRANSACTION_CHECKER','OFFICETRANSACTION','DELETE',1),(82,'organisation','READ_STAFF','STAFF','READ',0),(83,'organisation','CREATE_STAFF','STAFF','CREATE',1),(84,'organisation','CREATE_STAFF_CHECKER','STAFF','CREATE',1),(85,'organisation','UPDATE_STAFF','STAFF','UPDATE',1),(86,'organisation','UPDATE_STAFF_CHECKER','STAFF','UPDATE',1),(87,'organisation','DELETE_STAFF','STAFF','DELETE',1),(88,'organisation','DELETE_STAFF_CHECKER','STAFF','DELETE',1),(89,'organisation','READ_SAVINGSPRODUCT','SAVINGSPRODUCT','READ',0),(90,'organisation','CREATE_SAVINGSPRODUCT','SAVINGSPRODUCT','CREATE',1),(91,'organisation','CREATE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','CREATE',1),(92,'organisation','UPDATE_SAVINGSPRODUCT','SAVINGSPRODUCT','UPDATE',1),(93,'organisation','UPDATE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','UPDATE',1),(94,'organisation','DELETE_SAVINGSPRODUCT','SAVINGSPRODUCT','DELETE',1),(95,'organisation','DELETE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','DELETE',1),(96,'organisation','READ_DEPOSITPRODUCT','DEPOSITPRODUCT','READ',0),(97,'organisation','CREATE_DEPOSITPRODUCT','DEPOSITPRODUCT','CREATE',1),(98,'organisation','CREATE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','CREATE',1),(99,'organisation','UPDATE_DEPOSITPRODUCT','DEPOSITPRODUCT','UPDATE',1),(100,'organisation','UPDATE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','UPDATE',1),(101,'organisation','DELETE_DEPOSITPRODUCT','DEPOSITPRODUCT','DELETE',1),(102,'organisation','DELETE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','DELETE',1),(103,'portfolio','READ_LOAN','LOAN','READ',0),(104,'portfolio','CREATE_LOAN','LOAN','CREATE',1),(105,'portfolio','CREATE_LOAN_CHECKER','LOAN','CREATE',1),(106,'portfolio','UPDATE_LOAN','LOAN','UPDATE',1),(107,'portfolio','UPDATE_LOAN_CHECKER','LOAN','UPDATE',1),(108,'portfolio','DELETE_LOAN','LOAN','DELETE',1),(109,'portfolio','DELETE_LOAN_CHECKER','LOAN','DELETE',1),(110,'portfolio','READ_CLIENT','CLIENT','READ',0),(111,'portfolio','CREATE_CLIENT','CLIENT','CREATE',1),(112,'portfolio','CREATE_CLIENT_CHECKER','CLIENT','CREATE',1),(113,'portfolio','UPDATE_CLIENT','CLIENT','UPDATE',1),(114,'portfolio','UPDATE_CLIENT_CHECKER','CLIENT','UPDATE',1),(115,'portfolio','DELETE_CLIENT','CLIENT','DELETE',1),(116,'portfolio','DELETE_CLIENT_CHECKER','CLIENT','DELETE',1),(117,'portfolio','READ_CLIENTIMAGE','CLIENTIMAGE','READ',0),(118,'portfolio','CREATE_CLIENTIMAGE','CLIENTIMAGE','CREATE',1),(119,'portfolio','CREATE_CLIENTIMAGE_CHECKER','CLIENTIMAGE','CREATE',1),(120,'portfolio','DELETE_CLIENTIMAGE','CLIENTIMAGE','DELETE',1),(121,'portfolio','DELETE_CLIENTIMAGE_CHECKER','CLIENTIMAGE','DELETE',1),(122,'portfolio','READ_CLIENTNOTE','CLIENTNOTE','READ',0),(123,'portfolio','CREATE_CLIENTNOTE','CLIENTNOTE','CREATE',1),(124,'portfolio','CREATE_CLIENTNOTE_CHECKER','CLIENTNOTE','CREATE',1),(125,'portfolio','UPDATE_CLIENTNOTE','CLIENTNOTE','UPDATE',1),(126,'portfolio','UPDATE_CLIENTNOTE_CHECKER','CLIENTNOTE','UPDATE',1),(127,'portfolio','DELETE_CLIENTNOTE','CLIENTNOTE','DELETE',1),(128,'portfolio','DELETE_CLIENTNOTE_CHECKER','CLIENTNOTE','DELETE',1),(129,'portfolio','READ_CLIENTIDENTIFIER','CLIENTIDENTIFIER','READ',0),(130,'portfolio','CREATE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','CREATE',1),(131,'portfolio','CREATE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','CREATE',1),(132,'portfolio','UPDATE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','UPDATE',1),(133,'portfolio','UPDATE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','UPDATE',1),(134,'portfolio','DELETE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','DELETE',1),(135,'portfolio','DELETE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','DELETE',1),(136,'portfolio','READ_DOCUMENT','DOCUMENT','READ',0),(137,'portfolio','CREATE_DOCUMENT','DOCUMENT','CREATE',1),(138,'portfolio','CREATE_DOCUMENT_CHECKER','DOCUMENT','CREATE',1),(139,'portfolio','UPDATE_DOCUMENT','DOCUMENT','UPDATE',1),(140,'portfolio','UPDATE_DOCUMENT_CHECKER','DOCUMENT','UPDATE',1),(141,'portfolio','DELETE_DOCUMENT','DOCUMENT','DELETE',1),(142,'portfolio','DELETE_DOCUMENT_CHECKER','DOCUMENT','DELETE',1),(143,'portfolio','READ_GROUP','GROUP','READ',0),(144,'portfolio','CREATE_GROUP','GROUP','CREATE',1),(145,'portfolio','CREATE_GROUP_CHECKER','GROUP','CREATE',1),(146,'portfolio','UPDATE_GROUP','GROUP','UPDATE',1),(147,'portfolio','UPDATE_GROUP_CHECKER','GROUP','UPDATE',1),(148,'portfolio','DELETE_GROUP','GROUP','DELETE',1),(149,'portfolio','DELETE_GROUP_CHECKER','GROUP','DELETE',1),(150,'portfolio','CREATE_LOANCHARGE','LOANCHARGE','CREATE',1),(151,'portfolio','CREATE_LOANCHARGE_CHECKER','LOANCHARGE','CREATE',1),(152,'portfolio','UPDATE_LOANCHARGE','LOANCHARGE','UPDATE',1),(153,'portfolio','UPDATE_LOANCHARGE_CHECKER','LOANCHARGE','UPDATE',1),(154,'portfolio','DELETE_LOANCHARGE','LOANCHARGE','DELETE',1),(155,'portfolio','DELETE_LOANCHARGE_CHECKER','LOANCHARGE','DELETE',1),(156,'portfolio','WAIVE_LOANCHARGE','LOANCHARGE','WAIVE',1),(157,'portfolio','WAIVE_LOANCHARGE_CHECKER','LOANCHARGE','WAIVE',1),(158,'portfolio','READ_DEPOSITACCOUNT','DEPOSITACCOUNT','READ',0),(159,'portfolio','CREATE_DEPOSITACCOUNT','DEPOSITACCOUNT','CREATE',1),(160,'portfolio','CREATE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','CREATE',1),(161,'portfolio','UPDATE_DEPOSITACCOUNT','DEPOSITACCOUNT','UPDATE',1),(162,'portfolio','UPDATE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','UPDATE',1),(163,'portfolio','DELETE_DEPOSITACCOUNT','DEPOSITACCOUNT','DELETE',1),(164,'portfolio','DELETE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','DELETE',1),(165,'portfolio','READ_SAVINGSACCOUNT','SAVINGSACCOUNT','READ',0),(166,'portfolio','CREATE_SAVINGSACCOUNT','SAVINGSACCOUNT','CREATE',1),(167,'portfolio','CREATE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','CREATE',1),(168,'portfolio','UPDATE_SAVINGSACCOUNT','SAVINGSACCOUNT','UPDATE',1),(169,'portfolio','UPDATE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','UPDATE',1),(170,'portfolio','DELETE_SAVINGSACCOUNT','SAVINGSACCOUNT','DELETE',1),(171,'portfolio','DELETE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','DELETE',1),(172,'portfolio','READ_GUARANTOR','GUARANTOR','READ',0),(173,'portfolio','CREATE_GUARANTOR','GUARANTOR','CREATE',1),(174,'portfolio','CREATE_GUARANTOR_CHECKER','GUARANTOR','CREATE',1),(175,'portfolio','UPDATE_GUARANTOR','GUARANTOR','UPDATE',1),(176,'portfolio','UPDATE_GUARANTOR_CHECKER','GUARANTOR','UPDATE',1),(177,'portfolio','DELETE_GUARANTOR','GUARANTOR','DELETE',1),(178,'portfolio','DELETE_GUARANTOR_CHECKER','GUARANTOR','DELETE',1),(179,'transaction_loan','APPROVE_LOAN','LOAN','APPROVE',1),(180,'transaction_loan','APPROVEINPAST_LOAN','LOAN','APPROVEINPAST',1),(181,'transaction_loan','REJECT_LOAN','LOAN','REJECT',1),(182,'transaction_loan','REJECTINPAST_LOAN','LOAN','REJECTINPAST',1),(183,'transaction_loan','WITHDRAW_LOAN','LOAN','WITHDRAW',1),(184,'transaction_loan','WITHDRAWINPAST_LOAN','LOAN','WITHDRAWINPAST',1),(185,'transaction_loan','APPROVALUNDO_LOAN','LOAN','APPROVALUNDO',1),(186,'transaction_loan','DISBURSE_LOAN','LOAN','DISBURSE',1),(187,'transaction_loan','DISBURSEINPAST_LOAN','LOAN','DISBURSEINPAST',1),(188,'transaction_loan','DISBURSALUNDO_LOAN','LOAN','DISBURSALUNDO',1),(189,'transaction_loan','REPAYMENT_LOAN','LOAN','REPAYMENT',1),(190,'transaction_loan','REPAYMENTINPAST_LOAN','LOAN','REPAYMENTINPAST',1),(191,'transaction_loan','ADJUST_LOAN','LOAN','ADJUST',1),(192,'transaction_loan','WAIVEINTERESTPORTION_LOAN','LOAN','WAIVEINTERESTPORTION',1),(193,'transaction_loan','WRITEOFF_LOAN','LOAN','WRITEOFF',1),(194,'transaction_loan','CLOSE_LOAN','LOAN','CLOSE',1),(195,'transaction_loan','CLOSEASRESCHEDULED_LOAN','LOAN','CLOSEASRESCHEDULED',1),(196,'transaction_loan','UPDATELOANOFFICER_LOAN','LOAN','UPDATELOANOFFICER',1),(197,'transaction_loan','UPDATELOANOFFICER_LOAN_CHECKER','LOAN','UPDATELOANOFFICER',1),(198,'transaction_loan','REMOVELOANOFFICER_LOAN','LOAN','REMOVELOANOFFICER',1),(199,'transaction_loan','REMOVELOANOFFICER_LOAN_CHECKER','LOAN','REMOVELOANOFFICER',1),(200,'transaction_loan','BULKREASSIGN_LOAN','LOAN','BULKREASSIGN',1),(201,'transaction_loan','BULKREASSIGN_LOAN_CHECKER','LOAN','BULKREASSIGN',1),(202,'transaction_loan','APPROVE_LOAN_CHECKER','LOAN','APPROVE',1),(203,'transaction_loan','APPROVEINPAST_LOAN_CHECKER','LOAN','APPROVEINPAST',1),(204,'transaction_loan','REJECT_LOAN_CHECKER','LOAN','REJECT',1),(205,'transaction_loan','REJECTINPAST_LOAN_CHECKER','LOAN','REJECTINPAST',1),(206,'transaction_loan','WITHDRAW_LOAN_CHECKER','LOAN','WITHDRAW',1),(207,'transaction_loan','WITHDRAWINPAST_LOAN_CHECKER','LOAN','WITHDRAWINPAST',1),(208,'transaction_loan','APPROVALUNDO_LOAN_CHECKER','LOAN','APPROVALUNDO',1),(209,'transaction_loan','DISBURSE_LOAN_CHECKER','LOAN','DISBURSE',1),(210,'transaction_loan','DISBURSEINPAST_LOAN_CHECKER','LOAN','DISBURSEINPAST',1),(211,'transaction_loan','DISBURSALUNDO_LOAN_CHECKER','LOAN','DISBURSALUNDO',1),(212,'transaction_loan','REPAYMENT_LOAN_CHECKER','LOAN','REPAYMENT',1),(213,'transaction_loan','REPAYMENTINPAST_LOAN_CHECKER','LOAN','REPAYMENTINPAST',1),(214,'transaction_loan','ADJUST_LOAN_CHECKER','LOAN','ADJUST',1),(215,'transaction_loan','WAIVEINTERESTPORTION_LOAN_CHECKER','LOAN','WAIVEINTERESTPORTION',1),(216,'transaction_loan','WRITEOFF_LOAN_CHECKER','LOAN','WRITEOFF',1),(217,'transaction_loan','CLOSE_LOAN_CHECKER','LOAN','CLOSE',1),(218,'transaction_loan','CLOSEASRESCHEDULED_LOAN_CHECKER','LOAN','CLOSEASRESCHEDULED',1),(219,'transaction_deposit','APPROVE_DEPOSITACCOUNT','DEPOSITACCOUNT','APPROVE',1),(220,'transaction_deposit','REJECT_DEPOSITACCOUNT','DEPOSITACCOUNT','REJECT',1),(221,'transaction_deposit','WITHDRAW_DEPOSITACCOUNT','DEPOSITACCOUNT','WITHDRAW',1),(222,'transaction_deposit','APPROVALUNDO_DEPOSITACCOUNT','DEPOSITACCOUNT','APPROVALUNDO',1),(223,'transaction_deposit','WITHDRAWAL_DEPOSITACCOUNT','DEPOSITACCOUNT','WITHDRAWAL',1),(224,'transaction_deposit','INTEREST_DEPOSITACCOUNT','DEPOSITACCOUNT','INTEREST',1),(225,'transaction_deposit','RENEW_DEPOSITACCOUNT','DEPOSITACCOUNT','RENEW',1),(226,'transaction_deposit','APPROVE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','APPROVE',1),(227,'transaction_deposit','REJECT_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','REJECT',1),(228,'transaction_deposit','WITHDRAW_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','WITHDRAW',1),(229,'transaction_deposit','APPROVALUNDO_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','APPROVALUNDO',1),(230,'transaction_deposit','WITHDRAWAL_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','WITHDRAWAL',1),(231,'transaction_deposit','INTEREST_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','INTEREST',1),(232,'transaction_deposit','RENEW_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','RENEW',1),(233,'accounting','CREATE_GLACCOUNT','GLACCOUNT','CREATE',1),(234,'accounting','UPDATE_GLACCOUNT','GLACCOUNT','UPDATE',1),(235,'accounting','DELETE_GLACCOUNT','GLACCOUNT','DELETE',1),(236,'accounting','CREATE_GLCLOSURE','GLCLOSURE','CREATE',1),(237,'accounting','UPDATE_GLCLOSURE','GLCLOSURE','UPDATE',1),(238,'accounting','DELETE_GLCLOSURE','GLCLOSURE','DELETE',1),(239,'accounting','CREATE_JOURNALENTRY','JOURNALENTRY','CREATE',1),(240,'accounting','REVERSE_JOURNALENTRY','JOURNALENTRY','REVERSE',1),(241,'report','READ_Active Loans - Details','Active Loans - Details','READ',1),(242,'report','READ_Active Loans - Summary','Active Loans - Summary','READ',1),(243,'report','READ_Active Loans by Disbursal Period','Active Loans by Disbursal Period','READ',1),(244,'report','READ_Active Loans in last installment','Active Loans in last installment','READ',1),(245,'report','READ_Active Loans in last installment Summary','Active Loans in last installment Summary','READ',1),(246,'report','READ_Active Loans Passed Final Maturity','Active Loans Passed Final Maturity','READ',1),(247,'report','READ_Active Loans Passed Final Maturity Summary','Active Loans Passed Final Maturity Summary','READ',1),(248,'report','READ_Aging Summary (Arrears in weeks) - review','Aging Summary (Arrears in weeks) - review','READ',1),(249,'report','READ_Amount In Arrears','Amount In Arrears','READ',1),(250,'report','READ_Balance Sheet','Balance Sheet','READ',1),(251,'report','READ_Client Listing','Client Listing','READ',1),(252,'report','READ_Client Loans Listing','Client Loans Listing','READ',1),(253,'report','READ_Funds Disbursed Between Dates Summary','Funds Disbursed Between Dates Summary','READ',1),(254,'report','READ_Funds Disbursed Between Dates Summary by Office','Funds Disbursed Between Dates Summary by Office','READ',1),(255,'report','READ_Income Statement','Income Statement','READ',1),(256,'report','READ_Loans Awaiting Disbursal','Loans Awaiting Disbursal','READ',1),(257,'report','READ_Loans Awaiting Disbursal Summary','Loans Awaiting Disbursal Summary','READ',1),(258,'report','READ_Loans Awaiting Disbursal Summary by Month','Loans Awaiting Disbursal Summary by Month','READ',1),(259,'report','READ_Loans Pending Approval','Loans Pending Approval','READ',1),(260,'report','READ_Obligation Met Loans Details','Obligation Met Loans Details','READ',1),(261,'report','READ_Obligation Met Loans Summary','Obligation Met Loans Summary','READ',1),(262,'report','READ_Portfolio at Risk','Portfolio at Risk','READ',1),(263,'report','READ_Portfolio at Risk by Branch','Portfolio at Risk by Branch','READ',1),(264,'report','READ_Rescheduled Loans','Rescheduled Loans','READ',1),(265,'report','READ_Trial Balance','Trial Balance','READ',1),(266,'report','READ_Written-Off Loans','Written-Off Loans','READ',1),(272,'datatable','CREATE_extra_client_details','extra_client_details','CREATE',1),(273,'datatable','CREATE_extra_family_details','extra_family_details','CREATE',1),(274,'datatable','CREATE_extra_loan_details','extra_loan_details','CREATE',1),(275,'datatable','READ_extra_client_details','extra_client_details','READ',1),(276,'datatable','READ_extra_family_details','extra_family_details','READ',1),(277,'datatable','READ_extra_loan_details','extra_loan_details','READ',1),(278,'datatable','UPDATE_extra_client_details','extra_client_details','UPDATE',1),(279,'datatable','UPDATE_extra_family_details','extra_family_details','UPDATE',1),(280,'datatable','UPDATE_extra_loan_details','extra_loan_details','UPDATE',1),(281,'datatable','DELETE_extra_client_details','extra_client_details','DELETE',1),(282,'datatable','DELETE_extra_family_details','extra_family_details','DELETE',1),(283,'datatable','DELETE_extra_loan_details','extra_loan_details','DELETE',1); +INSERT INTO `m_permission` VALUES (1,'special','ALL_FUNCTIONS',NULL,NULL,0),(2,'special','ALL_FUNCTIONS_READ',NULL,NULL,0),(3,'special','CHECKER_SUPER_USER',NULL,NULL,0),(4,'special','REPORTING_SUPER_USER',NULL,NULL,0),(5,'authorisation','READ_PERMISSION','PERMISSION','READ',0),(6,'authorisation','PERMISSIONS_ROLE','ROLE','PERMISSIONS',1),(7,'authorisation','CREATE_ROLE','ROLE','CREATE',1),(8,'authorisation','CREATE_ROLE_CHECKER','ROLE','CREATE',1),(9,'authorisation','READ_ROLE','ROLE','READ',0),(10,'authorisation','UPDATE_ROLE','ROLE','UPDATE',1),(11,'authorisation','UPDATE_ROLE_CHECKER','ROLE','UPDATE',1),(12,'authorisation','DELETE_ROLE','ROLE','DELETE',1),(13,'authorisation','DELETE_ROLE_CHECKER','ROLE','DELETE',1),(14,'authorisation','CREATE_USER','USER','CREATE',1),(15,'authorisation','CREATE_USER_CHECKER','USER','CREATE',1),(16,'authorisation','READ_USER','USER','READ',0),(17,'authorisation','UPDATE_USER','USER','UPDATE',1),(18,'authorisation','UPDATE_USER_CHECKER','USER','UPDATE',1),(19,'authorisation','DELETE_USER','USER','DELETE',1),(20,'authorisation','DELETE_USER_CHECKER','USER','DELETE',1),(21,'configuration','READ_CONFIGURATION','CONFIGURATION','READ',1),(22,'configuration','UPDATE_CONFIGURATION','CONFIGURATION','UPDATE',1),(23,'configuration','UPDATE_CONFIGURATION_CHECKER','CONFIGURATION','UPDATE',1),(24,'configuration','READ_CODE','CODE','READ',0),(25,'configuration','CREATE_CODE','CODE','CREATE',1),(26,'configuration','CREATE_CODE_CHECKER','CODE','CREATE',1),(27,'configuration','UPDATE_CODE','CODE','UPDATE',1),(28,'configuration','UPDATE_CODE_CHECKER','CODE','UPDATE',1),(29,'configuration','DELETE_CODE','CODE','DELETE',1),(30,'configuration','DELETE_CODE_CHECKER','CODE','DELETE',1),(31,'configuration','READ_CODEVALUE','CODEVALUE','READ',0),(32,'configuration','CREATE_CODEVALUE','CODEVALUE','CREATE',1),(33,'configuration','CREATE_CODEVALUE_CHECKER','CODEVALUE','CREATE',1),(34,'configuration','UPDATE_CODEVALUE','CODEVALUE','UPDATE',1),(35,'configuration','UPDATE_CODEVALUE_CHECKER','CODEVALUE','UPDATE',1),(36,'configuration','DELETE_CODEVALUE','CODEVALUE','DELETE',1),(37,'configuration','DELETE_CODEVALUE_CHECKER','CODEVALUE','DELETE',1),(38,'configuration','READ_CURRENCY','CURRENCY','READ',0),(39,'configuration','UPDATE_CURRENCY','CURRENCY','UPDATE',1),(40,'configuration','UPDATE_CURRENCY_CHECKER','CURRENCY','UPDATE',1),(41,'configuration','UPDATE_PERMISSION','PERMISSION','UPDATE',1),(42,'configuration','UPDATE_PERMISSION_CHECKER','PERMISSION','UPDATE',1),(43,'configuration','READ_DATATABLE','DATATABLE','READ',0),(44,'configuration','REGISTER_DATATABLE','DATATABLE','REGISTER',1),(45,'configuration','REGISTER_DATATABLE_CHECKER','DATATABLE','REGISTER',1),(46,'configuration','DEREGISTER_DATATABLE','DATATABLE','DEREGISTER',1),(47,'configuration','DEREGISTER_DATATABLE_CHECKER','DATATABLE','DEREGISTER',1),(48,'configuration','READ_AUDIT','AUDIT','READ',0),(49,'organisation','READ_MAKERCHECKER','MAKERCHECKER','READ',0),(50,'organisation','READ_CHARGE','CHARGE','READ',0),(51,'organisation','CREATE_CHARGE','CHARGE','CREATE',1),(52,'organisation','CREATE_CHARGE_CHECKER','CHARGE','CREATE',1),(53,'organisation','UPDATE_CHARGE','CHARGE','UPDATE',1),(54,'organisation','UPDATE_CHARGE_CHECKER','CHARGE','UPDATE',1),(55,'organisation','DELETE_CHARGE','CHARGE','DELETE',1),(56,'organisation','DELETE_CHARGE_CHECKER','CHARGE','DELETE',1),(57,'organisation','READ_FUND','FUND','READ',0),(58,'organisation','CREATE_FUND','FUND','CREATE',1),(59,'organisation','CREATE_FUND_CHECKER','FUND','CREATE',1),(60,'organisation','UPDATE_FUND','FUND','UPDATE',1),(61,'organisation','UPDATE_FUND_CHECKER','FUND','UPDATE',1),(62,'organisation','DELETE_FUND','FUND','DELETE',1),(63,'organisation','DELETE_FUND_CHECKER','FUND','DELETE',1),(64,'organisation','READ_LOANPRODUCT','LOANPRODUCT','READ',0),(65,'organisation','CREATE_LOANPRODUCT','LOANPRODUCT','CREATE',1),(66,'organisation','CREATE_LOANPRODUCT_CHECKER','LOANPRODUCT','CREATE',1),(67,'organisation','UPDATE_LOANPRODUCT','LOANPRODUCT','UPDATE',1),(68,'organisation','UPDATE_LOANPRODUCT_CHECKER','LOANPRODUCT','UPDATE',1),(69,'organisation','DELETE_LOANPRODUCT','LOANPRODUCT','DELETE',1),(70,'organisation','DELETE_LOANPRODUCT_CHECKER','LOANPRODUCT','DELETE',1),(71,'organisation','READ_OFFICE','OFFICE','READ',0),(72,'organisation','CREATE_OFFICE','OFFICE','CREATE',1),(73,'organisation','CREATE_OFFICE_CHECKER','OFFICE','CREATE',1),(74,'organisation','UPDATE_OFFICE','OFFICE','UPDATE',1),(75,'organisation','UPDATE_OFFICE_CHECKER','OFFICE','UPDATE',1),(76,'organisation','READ_OFFICETRANSACTION','OFFICETRANSACTION','READ',0),(77,'organisation','DELETE_OFFICE_CHECKER','OFFICE','DELETE',1),(78,'organisation','CREATE_OFFICETRANSACTION','OFFICETRANSACTION','CREATE',1),(79,'organisation','CREATE_OFFICETRANSACTION_CHECKER','OFFICETRANSACTION','CREATE',1),(80,'organisation','DELETE_OFFICETRANSACTION','OFFICETRANSACTION','DELETE',1),(81,'organisation','DELETE_OFFICETRANSACTION_CHECKER','OFFICETRANSACTION','DELETE',1),(82,'organisation','READ_STAFF','STAFF','READ',0),(83,'organisation','CREATE_STAFF','STAFF','CREATE',1),(84,'organisation','CREATE_STAFF_CHECKER','STAFF','CREATE',1),(85,'organisation','UPDATE_STAFF','STAFF','UPDATE',1),(86,'organisation','UPDATE_STAFF_CHECKER','STAFF','UPDATE',1),(87,'organisation','DELETE_STAFF','STAFF','DELETE',1),(88,'organisation','DELETE_STAFF_CHECKER','STAFF','DELETE',1),(89,'organisation','READ_SAVINGSPRODUCT','SAVINGSPRODUCT','READ',0),(90,'organisation','CREATE_SAVINGSPRODUCT','SAVINGSPRODUCT','CREATE',1),(91,'organisation','CREATE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','CREATE',1),(92,'organisation','UPDATE_SAVINGSPRODUCT','SAVINGSPRODUCT','UPDATE',1),(93,'organisation','UPDATE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','UPDATE',1),(94,'organisation','DELETE_SAVINGSPRODUCT','SAVINGSPRODUCT','DELETE',1),(95,'organisation','DELETE_SAVINGSPRODUCT_CHECKER','SAVINGSPRODUCT','DELETE',1),(96,'organisation','READ_DEPOSITPRODUCT','DEPOSITPRODUCT','READ',0),(97,'organisation','CREATE_DEPOSITPRODUCT','DEPOSITPRODUCT','CREATE',1),(98,'organisation','CREATE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','CREATE',1),(99,'organisation','UPDATE_DEPOSITPRODUCT','DEPOSITPRODUCT','UPDATE',1),(100,'organisation','UPDATE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','UPDATE',1),(101,'organisation','DELETE_DEPOSITPRODUCT','DEPOSITPRODUCT','DELETE',1),(102,'organisation','DELETE_DEPOSITPRODUCT_CHECKER','DEPOSITPRODUCT','DELETE',1),(103,'portfolio','READ_LOAN','LOAN','READ',0),(104,'portfolio','CREATE_LOAN','LOAN','CREATE',1),(105,'portfolio','CREATE_LOAN_CHECKER','LOAN','CREATE',1),(106,'portfolio','UPDATE_LOAN','LOAN','UPDATE',1),(107,'portfolio','UPDATE_LOAN_CHECKER','LOAN','UPDATE',1),(108,'portfolio','DELETE_LOAN','LOAN','DELETE',1),(109,'portfolio','DELETE_LOAN_CHECKER','LOAN','DELETE',1),(110,'portfolio','READ_CLIENT','CLIENT','READ',0),(111,'portfolio','CREATE_CLIENT','CLIENT','CREATE',1),(112,'portfolio','CREATE_CLIENT_CHECKER','CLIENT','CREATE',1),(113,'portfolio','UPDATE_CLIENT','CLIENT','UPDATE',1),(114,'portfolio','UPDATE_CLIENT_CHECKER','CLIENT','UPDATE',1),(115,'portfolio','DELETE_CLIENT','CLIENT','DELETE',1),(116,'portfolio','DELETE_CLIENT_CHECKER','CLIENT','DELETE',1),(117,'portfolio','READ_CLIENTIMAGE','CLIENTIMAGE','READ',0),(118,'portfolio','CREATE_CLIENTIMAGE','CLIENTIMAGE','CREATE',1),(119,'portfolio','CREATE_CLIENTIMAGE_CHECKER','CLIENTIMAGE','CREATE',1),(120,'portfolio','DELETE_CLIENTIMAGE','CLIENTIMAGE','DELETE',1),(121,'portfolio','DELETE_CLIENTIMAGE_CHECKER','CLIENTIMAGE','DELETE',1),(122,'portfolio','READ_CLIENTNOTE','CLIENTNOTE','READ',0),(123,'portfolio','CREATE_CLIENTNOTE','CLIENTNOTE','CREATE',1),(124,'portfolio','CREATE_CLIENTNOTE_CHECKER','CLIENTNOTE','CREATE',1),(125,'portfolio','UPDATE_CLIENTNOTE','CLIENTNOTE','UPDATE',1),(126,'portfolio','UPDATE_CLIENTNOTE_CHECKER','CLIENTNOTE','UPDATE',1),(127,'portfolio','DELETE_CLIENTNOTE','CLIENTNOTE','DELETE',1),(128,'portfolio','DELETE_CLIENTNOTE_CHECKER','CLIENTNOTE','DELETE',1),(129,'portfolio','READ_CLIENTIDENTIFIER','CLIENTIDENTIFIER','READ',0),(130,'portfolio','CREATE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','CREATE',1),(131,'portfolio','CREATE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','CREATE',1),(132,'portfolio','UPDATE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','UPDATE',1),(133,'portfolio','UPDATE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','UPDATE',1),(134,'portfolio','DELETE_CLIENTIDENTIFIER','CLIENTIDENTIFIER','DELETE',1),(135,'portfolio','DELETE_CLIENTIDENTIFIER_CHECKER','CLIENTIDENTIFIER','DELETE',1),(136,'portfolio','READ_DOCUMENT','DOCUMENT','READ',0),(137,'portfolio','CREATE_DOCUMENT','DOCUMENT','CREATE',1),(138,'portfolio','CREATE_DOCUMENT_CHECKER','DOCUMENT','CREATE',1),(139,'portfolio','UPDATE_DOCUMENT','DOCUMENT','UPDATE',1),(140,'portfolio','UPDATE_DOCUMENT_CHECKER','DOCUMENT','UPDATE',1),(141,'portfolio','DELETE_DOCUMENT','DOCUMENT','DELETE',1),(142,'portfolio','DELETE_DOCUMENT_CHECKER','DOCUMENT','DELETE',1),(143,'portfolio','READ_GROUP','GROUP','READ',0),(144,'portfolio','CREATE_GROUP','GROUP','CREATE',1),(145,'portfolio','CREATE_GROUP_CHECKER','GROUP','CREATE',1),(146,'portfolio','UPDATE_GROUP','GROUP','UPDATE',1),(147,'portfolio','UPDATE_GROUP_CHECKER','GROUP','UPDATE',1),(148,'portfolio','DELETE_GROUP','GROUP','DELETE',1),(149,'portfolio','DELETE_GROUP_CHECKER','GROUP','DELETE',1),(150,'portfolio','CREATE_LOANCHARGE','LOANCHARGE','CREATE',1),(151,'portfolio','CREATE_LOANCHARGE_CHECKER','LOANCHARGE','CREATE',1),(152,'portfolio','UPDATE_LOANCHARGE','LOANCHARGE','UPDATE',1),(153,'portfolio','UPDATE_LOANCHARGE_CHECKER','LOANCHARGE','UPDATE',1),(154,'portfolio','DELETE_LOANCHARGE','LOANCHARGE','DELETE',1),(155,'portfolio','DELETE_LOANCHARGE_CHECKER','LOANCHARGE','DELETE',1),(156,'portfolio','WAIVE_LOANCHARGE','LOANCHARGE','WAIVE',1),(157,'portfolio','WAIVE_LOANCHARGE_CHECKER','LOANCHARGE','WAIVE',1),(158,'portfolio','READ_DEPOSITACCOUNT','DEPOSITACCOUNT','READ',0),(159,'portfolio','CREATE_DEPOSITACCOUNT','DEPOSITACCOUNT','CREATE',1),(160,'portfolio','CREATE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','CREATE',1),(161,'portfolio','UPDATE_DEPOSITACCOUNT','DEPOSITACCOUNT','UPDATE',1),(162,'portfolio','UPDATE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','UPDATE',1),(163,'portfolio','DELETE_DEPOSITACCOUNT','DEPOSITACCOUNT','DELETE',1),(164,'portfolio','DELETE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','DELETE',1),(165,'portfolio','READ_SAVINGSACCOUNT','SAVINGSACCOUNT','READ',0),(166,'portfolio','CREATE_SAVINGSACCOUNT','SAVINGSACCOUNT','CREATE',1),(167,'portfolio','CREATE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','CREATE',1),(168,'portfolio','UPDATE_SAVINGSACCOUNT','SAVINGSACCOUNT','UPDATE',1),(169,'portfolio','UPDATE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','UPDATE',1),(170,'portfolio','DELETE_SAVINGSACCOUNT','SAVINGSACCOUNT','DELETE',1),(171,'portfolio','DELETE_SAVINGSACCOUNT_CHECKER','SAVINGSACCOUNT','DELETE',1),(172,'portfolio','READ_GUARANTOR','GUARANTOR','READ',0),(173,'portfolio','CREATE_GUARANTOR','GUARANTOR','CREATE',1),(174,'portfolio','CREATE_GUARANTOR_CHECKER','GUARANTOR','CREATE',1),(175,'portfolio','UPDATE_GUARANTOR','GUARANTOR','UPDATE',1),(176,'portfolio','UPDATE_GUARANTOR_CHECKER','GUARANTOR','UPDATE',1),(177,'portfolio','DELETE_GUARANTOR','GUARANTOR','DELETE',1),(178,'portfolio','DELETE_GUARANTOR_CHECKER','GUARANTOR','DELETE',1),(179,'transaction_loan','APPROVE_LOAN','LOAN','APPROVE',1),(180,'transaction_loan','APPROVEINPAST_LOAN','LOAN','APPROVEINPAST',1),(181,'transaction_loan','REJECT_LOAN','LOAN','REJECT',1),(182,'transaction_loan','REJECTINPAST_LOAN','LOAN','REJECTINPAST',1),(183,'transaction_loan','WITHDRAW_LOAN','LOAN','WITHDRAW',1),(184,'transaction_loan','WITHDRAWINPAST_LOAN','LOAN','WITHDRAWINPAST',1),(185,'transaction_loan','APPROVALUNDO_LOAN','LOAN','APPROVALUNDO',1),(186,'transaction_loan','DISBURSE_LOAN','LOAN','DISBURSE',1),(187,'transaction_loan','DISBURSEINPAST_LOAN','LOAN','DISBURSEINPAST',1),(188,'transaction_loan','DISBURSALUNDO_LOAN','LOAN','DISBURSALUNDO',1),(189,'transaction_loan','REPAYMENT_LOAN','LOAN','REPAYMENT',1),(190,'transaction_loan','REPAYMENTINPAST_LOAN','LOAN','REPAYMENTINPAST',1),(191,'transaction_loan','ADJUST_LOAN','LOAN','ADJUST',1),(192,'transaction_loan','WAIVEINTERESTPORTION_LOAN','LOAN','WAIVEINTERESTPORTION',1),(193,'transaction_loan','WRITEOFF_LOAN','LOAN','WRITEOFF',1),(194,'transaction_loan','CLOSE_LOAN','LOAN','CLOSE',1),(195,'transaction_loan','CLOSEASRESCHEDULED_LOAN','LOAN','CLOSEASRESCHEDULED',1),(196,'transaction_loan','UPDATELOANOFFICER_LOAN','LOAN','UPDATELOANOFFICER',1),(197,'transaction_loan','UPDATELOANOFFICER_LOAN_CHECKER','LOAN','UPDATELOANOFFICER',1),(198,'transaction_loan','REMOVELOANOFFICER_LOAN','LOAN','REMOVELOANOFFICER',1),(199,'transaction_loan','REMOVELOANOFFICER_LOAN_CHECKER','LOAN','REMOVELOANOFFICER',1),(200,'transaction_loan','BULKREASSIGN_LOAN','LOAN','BULKREASSIGN',1),(201,'transaction_loan','BULKREASSIGN_LOAN_CHECKER','LOAN','BULKREASSIGN',1),(202,'transaction_loan','APPROVE_LOAN_CHECKER','LOAN','APPROVE',1),(203,'transaction_loan','APPROVEINPAST_LOAN_CHECKER','LOAN','APPROVEINPAST',1),(204,'transaction_loan','REJECT_LOAN_CHECKER','LOAN','REJECT',1),(205,'transaction_loan','REJECTINPAST_LOAN_CHECKER','LOAN','REJECTINPAST',1),(206,'transaction_loan','WITHDRAW_LOAN_CHECKER','LOAN','WITHDRAW',1),(207,'transaction_loan','WITHDRAWINPAST_LOAN_CHECKER','LOAN','WITHDRAWINPAST',1),(208,'transaction_loan','APPROVALUNDO_LOAN_CHECKER','LOAN','APPROVALUNDO',1),(209,'transaction_loan','DISBURSE_LOAN_CHECKER','LOAN','DISBURSE',1),(210,'transaction_loan','DISBURSEINPAST_LOAN_CHECKER','LOAN','DISBURSEINPAST',1),(211,'transaction_loan','DISBURSALUNDO_LOAN_CHECKER','LOAN','DISBURSALUNDO',1),(212,'transaction_loan','REPAYMENT_LOAN_CHECKER','LOAN','REPAYMENT',1),(213,'transaction_loan','REPAYMENTINPAST_LOAN_CHECKER','LOAN','REPAYMENTINPAST',1),(214,'transaction_loan','ADJUST_LOAN_CHECKER','LOAN','ADJUST',1),(215,'transaction_loan','WAIVEINTERESTPORTION_LOAN_CHECKER','LOAN','WAIVEINTERESTPORTION',1),(216,'transaction_loan','WRITEOFF_LOAN_CHECKER','LOAN','WRITEOFF',1),(217,'transaction_loan','CLOSE_LOAN_CHECKER','LOAN','CLOSE',1),(218,'transaction_loan','CLOSEASRESCHEDULED_LOAN_CHECKER','LOAN','CLOSEASRESCHEDULED',1),(219,'transaction_deposit','APPROVE_DEPOSITACCOUNT','DEPOSITACCOUNT','APPROVE',1),(220,'transaction_deposit','REJECT_DEPOSITACCOUNT','DEPOSITACCOUNT','REJECT',1),(221,'transaction_deposit','WITHDRAW_DEPOSITACCOUNT','DEPOSITACCOUNT','WITHDRAW',1),(222,'transaction_deposit','APPROVALUNDO_DEPOSITACCOUNT','DEPOSITACCOUNT','APPROVALUNDO',1),(223,'transaction_deposit','WITHDRAWAL_DEPOSITACCOUNT','DEPOSITACCOUNT','WITHDRAWAL',1),(224,'transaction_deposit','INTEREST_DEPOSITACCOUNT','DEPOSITACCOUNT','INTEREST',1),(225,'transaction_deposit','RENEW_DEPOSITACCOUNT','DEPOSITACCOUNT','RENEW',1),(226,'transaction_deposit','APPROVE_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','APPROVE',1),(227,'transaction_deposit','REJECT_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','REJECT',1),(228,'transaction_deposit','WITHDRAW_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','WITHDRAW',1),(229,'transaction_deposit','APPROVALUNDO_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','APPROVALUNDO',1),(230,'transaction_deposit','WITHDRAWAL_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','WITHDRAWAL',1),(231,'transaction_deposit','INTEREST_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','INTEREST',1),(232,'transaction_deposit','RENEW_DEPOSITACCOUNT_CHECKER','DEPOSITACCOUNT','RENEW',1),(233,'accounting','CREATE_GLACCOUNT','GLACCOUNT','CREATE',1),(234,'accounting','UPDATE_GLACCOUNT','GLACCOUNT','UPDATE',1),(235,'accounting','DELETE_GLACCOUNT','GLACCOUNT','DELETE',1),(236,'accounting','CREATE_GLCLOSURE','GLCLOSURE','CREATE',1),(237,'accounting','UPDATE_GLCLOSURE','GLCLOSURE','UPDATE',1),(238,'accounting','DELETE_GLCLOSURE','GLCLOSURE','DELETE',1),(239,'accounting','CREATE_JOURNALENTRY','JOURNALENTRY','CREATE',1),(240,'accounting','REVERSE_JOURNALENTRY','JOURNALENTRY','REVERSE',1),(241,'report','READ_Active Loans - Details','Active Loans - Details','READ',1),(242,'report','READ_Active Loans - Summary','Active Loans - Summary','READ',1),(243,'report','READ_Active Loans by Disbursal Period','Active Loans by Disbursal Period','READ',1),(244,'report','READ_Active Loans in last installment','Active Loans in last installment','READ',1),(245,'report','READ_Active Loans in last installment Summary','Active Loans in last installment Summary','READ',1),(246,'report','READ_Active Loans Passed Final Maturity','Active Loans Passed Final Maturity','READ',1),(247,'report','READ_Active Loans Passed Final Maturity Summary','Active Loans Passed Final Maturity Summary','READ',1),(248,'report','READ_Aging Summary (Arrears in weeks) - review','Aging Summary (Arrears in weeks) - review','READ',1),(249,'report','READ_Amount In Arrears','Amount In Arrears','READ',1),(250,'report','READ_Balance Sheet','Balance Sheet','READ',1),(251,'report','READ_Client Listing','Client Listing','READ',1),(252,'report','READ_Client Loans Listing','Client Loans Listing','READ',1),(253,'report','READ_Funds Disbursed Between Dates Summary','Funds Disbursed Between Dates Summary','READ',1),(254,'report','READ_Funds Disbursed Between Dates Summary by Office','Funds Disbursed Between Dates Summary by Office','READ',1),(255,'report','READ_Income Statement','Income Statement','READ',1),(256,'report','READ_Loans Awaiting Disbursal','Loans Awaiting Disbursal','READ',1),(257,'report','READ_Loans Awaiting Disbursal Summary','Loans Awaiting Disbursal Summary','READ',1),(258,'report','READ_Loans Awaiting Disbursal Summary by Month','Loans Awaiting Disbursal Summary by Month','READ',1),(259,'report','READ_Loans Pending Approval','Loans Pending Approval','READ',1),(260,'report','READ_Obligation Met Loans Details','Obligation Met Loans Details','READ',1),(261,'report','READ_Obligation Met Loans Summary','Obligation Met Loans Summary','READ',1),(262,'report','READ_Portfolio at Risk','Portfolio at Risk','READ',1),(263,'report','READ_Portfolio at Risk by Branch','Portfolio at Risk by Branch','READ',1),(264,'report','READ_Rescheduled Loans','Rescheduled Loans','READ',1),(265,'report','READ_Trial Balance','Trial Balance','READ',1),(266,'report','READ_Written-Off Loans','Written-Off Loans','READ',1),(272,'datatable','CREATE_client additional data','client additional data','CREATE',1),(273,'datatable','CREATE_impact measurement','impact measurement','CREATE',1),(274,'datatable','CREATE_loan additional data','loan additional data','CREATE',1),(275,'datatable','READ_client additional data','client additional data','READ',1),(276,'datatable','READ_impact measurement','impact measurement','READ',1),(277,'datatable','READ_loan additional data','loan additional data','READ',1),(278,'datatable','UPDATE_client additional data','client additional data','UPDATE',1),(279,'datatable','UPDATE_impact measurement','impact measurement','UPDATE',1),(280,'datatable','UPDATE_loan additional data','loan additional data','UPDATE',1),(281,'datatable','DELETE_client additional data','client additional data','DELETE',1),(282,'datatable','DELETE_impact measurement','impact measurement','DELETE',1),(283,'datatable','DELETE_loan additional data','loan additional data','DELETE',1); /*!40000 ALTER TABLE `m_permission` ENABLE KEYS */; UNLOCK TABLES; @@ -1311,7 +1379,7 @@ CREATE TABLE `m_portfolio_command_source` ( KEY `loan_id` (`office_id`), CONSTRAINT `FK_m_checker_m_appuser` FOREIGN KEY (`checker_id`) REFERENCES `m_appuser` (`id`), CONSTRAINT `FK_m_maker_m_appuser` FOREIGN KEY (`maker_id`) REFERENCES `m_appuser` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1320,6 +1388,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,'/clients/template',1,'{\"officeId\":\"2\",\"firstname\":\"Kampala\",\"middlename\":\"first\",\"lastname\":\"Client\",\"fullname\":\"\",\"externalId\":\"\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"joinedDate\":\"2011-02-01\"}',1,'2013-02-26 21:26:31',NULL,NULL,1),(2,'CREATE','LOAN',2,NULL,1,1,'/loans',1,'{\"clientId\":\"1\",\"dateFormat\":\"yyyy-MM-dd\",\"locale\":\"en\",\"productId\":\"1\",\"loanOfficerId\":\"2\",\"submittedOnDate\":\"2011-02-01\",\"loanPurposeId\":\"22\",\"principal\":\"1,000,000.00\",\"loanTermFrequency\":\"12\",\"loanTermFrequencyType\":\"2\",\"numberOfRepayments\":\"12\",\"repaymentEvery\":\"1\",\"repaymentFrequencyType\":\"2\",\"transactionProcessingStrategyId\":\"2\",\"expectedDisbursementDate\":\"2011-02-08\",\"repaymentsStartingFromDate\":\"\",\"interestRatePerPeriod\":\"24\",\"interestRateFrequencyType\":\"3\",\"amortizationType\":\"1\",\"interestType\":\"1\",\"interestCalculationPeriodType\":\"1\",\"interestChargedFromDate\":\"\",\"inArrearsTolerance\":\"\",\"charges\":[{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-03-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-04-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-05-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-06-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-07-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-08-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-09-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-10-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-11-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2011-12-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-01-08\"},{\"chargeId\":\"1\",\"amount\":\"1,500\",\"dueDate\":\"2012-02-08\"}],\"collateral\":[{\"id\":\"\",\"type\":\"19\",\"description\":\" collateral example 1.\"},{\"id\":\"\",\"type\":\"18\",\"description\":\"collateral example notes 2. \"}]}',1,'2013-02-26 21:30:40',NULL,NULL,1),(3,'APPROVE','LOAN',2,NULL,1,1,'/loans/1',1,'{\"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-02-04\"}',1,'2013-02-26 21:33:45',NULL,NULL,1); /*!40000 ALTER TABLE `m_portfolio_command_source` ENABLE KEYS */; UNLOCK TABLES; @@ -1353,17 +1422,9 @@ CREATE TABLE `m_product_deposit` ( `is_lock_in_period_allowed` tinyint(1) NOT NULL DEFAULT '0', `lock_in_period` bigint(20) DEFAULT NULL, `lock_in_period_type` smallint(5) NOT NULL DEFAULT '2', - `createdby_id` bigint(20) DEFAULT NULL, - `created_date` datetime DEFAULT NULL, - `lastmodified_date` datetime DEFAULT NULL, - `lastmodifiedby_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name_deposit_product` (`name`), - UNIQUE KEY `externalid_deposit_product` (`external_id`), - KEY `FKJPW0000000000003` (`createdby_id`), - KEY `FKJPW0000000000004` (`lastmodifiedby_id`), - CONSTRAINT `FKJPX0000000000003` FOREIGN KEY (`createdby_id`) REFERENCES `m_appuser` (`id`), - CONSTRAINT `FKJPX0000000000004` FOREIGN KEY (`lastmodifiedby_id`) REFERENCES `m_appuser` (`id`) + UNIQUE KEY `externalid_deposit_product` (`external_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1409,7 +1470,7 @@ CREATE TABLE `m_product_loan` ( 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`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1418,6 +1479,7 @@ CREATE TABLE `m_product_loan` ( LOCK TABLES `m_product_loan` WRITE; /*!40000 ALTER TABLE `m_product_loan` DISABLE KEYS */; +INSERT INTO `m_product_loan` VALUES (1,'UGX',2,'1000000.000000',NULL,'Kampala Product (with cash accounting)','Typical Kampala loan product with cash accounting enabled for testing.',NULL,'24.000000',3,'24.000000',1,1,1,2,12,1,2,2); /*!40000 ALTER TABLE `m_product_loan` ENABLE KEYS */; UNLOCK TABLES; @@ -1711,7 +1773,7 @@ CREATE TABLE `m_staff` ( UNIQUE KEY `display_name` (`display_name`), KEY `FK_m_staff_m_office` (`office_id`), CONSTRAINT `FK_m_staff_m_office` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -1720,6 +1782,7 @@ CREATE TABLE `m_staff` ( LOCK TABLES `m_staff` WRITE; /*!40000 ALTER TABLE `m_staff` DISABLE KEYS */; +INSERT INTO `m_staff` VALUES (1,1,1,'CEDA HO','LoanOfficer','LoanOfficer, CEDA HO'),(2,1,2,'Kampala','LoanOfficer','LoanOfficer, Kampala'); /*!40000 ALTER TABLE `m_staff` ENABLE KEYS */; UNLOCK TABLES; @@ -1777,7 +1840,7 @@ CREATE 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); +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; @@ -1915,7 +1978,7 @@ CREATE TABLE `x_registered_table` ( LOCK TABLES `x_registered_table` WRITE; /*!40000 ALTER TABLE `x_registered_table` DISABLE KEYS */; -INSERT INTO `x_registered_table` VALUES ('extra_client_details','m_client'),('extra_family_details','m_loan'),('extra_loan_details','m_loan'); +INSERT INTO `x_registered_table` VALUES ('client additional data','m_client'),('impact measurement','m_loan'),('loan additional data','m_loan'); /*!40000 ALTER TABLE `x_registered_table` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -1928,4 +1991,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2013-02-25 11:00:18 +-- Dump completed on 2013-02-26 21:34:09 diff --git a/mifosng-db/patches/15-loan-derived-fields.sql b/mifosng-db/patches/15-loan-derived-fields.sql new file mode 100644 index 000000000..ac0a7e50c --- /dev/null +++ b/mifosng-db/patches/15-loan-derived-fields.sql @@ -0,0 +1,43 @@ +ALTER TABLE `m_loan` +DROP COLUMN `lastmodifiedby_id`, +DROP COLUMN `lastmodified_date`, +DROP COLUMN `created_date`, +DROP COLUMN `createdby_id`; + + +ALTER TABLE `m_loan` +CHANGE COLUMN `total_charges_due_at_disbursement_derived` `total_charges_due_at_disbursement_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `closedon_userid` ; + +ALTER TABLE `m_loan` +ADD COLUMN `principal_disbursed_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_charges_due_at_disbursement_derived` , +ADD COLUMN `principal_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `principal_disbursed_derived` , +ADD COLUMN `principal_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `principal_repaid_derived` , +ADD COLUMN `principal_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `principal_writtenoff_derived`, +ADD COLUMN `principal_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `principal_outstanding_derived`, +ADD COLUMN `interest_charged_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `principal_overdue_derived` , +ADD COLUMN `interest_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_charged_derived` , +ADD COLUMN `interest_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_repaid_derived` , +ADD COLUMN `interest_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_waived_derived` , +ADD COLUMN `interest_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_writtenoff_derived`, +ADD COLUMN `interest_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_outstanding_derived`, +ADD COLUMN `fee_charges_charged_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `interest_overdue_derived` , +ADD COLUMN `fee_charges_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_charged_derived` , +ADD COLUMN `fee_charges_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_repaid_derived` , +ADD COLUMN `fee_charges_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_waived_derived` , +ADD COLUMN `fee_charges_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_writtenoff_derived`, +ADD COLUMN `fee_charges_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_outstanding_derived`, +ADD COLUMN `penalty_charges_charged_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `fee_charges_overdue_derived` , +ADD COLUMN `penalty_charges_repaid_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_charged_derived` , +ADD COLUMN `penalty_charges_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_repaid_derived` , +ADD COLUMN `penalty_charges_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_waived_derived`, +ADD COLUMN `penalty_charges_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_writtenoff_derived`, +ADD COLUMN `penalty_charges_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_outstanding_derived`, +ADD COLUMN `total_expected_repayment_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `penalty_charges_overdue_derived`, +ADD COLUMN `total_repayment_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_expected_repayment_derived`, +ADD COLUMN `total_expected_costofloan_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_repayment_derived`, +ADD COLUMN `total_costofloan_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_expected_costofloan_derived`, +ADD COLUMN `total_waived_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_costofloan_derived`, +ADD COLUMN `total_writtenoff_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_waived_derived`, +ADD COLUMN `total_outstanding_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_writtenoff_derived`, +ADD COLUMN `total_overdue_derived` DECIMAL(19,6) NOT NULL DEFAULT 0.0 AFTER `total_outstanding_derived`, +ADD COLUMN `overdue_since_date_derived` DATE NULL AFTER `total_outstanding_derived`; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/domain/JdbcSupport.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/domain/JdbcSupport.java index afd45ba4c..6ecc4d2aa 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/domain/JdbcSupport.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/domain/JdbcSupport.java @@ -16,46 +16,60 @@ import org.joda.time.LocalDate; import org.springframework.jdbc.support.JdbcUtils; /** - * Support for retrieving possibly null values from jdbc recordset delegating to springs {@link JdbcUtils} where possible. + * Support for retrieving possibly null values from jdbc recordset delegating to + * springs {@link JdbcUtils} where possible. */ public class JdbcSupport { - public static DateTime getDateTime(ResultSet rs, String columnName) throws SQLException { - DateTime dateTime = null; - Timestamp dateValue = rs.getTimestamp(columnName); - if (dateValue != null) { - dateTime = new DateTime(dateValue.getTime()); - } - return dateTime; - } - - public static LocalDate getLocalDate(final ResultSet rs, final String columnName) throws SQLException { - LocalDate localDate = null; - Date dateValue = rs.getDate(columnName); - if (dateValue != null) { - localDate = new LocalDate(dateValue); - } - return localDate; - } + public static DateTime getDateTime(final ResultSet rs, final String columnName) throws SQLException { + DateTime dateTime = null; + Timestamp dateValue = rs.getTimestamp(columnName); + if (dateValue != null) { + dateTime = new DateTime(dateValue.getTime()); + } + return dateTime; + } - public static Long getLong(final ResultSet rs, final String columnName) throws SQLException { - return (Long) JdbcUtils.getResultSetValue(rs, rs.findColumn(columnName), Long.class); - } + public static LocalDate getLocalDate(final ResultSet rs, final String columnName) throws SQLException { + LocalDate localDate = null; + final Date dateValue = rs.getDate(columnName); + if (dateValue != null) { + localDate = new LocalDate(dateValue); + } + return localDate; + } - public static Integer getInteger(final ResultSet rs, final String columnName) throws SQLException { - return (Integer) JdbcUtils.getResultSetValue(rs, rs.findColumn(columnName), Integer.class); - } + public static Long getLong(final ResultSet rs, final String columnName) throws SQLException { + return (Long) JdbcUtils.getResultSetValue(rs, rs.findColumn(columnName), Long.class); + } - public static BigDecimal getBigDecimalDefaultToZeroIfNull(final ResultSet rs, final String columnName) throws SQLException { - final BigDecimal value = rs.getBigDecimal(columnName); - return defaultToZeroIfNull(value); - } - - private static BigDecimal defaultToZeroIfNull(final BigDecimal value) { - BigDecimal result = BigDecimal.ZERO; - if (value != null) { - result = value; - } - return result; - } + public static Integer getInteger(final ResultSet rs, final String columnName) throws SQLException { + return (Integer) JdbcUtils.getResultSetValue(rs, rs.findColumn(columnName), Integer.class); + } + + public static BigDecimal getBigDecimalDefaultToZeroIfNull(final ResultSet rs, final String columnName) throws SQLException { + final BigDecimal value = rs.getBigDecimal(columnName); + return defaultToZeroIfNull(value); + } + + private static BigDecimal defaultToZeroIfNull(final BigDecimal value) { + BigDecimal result = BigDecimal.ZERO; + if (value != null) { + result = value; + } + return result; + } + + public static BigDecimal getBigDecimalDefaultToNullIfZero(final ResultSet rs, final String columnName) throws SQLException { + final BigDecimal value = rs.getBigDecimal(columnName); + return defaultToNullIfZero(value); + } + + private static BigDecimal defaultToNullIfZero(final BigDecimal value) { + BigDecimal result = value; + if (BigDecimal.ZERO.compareTo(value) == 0) { + result = null; + } + return result; + } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java index 6960ca376..f1c9bf05e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java @@ -81,9 +81,9 @@ public class LoansApiResource { "inArrearsTolerance", "termFrequency", "termPeriodFrequencyType", "numberOfRepayments", "repaymentEvery", "interestRatePerPeriod", "annualInterestRate", "repaymentFrequencyType", "transactionProcessingStrategyId", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", - "expectedFirstRepaymentOnDate", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "repaymentSchedule", - "transactions", "charges", "collateral", "guarantors", "productOptions", "amortizationTypeOptions", "interestTypeOptions", - "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "termFrequencyTypeOptions", + "expectedFirstRepaymentOnDate", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "summary", + "repaymentSchedule", "transactions", "charges", "collateral", "guarantors", "productOptions", "amortizationTypeOptions", + "interestTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "termFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions", "loanOfficerOptions", "loanPurposeOptions", "loanCollateralOptions", "chargeTemplate")); @@ -146,7 +146,7 @@ public class LoansApiResource { @Path("template") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String templateForNewLoanApplication(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId, + public String template(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId, @QueryParam("productId") final Long productId, @Context final UriInfo uriInfo) { context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); @@ -217,7 +217,7 @@ public class LoansApiResource { @Path("{loanId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveLoanAccountDetails(@PathParam("loanId") final Long loanId, @Context final UriInfo uriInfo) { + public String retrieveLoan(@PathParam("loanId") final Long loanId, @Context final UriInfo uriInfo) { context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java index aeb0979d1..1ab3acf9c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java @@ -9,6 +9,8 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; +import javax.persistence.Transient; + import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.codes.data.CodeValueData; import org.mifosplatform.infrastructure.core.data.EnumOptionData; @@ -69,7 +71,7 @@ public class LoanAccountData { // timeline private final LoanApplicationTimelineData timeline; // totals - private final BigDecimal totalFeeChargesAtDisbursement; + private final LoanSummaryData summary; // associations private final LoanScheduleData repaymentSchedule; @@ -95,6 +97,9 @@ public class LoanAccountData { private final ChargeData chargeTemplate; + @Transient + private BigDecimal feeChargesAtDisbursementCharged; + /** * Used to produce a {@link LoanAccountData} with only collateral options * for now. @@ -137,7 +142,8 @@ public class LoanAccountData { final LocalDate expectedFirstRepaymentOnDate = null; final LocalDate interestChargedFromDate = null; final LoanApplicationTimelineData timeline = null; - final BigDecimal totalFeeChargesAtDisbursement = null; + final LoanSummaryData summary = null; + final BigDecimal feeChargesDueAtDisbursementCharged = null; final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; @@ -163,11 +169,11 @@ public class LoanAccountData { loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, - expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, totalFeeChargesAtDisbursement, repaymentSchedule, - transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, - repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, - interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, - loanCollateralOptions); + expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, + repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, + repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, + interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, + loanPurposeOptions, loanCollateralOptions); } /** @@ -210,7 +216,8 @@ public class LoanAccountData { final LocalDate expectedFirstRepaymentOnDate = null; final LocalDate interestChargedFromDate = null; final LoanApplicationTimelineData timeline = LoanApplicationTimelineData.templateDefault(expectedDisbursementDate); - final BigDecimal totalFeeChargesAtDisbursement = null; + final LoanSummaryData summary = null; + final BigDecimal feeChargesDueAtDisbursementCharged = null; final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; @@ -237,11 +244,11 @@ public class LoanAccountData { loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, - expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, totalFeeChargesAtDisbursement, repaymentSchedule, - transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, - repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, - interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, - loanCollateralOptions); + expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, + repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, + repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, + interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, + loanPurposeOptions, loanCollateralOptions); } /** @@ -285,7 +292,8 @@ public class LoanAccountData { final LocalDate expectedFirstRepaymentOnDate = null; final LocalDate interestChargedFromDate = null; final LoanApplicationTimelineData timeline = LoanApplicationTimelineData.templateDefault(expectedDisbursementDate); - final BigDecimal totalFeeChargesAtDisbursement = null; + final LoanSummaryData summary = null; + final BigDecimal feeChargesDueAtDisbursementCharged = null; final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; @@ -312,11 +320,11 @@ public class LoanAccountData { loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, - expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, totalFeeChargesAtDisbursement, repaymentSchedule, - transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, - repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, - interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, - loanCollateralOptions); + expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, + repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, + repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, + interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, + loanPurposeOptions, loanCollateralOptions); } public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) { @@ -357,10 +365,10 @@ public class LoanAccountData { product.getTransactionProcessingStrategyId(), product.getAmortizationType(), product.getInterestRatePerPeriod(), product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(), product.getInterestCalculationPeriodType(), acc.expectedFirstRepaymentOnDate, acc.interestChargedFromDate, acc.timeline, - acc.totalFeeChargesAtDisbursement, repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, - termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, - chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions); + acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, + productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, + interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, + fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions); } /* @@ -378,7 +386,8 @@ public class LoanAccountData { final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType, final BigDecimal annualInterestRate, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType, final LocalDate expectedFirstRepaymentOnDate, final LocalDate interestChargedFromDate, - final LoanApplicationTimelineData timeline, final BigDecimal totalFeeChargesAtDisbursement) { + final LoanApplicationTimelineData timeline, final LoanSummaryData loanSummary, + final BigDecimal feeChargesDueAtDisbursementCharged) { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; @@ -405,10 +414,11 @@ public class LoanAccountData { loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, - interestChargedFromDate, timeline, totalFeeChargesAtDisbursement, repaymentSchedule, transactions, charges, collateral, - guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, - interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, - fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions); + interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, + charges, collateral, guarantors, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, + repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, + interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, + loanCollateralOptions); } /* @@ -433,10 +443,10 @@ public class LoanAccountData { acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.interestChargedFromDate, acc.timeline, - acc.totalFeeChargesAtDisbursement, repaymentSchedule, transactions, charges, collateral, guarantors, productOptions, - termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, - chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions); + acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, + productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, + interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, + fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions); } private LoanAccountData( @@ -477,11 +487,12 @@ public class LoanAccountData { final LocalDate expectedFirstRepaymentOnDate, final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline, - final BigDecimal totalFeeChargesAtDisbursement, // - final LoanScheduleData repaymentSchedule, final Collection transactions, - final Collection charges, final Collection collateral, - final Collection guarantors, final Collection productOptions, - final Collection termFrequencyTypeOptions, final Collection repaymentFrequencyTypeOptions, + final LoanSummaryData summary, // + final BigDecimal feeChargesDueAtDisbursementCharged, final LoanScheduleData repaymentSchedule, + final Collection transactions, final Collection charges, + final Collection collateral, final Collection guarantors, + final Collection productOptions, final Collection termFrequencyTypeOptions, + final Collection repaymentFrequencyTypeOptions, final Collection repaymentStrategyOptions, final Collection interestRateFrequencyTypeOptions, final Collection amortizationTypeOptions, final Collection interestTypeOptions, final Collection interestCalculationPeriodTypeOptions, @@ -527,7 +538,7 @@ public class LoanAccountData { this.timeline = timeline; // totals - this.totalFeeChargesAtDisbursement = totalFeeChargesAtDisbursement; + this.summary = summary; // associations this.repaymentSchedule = repaymentSchedule; @@ -555,7 +566,7 @@ public class LoanAccountData { public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() { return this.timeline.repaymentScheduleRelatedData(this.currency, this.principal, this.inArrearsTolerance, - this.totalFeeChargesAtDisbursement); + this.feeChargesAtDisbursementCharged); } public Long officeId() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanSummaryData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanSummaryData.java new file mode 100644 index 000000000..d874cb5aa --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanSummaryData.java @@ -0,0 +1,101 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.loanaccount.data; + +import java.math.BigDecimal; + +import org.joda.time.LocalDate; +import org.mifosplatform.organisation.monetary.data.CurrencyData; + +/** + * Immutable data object representing loan summary information. + */ +@SuppressWarnings("unused") +public class LoanSummaryData { + + private final CurrencyData currency; + private final BigDecimal principalDisbursed; + private final BigDecimal principalPaid; + private final BigDecimal principalWrittenOff; + private final BigDecimal principalOutstanding; + private final BigDecimal principalOverdue; + private final BigDecimal interestCharged; + private final BigDecimal interestPaid; + private final BigDecimal interestWaived; + private final BigDecimal interestWrittenOff; + private final BigDecimal interestOutstanding; + private final BigDecimal interestOverdue; + private final BigDecimal feeChargesCharged; + private final BigDecimal feeChargesDueAtDisbursementCharged; + private final BigDecimal feeChargesPaid; + private final BigDecimal feeChargesWaived; + private final BigDecimal feeChargesWrittenOff; + private final BigDecimal feeChargesOutstanding; + private final BigDecimal feeChargesOverdue; + private final BigDecimal penaltyChargesCharged; + private final BigDecimal penaltyChargesPaid; + private final BigDecimal penaltyChargesWaived; + private final BigDecimal penaltyChargesWrittenOff; + private final BigDecimal penaltyChargesOutstanding; + private final BigDecimal penaltyChargesOverdue; + private final BigDecimal totalExpectedRepayment; + private final BigDecimal totalRepayment; + private final BigDecimal totalExpectedCostOfLoan; + private final BigDecimal totalCostOfLoan; + private final BigDecimal totalWaived; + private final BigDecimal totalWrittenOff; + private final BigDecimal totalOutstanding; + private final BigDecimal totalOverdue; + private final LocalDate overdueSinceDate; + + public LoanSummaryData(final CurrencyData currency, final BigDecimal principalDisbursed, final BigDecimal principalPaid, + final BigDecimal principalWrittenOff, final BigDecimal principalOutstanding, final BigDecimal principalOverdue, + final BigDecimal interestCharged, final BigDecimal interestPaid, final BigDecimal interestWaived, + final BigDecimal interestWrittenOff, final BigDecimal interestOutstanding, final BigDecimal interestOverdue, + final BigDecimal feeChargesCharged, final BigDecimal feeChargesDueAtDisbursementCharged, final BigDecimal feeChargesPaid, + final BigDecimal feeChargesWaived, final BigDecimal feeChargesWrittenOff, final BigDecimal feeChargesOutstanding, + final BigDecimal feeChargesOverdue, final BigDecimal penaltyChargesCharged, final BigDecimal penaltyChargesPaid, + final BigDecimal penaltyChargesWaived, final BigDecimal penaltyChargesWrittenOff, final BigDecimal penaltyChargesOutstanding, + final BigDecimal penaltyChargesOverdue, final BigDecimal totalExpectedRepayment, final BigDecimal totalRepayment, + final BigDecimal totalExpectedCostOfLoan, final BigDecimal totalCostOfLoan, final BigDecimal totalWaived, + final BigDecimal totalWrittenOff, final BigDecimal totalOutstanding, final BigDecimal totalOverdue, + final LocalDate overdueSinceDate) { + this.currency = currency; + this.principalDisbursed = principalDisbursed; + this.principalPaid = principalPaid; + this.principalWrittenOff = principalWrittenOff; + this.principalOutstanding = principalOutstanding; + this.principalOverdue = principalOverdue; + this.interestCharged = interestCharged; + this.interestPaid = interestPaid; + this.interestWaived = interestWaived; + this.interestWrittenOff = interestWrittenOff; + this.interestOutstanding = interestOutstanding; + this.interestOverdue = interestOverdue; + this.feeChargesCharged = feeChargesCharged; + this.feeChargesDueAtDisbursementCharged = feeChargesDueAtDisbursementCharged; + this.feeChargesPaid = feeChargesPaid; + this.feeChargesWaived = feeChargesWaived; + this.feeChargesWrittenOff = feeChargesWrittenOff; + this.feeChargesOutstanding = feeChargesOutstanding; + this.feeChargesOverdue = feeChargesOverdue; + this.penaltyChargesCharged = penaltyChargesCharged; + this.penaltyChargesPaid = penaltyChargesPaid; + this.penaltyChargesWaived = penaltyChargesWaived; + this.penaltyChargesWrittenOff = penaltyChargesWrittenOff; + this.penaltyChargesOutstanding = penaltyChargesOutstanding; + this.penaltyChargesOverdue = penaltyChargesOverdue; + this.totalExpectedRepayment = totalExpectedRepayment; + this.totalRepayment = totalRepayment; + this.totalExpectedCostOfLoan = totalExpectedCostOfLoan; + this.totalCostOfLoan = totalCostOfLoan; + this.totalWaived = totalWaived; + this.totalWrittenOff = totalWrittenOff; + this.totalOutstanding = totalOutstanding; + this.totalOverdue = totalOverdue; + this.overdueSinceDate = overdueSinceDate; + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java index d12e26df2..2e57a7cf9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/AbstractLoanRepaymentScheduleTransactionProcessor.java @@ -46,7 +46,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen // re-process loan charges over repayment periods (picking up on waived // loan charges) - LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); + LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(currency, disbursementDate, installments, charges); for (LoanTransaction loanTransaction : transactionsPostDisbursement) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java index 0be0a1bde..52dc3abd9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java @@ -84,7 +84,7 @@ public class HeavensFamilyLoanRepaymentScheduleTransactionProcessor extends Abst if (currentInstallment.isPrincipalCompleted(currency)) { // FIXME - KW - if auto waiving interest need to create // another transaction to handle this. - currentInstallment.waiveInterestComponent(currentInstallment.getInterest(currency)); + currentInstallment.waiveInterestComponent(currentInstallment.getInterestCharged(currency)); } loanTransaction.updateComponents(principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index b9ec40b4c..e417be196 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -40,7 +40,6 @@ import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import org.mifosplatform.infrastructure.codes.domain.CodeValue; import org.mifosplatform.infrastructure.core.api.JsonCommand; -import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.infrastructure.core.service.DateUtils; import org.mifosplatform.infrastructure.security.service.RandomPasswordGenerator; import org.mifosplatform.organisation.monetary.data.CurrencyData; @@ -73,11 +72,12 @@ import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingS import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations; import org.mifosplatform.useradministration.domain.AppUser; +import org.springframework.data.jpa.domain.AbstractPersistable; @Entity @Table(name = "m_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "loan_account_no_UNIQUE"), @UniqueConstraint(columnNames = { "external_id" }, name = "loan_externalid_UNIQUE") }) -public class Loan extends AbstractAuditableCustom { +public class Loan extends AbstractPersistable { @Column(name = "account_no", length = 20, unique = true, nullable = false) private String accountNumber; @@ -135,6 +135,7 @@ public class Loan extends AbstractAuditableCustom { @JoinColumn(name = "submittedon_userid", nullable = true) private AppUser submittedBy; + @SuppressWarnings("unused") @Temporal(TemporalType.DATE) @Column(name = "rejectedon_date") private Date rejectedOnDate; @@ -176,6 +177,7 @@ public class Loan extends AbstractAuditableCustom { @JoinColumn(name = "disbursedon_userid", nullable = true) private AppUser disbursedBy; + @SuppressWarnings("unused") @Temporal(TemporalType.DATE) @Column(name = "closedon_date") private Date closedOnDate; @@ -185,6 +187,7 @@ public class Loan extends AbstractAuditableCustom { @JoinColumn(name = "closedon_userid", nullable = true) private AppUser closedBy; + @SuppressWarnings("unused") @Temporal(TemporalType.DATE) @Column(name = "writtenoffon_date") private Date writtenOffOnDate; @@ -193,10 +196,12 @@ public class Loan extends AbstractAuditableCustom { @Column(name = "rescheduledon_date") private Date rescheduledOnDate; + @SuppressWarnings("unused") @Temporal(TemporalType.DATE) @Column(name = "expected_maturedon_date") private Date expectedMaturityDate; + @SuppressWarnings("unused") @Temporal(TemporalType.DATE) @Column(name = "maturedon_date") private Date actualMaturityDate; @@ -234,14 +239,123 @@ public class Loan extends AbstractAuditableCustom { @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true) private final List loanTransactions = new ArrayList(); + // derived totals fields + @Column(name = "principal_disbursed_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalDisbursed; + + @Column(name = "principal_repaid_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalRepaid; + + @Column(name = "principal_writtenoff_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalWrittenOff; + + @Column(name = "principal_outstanding_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalOutstanding; + + @Column(name = "principal_overdue_derived", scale = 6, precision = 19) + private BigDecimal totalPrincipalOverdue; + + @Column(name = "interest_charged_derived", scale = 6, precision = 19) + private BigDecimal totalInterestCharged; + + @Column(name = "interest_repaid_derived", scale = 6, precision = 19) + private BigDecimal totalInterestRepaid; + + @Column(name = "interest_waived_derived", scale = 6, precision = 19) + private BigDecimal totalInterestWaived; + + @Column(name = "interest_writtenoff_derived", scale = 6, precision = 19) + private BigDecimal totalInterestWrittenOff; + + @Column(name = "interest_outstanding_derived", scale = 6, precision = 19) + private BigDecimal totalInterestOutstanding; + + @Column(name = "interest_overdue_derived", scale = 6, precision = 19) + private BigDecimal totalInterestOverdue; + + @Column(name = "fee_charges_charged_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesCharged; + @Column(name = "total_charges_due_at_disbursement_derived", scale = 6, precision = 19) private BigDecimal totalChargesDueAtDisbursement; - @Transient - private boolean accountNumberRequiresAutoGeneration = false; + @Column(name = "fee_charges_repaid_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesRepaid; + + @Column(name = "fee_charges_waived_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesWaived; + + @Column(name = "fee_charges_writtenoff_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesWrittenOff; + + @Column(name = "fee_charges_outstanding_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesOutstanding; + + @Column(name = "fee_charges_overdue_derived", scale = 6, precision = 19) + private BigDecimal totalFeeChargesOverdue; + + @Column(name = "penalty_charges_charged_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesCharged; + + @Column(name = "penalty_charges_repaid_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesRepaid; + + @Column(name = "penalty_charges_waived_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesWaived; + + @Column(name = "penalty_charges_writtenoff_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesWrittenOff; + + @Column(name = "penalty_charges_outstanding_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesOutstanding; + + @Column(name = "penalty_charges_overdue_derived", scale = 6, precision = 19) + private BigDecimal totalPenaltyChargesOverdue; + + @SuppressWarnings("unused") + @Column(name = "total_expected_repayment_derived", scale = 6, precision = 19) + private BigDecimal totalExpectedRepayment; + + @SuppressWarnings("unused") + @Column(name = "total_repayment_derived", scale = 6, precision = 19) + private BigDecimal totalRepayment; + + @SuppressWarnings("unused") + @Column(name = "total_expected_costofloan_derived", scale = 6, precision = 19) + private BigDecimal totalExpectedCostOfLoan; + + @SuppressWarnings("unused") + @Column(name = "total_costofloan_derived", scale = 6, precision = 19) + private BigDecimal totalCostOfLoan; + + @SuppressWarnings("unused") + @Column(name = "total_waived_derived", scale = 6, precision = 19) + private BigDecimal totalWaived; + + @SuppressWarnings("unused") + @Column(name = "total_writtenoff_derived", scale = 6, precision = 19) + private BigDecimal totalWrittenOff; + + @Column(name = "total_outstanding_derived", scale = 6, precision = 19) + private BigDecimal totalOutstanding; + + @SuppressWarnings("unused") + @Column(name = "total_overdue_derived", scale = 6, precision = 19) + private BigDecimal totalOverdue; + + @SuppressWarnings("unused") + @Temporal(TemporalType.DATE) + @Column(name = "overdue_since_date_derived") + private Date overdueSinceDate; @Transient - private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessor = new LoanRepaymentScheduleTransactionProcessorFactory(); + private boolean accountNumberRequiresAutoGeneration = false; + @Transient + private LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory; + @Transient + private LoanLifecycleStateMachine loanLifecycleStateMachine; + @Transient + private LoanSummaryWrapper loanSummaryWrapper; public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose, @@ -385,7 +499,7 @@ public class Loan extends AbstractAuditableCustom { updateTotalChargesDueAtDisbursement(); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (!loanCharge.isDueAtDisbursement()) { @@ -394,9 +508,11 @@ public class Loan extends AbstractAuditableCustom { getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); } else { // just reprocess the loan schedule only for now. - LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); + LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges()); } + + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } private void validateLoanIsNotClosed(final LoanCharge loanCharge) { @@ -443,13 +559,15 @@ public class Loan extends AbstractAuditableCustom { removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(loanCharge); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { final List allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); } + + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) { @@ -491,7 +609,7 @@ public class Loan extends AbstractAuditableCustom { updateTotalChargesDueAtDisbursement(); } - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (!loanCharge.isDueAtDisbursement()) { final List allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); @@ -499,10 +617,12 @@ public class Loan extends AbstractAuditableCustom { getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); } else { // reprocess loan schedule based on charge been waived. - LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); + LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges()); } + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); + return actualChanges; } @@ -534,7 +654,7 @@ public class Loan extends AbstractAuditableCustom { // Waive of charges whose due date falls after latest 'repayment' // transaction dont require entire loan schedule to be reprocessed. - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { final List allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); @@ -542,10 +662,12 @@ public class Loan extends AbstractAuditableCustom { getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); } else { // reprocess loan schedule based on charge been waived. - LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); + LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges()); } + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); + doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine); return waiveLoanChargeTransaction; @@ -628,17 +750,155 @@ public class Loan extends AbstractAuditableCustom { // already against it - then need to re-process it final List repaymentsOrWaivers = retreiveListOfTransactionsPostDisbursement(); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); + + updateLoanScheduleDependentDerivedFields(); + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } - public void updateLoanScheduleDependentDerivedFields() { + private void updateLoanScheduleDependentDerivedFields() { this.expectedMaturityDate = determineExpectedMaturityDate().toDate(); this.actualMaturityDate = determineExpectedMaturityDate().toDate(); } + private void updateLoanSummaryDerivedFields(final LoanSummaryWrapper summary) { + + final Money principal = this.loanRepaymentScheduleDetail.getPrincipal(); + final MonetaryCurrency currency = loanCurrency(); + + if (isNotDisbursed()) { + this.totalPrincipalDisbursed = BigDecimal.ZERO; + this.totalPrincipalRepaid = BigDecimal.ZERO; + this.totalPrincipalWrittenOff = BigDecimal.ZERO; + this.totalPrincipalOutstanding = BigDecimal.ZERO; + this.totalPrincipalOverdue = BigDecimal.ZERO; + this.totalInterestCharged = BigDecimal.ZERO; + this.totalInterestRepaid = BigDecimal.ZERO; + this.totalInterestWaived = BigDecimal.ZERO; + this.totalInterestWrittenOff = BigDecimal.ZERO; + this.totalInterestOutstanding = BigDecimal.ZERO; + this.totalInterestOverdue = BigDecimal.ZERO; + this.totalFeeChargesCharged = BigDecimal.ZERO; + this.totalFeeChargesRepaid = BigDecimal.ZERO; + this.totalFeeChargesWaived = BigDecimal.ZERO; + this.totalFeeChargesWrittenOff = BigDecimal.ZERO; + this.totalFeeChargesOutstanding = BigDecimal.ZERO; + this.totalFeeChargesOverdue = BigDecimal.ZERO; + this.totalPenaltyChargesCharged = BigDecimal.ZERO; + this.totalPenaltyChargesRepaid = BigDecimal.ZERO; + this.totalPenaltyChargesWaived = BigDecimal.ZERO; + this.totalPenaltyChargesWrittenOff = BigDecimal.ZERO; + this.totalPenaltyChargesOutstanding = BigDecimal.ZERO; + this.totalPenaltyChargesOverdue = BigDecimal.ZERO; + this.totalExpectedRepayment = BigDecimal.ZERO; + this.totalRepayment = BigDecimal.ZERO; + this.totalExpectedCostOfLoan = BigDecimal.ZERO; + this.totalCostOfLoan = BigDecimal.ZERO; + this.totalWaived = BigDecimal.ZERO; + this.totalWrittenOff = BigDecimal.ZERO; + this.totalOutstanding = BigDecimal.ZERO; + this.totalOverdue = BigDecimal.ZERO; + this.overdueSinceDate = null; + } else { + this.totalPrincipalDisbursed = principal.getAmount(); + this.totalPrincipalRepaid = summary.calculateTotalPrincipalRepaid(this.repaymentScheduleInstallments, currency).getAmount(); + this.totalPrincipalWrittenOff = summary.calculateTotalPrincipalWrittenOff(this.repaymentScheduleInstallments, currency) + .getAmount(); + + this.totalPrincipalOutstanding = principal.minus(totalPrincipalRepaid).minus(totalPrincipalWrittenOff).getAmount(); + this.totalPrincipalOverdue = summary.calculateTotalPrincipalOverdueOn(this.repaymentScheduleInstallments, currency, + DateUtils.getLocalDateOfTenant()).getAmount(); + + final Money totalInterestCharged = summary.calculateTotalInterestCharged(this.repaymentScheduleInstallments, currency); + this.totalInterestCharged = totalInterestCharged.getAmount(); + this.totalInterestRepaid = summary.calculateTotalInterestRepaid(this.repaymentScheduleInstallments, currency).getAmount(); + this.totalInterestWaived = summary.calculateTotalInterestWaived(this.repaymentScheduleInstallments, currency).getAmount(); + this.totalInterestWrittenOff = summary.calculateTotalInterestWrittenOff(this.repaymentScheduleInstallments, currency) + .getAmount(); + + if (totalInterestCharged.isGreaterThanZero()) { + this.totalInterestOutstanding = totalInterestCharged.minus(this.totalInterestRepaid).minus(this.totalInterestWaived) + .minus(this.totalInterestWrittenOff).getAmount(); + this.totalInterestOverdue = summary.calculateTotalInterestOverdueOn(this.repaymentScheduleInstallments, currency, + DateUtils.getLocalDateOfTenant()).getAmount(); + } + + final Money totalFeeChargesCharged = summary.calculateTotalFeeChargesCharged(this.repaymentScheduleInstallments, currency); + this.totalFeeChargesCharged = totalFeeChargesCharged.getAmount(); + this.totalFeeChargesRepaid = summary.calculateTotalFeeChargesRepaid(this.repaymentScheduleInstallments, currency).getAmount(); + this.totalFeeChargesWaived = summary.calculateTotalFeeChargesWaived(this.repaymentScheduleInstallments, currency).getAmount(); + this.totalFeeChargesWrittenOff = summary.calculateTotalFeeChargesWrittenOff(this.repaymentScheduleInstallments, currency) + .getAmount(); + + if (totalFeeChargesCharged.isGreaterThanZero()) { + this.totalFeeChargesOutstanding = totalFeeChargesCharged.minus(this.totalFeeChargesRepaid) + .minus(this.totalFeeChargesWaived).minus(this.totalFeeChargesWrittenOff).getAmount(); + this.totalFeeChargesOverdue = summary.calculateTotalFeeChargesOverdueOn(this.repaymentScheduleInstallments, currency, + DateUtils.getLocalDateOfTenant()).getAmount(); + } + + final Money totalPenaltyChargesCharged = summary.calculateTotalPenaltyChargesCharged(this.repaymentScheduleInstallments, + currency); + this.totalPenaltyChargesCharged = totalPenaltyChargesCharged.getAmount(); + this.totalPenaltyChargesRepaid = summary.calculateTotalPenaltyChargesRepaid(this.repaymentScheduleInstallments, currency) + .getAmount(); + this.totalPenaltyChargesWaived = summary.calculateTotalPenaltyChargesWaived(this.repaymentScheduleInstallments, currency) + .getAmount(); + this.totalPenaltyChargesWrittenOff = summary.calculateTotalPenaltyChargesWrittenOff(this.repaymentScheduleInstallments, + currency).getAmount(); + + if (totalPenaltyChargesCharged.isGreaterThanZero()) { + this.totalPenaltyChargesOutstanding = totalPenaltyChargesCharged.minus(this.totalPenaltyChargesRepaid) + .minus(this.totalPenaltyChargesWaived).minus(this.totalPenaltyChargesWrittenOff).getAmount(); + this.totalPenaltyChargesOverdue = summary.calculateTotalPenaltyChargesOverdueOn(this.repaymentScheduleInstallments, + currency, DateUtils.getLocalDateOfTenant()).getAmount(); + } + + final Money totalExpectedRepayment = Money.of(currency, this.totalPrincipalDisbursed).plus(this.totalInterestCharged) + .plus(this.totalFeeChargesCharged).plus(this.totalPenaltyChargesCharged); + this.totalExpectedRepayment = totalExpectedRepayment.getAmount(); + + final Money totalRepayment = Money.of(currency, this.totalPrincipalRepaid).plus(this.totalInterestRepaid) + .plus(this.totalFeeChargesRepaid).plus(this.totalPenaltyChargesRepaid); + this.totalRepayment = totalRepayment.getAmount(); + + final Money totalExpectedCostOfLoan = Money.of(currency, this.totalInterestCharged).plus(this.totalFeeChargesCharged) + .plus(this.totalPenaltyChargesCharged); + this.totalExpectedCostOfLoan = totalExpectedCostOfLoan.getAmount(); + + final Money totalCostOfLoan = Money.of(currency, this.totalInterestRepaid).plus(this.totalFeeChargesRepaid) + .plus(this.totalPenaltyChargesRepaid); + this.totalCostOfLoan = totalCostOfLoan.getAmount(); + + final Money totalWaived = Money.of(currency, this.totalInterestWaived).plus(this.totalFeeChargesWaived) + .plus(this.totalPenaltyChargesWaived); + this.totalWaived = totalWaived.getAmount(); + + final Money totalWrittenOff = Money.of(currency, this.totalPrincipalWrittenOff).plus(this.totalInterestWrittenOff) + .plus(this.totalFeeChargesWrittenOff).plus(this.totalPenaltyChargesWrittenOff); + this.totalWrittenOff = totalWrittenOff.getAmount(); + + final Money totalOutstanding = Money.of(currency, this.totalPrincipalOutstanding).plus(this.totalInterestOutstanding) + .plus(this.totalFeeChargesOutstanding).plus(this.totalPenaltyChargesOutstanding); + this.totalOutstanding = totalOutstanding.getAmount(); + + final Money totalOverdue = Money.of(currency, this.totalPrincipalOverdue).plus(this.totalInterestOverdue) + .plus(this.totalFeeChargesOverdue).plus(this.totalPenaltyChargesOverdue); + this.totalOverdue = totalOverdue.getAmount(); + + final LocalDate overdueSinceLocalDate = summary.determineOverdueSinceDateFrom(this.repaymentScheduleInstallments, currency, + DateUtils.getLocalDateOfTenant()); + if (overdueSinceLocalDate != null) { + this.overdueSinceDate = overdueSinceLocalDate.toDate(); + } else { + this.overdueSinceDate = null; + } + } + } + public Map loanApplicationModification(final JsonCommand command, final Set possiblyModifedLoanCharges, final Set possiblyModifedLoanCollateralItems, final AprCalculator aprCalculator) { @@ -1100,13 +1360,12 @@ public class Loan extends AbstractAuditableCustom { return ids; } - public Map disburse(final AppUser currentUser, final JsonCommand command, - final LoanLifecycleStateMachine loanLifecycleStateMachine, final ApplicationCurrency currency, + public Map disburse(final AppUser currentUser, final JsonCommand command, final ApplicationCurrency currency, final List existingTransactionIds, final List existingReversedTransactionIds) { final Map actualChanges = new LinkedHashMap(); - updateLoanToPreDisbursalState(); + updateLoanToPreDisbursalState(this.loanSummaryWrapper); final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, LoanStatus.fromInt(this.loanStatus)); if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { @@ -1131,6 +1390,8 @@ public class Loan extends AbstractAuditableCustom { if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate)) { regenerateRepaymentSchedule(currency); + } else { + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } } @@ -1164,8 +1425,8 @@ public class Loan extends AbstractAuditableCustom { final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod, interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency, - loanTermPeriodFrequencyType, setOfLoanCharges(), this.getDisbursementDate(), - this.getExpectedFirstRepaymentOnDate(), this.getInterestChargedFromDate(), inArrearsTolerance); + loanTermPeriodFrequencyType, setOfLoanCharges(), this.getDisbursementDate(), this.getExpectedFirstRepaymentOnDate(), + this.getInterestChargedFromDate(), inArrearsTolerance); final LoanScheduleData generatedData = loanSchedule.generate(); @@ -1219,13 +1480,12 @@ public class Loan extends AbstractAuditableCustom { return disbursementTransaction; } - public Map undoDisbursal(final LoanLifecycleStateMachine loanLifecycleStateMachine, - final List existingTransactionIds, final List existingReversedTransactionIds) { + public Map undoDisbursal(final List existingTransactionIds, final List existingReversedTransactionIds) { final Map actualChanges = new LinkedHashMap(); final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus); - final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, currentStatus); + final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, currentStatus); if (!statusEnum.hasStateOf(currentStatus)) { this.loanStatus = statusEnum.getValue(); actualChanges.put("status", LoanEnumerations.status(this.loanStatus)); @@ -1239,7 +1499,7 @@ public class Loan extends AbstractAuditableCustom { reverseExistingTransactions(); - updateLoanToPreDisbursalState(); + updateLoanToPreDisbursalState(this.loanSummaryWrapper); } return actualChanges; @@ -1252,7 +1512,7 @@ public class Loan extends AbstractAuditableCustom { } } - private void updateLoanToPreDisbursalState() { + private void updateLoanToPreDisbursalState(final LoanSummaryWrapper summaryWrapper) { this.actualDisbursementDate = null; for (LoanCharge charge : setOfLoanCharges()) { @@ -1263,8 +1523,10 @@ public class Loan extends AbstractAuditableCustom { currentInstallment.resetDerivedComponents(); } - LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); + LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges()); + + updateLoanSummaryDerivedFields(summaryWrapper); } public LoanTransaction waiveInterest(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) { @@ -1340,7 +1602,7 @@ public class Loan extends AbstractAuditableCustom { } } - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (isTransactionChronologicallyLatest && adjustedTransaction == null) { loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments, @@ -1351,6 +1613,8 @@ public class Loan extends AbstractAuditableCustom { getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges()); } + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); + doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine); } @@ -1529,31 +1793,7 @@ public class Loan extends AbstractAuditableCustom { } private boolean isRepaidInFull() { - - MonetaryCurrency currency = loanCurrency(); - - Money cumulativeOriginalPrincipalExpected = Money.zero(currency); - Money cumulativeOriginalInterestExpected = Money.zero(currency); - Money cumulativeOriginalTotalExpected = Money.zero(currency); - - Money cumulativeTotalPaid = Money.zero(currency); - Money cumulativeTotalWaived = Money.zero(currency); - - for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) { - cumulativeOriginalPrincipalExpected = cumulativeOriginalPrincipalExpected.plus(scheduledRepayment.getPrincipal(currency)); - cumulativeOriginalInterestExpected = cumulativeOriginalInterestExpected.plus(scheduledRepayment.getInterest(currency)); - - cumulativeTotalPaid = cumulativeTotalPaid.plus(scheduledRepayment.getPrincipalCompleted(currency).plus( - scheduledRepayment.getInterestCompleted(currency))); - cumulativeTotalWaived = cumulativeTotalWaived.plus(scheduledRepayment.getInterestWaived(currency)); - } - - cumulativeOriginalTotalExpected = cumulativeOriginalPrincipalExpected.plus(cumulativeOriginalInterestExpected); - - Money totalOutstanding = cumulativeOriginalTotalExpected.minus(cumulativeTotalPaid.plus(cumulativeTotalWaived)); - boolean isRepaidInFull = totalOutstanding.isZero(); - - return isRepaidInFull; + return Money.of(loanCurrency(), this.totalOutstanding).isZero(); } private boolean isOverPaid() { @@ -1571,9 +1811,8 @@ public class Loan extends AbstractAuditableCustom { for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) { cumulativeTotalPaidOnInstallments = cumulativeTotalPaidOnInstallments - .plus(scheduledRepayment.getPrincipalCompleted(currency).plus(scheduledRepayment.getInterestCompleted(currency))) - .plus(scheduledRepayment.getFeeChargesCompleted(currency)) - .plus(scheduledRepayment.getPenaltyChargesCompleted(currency)); + .plus(scheduledRepayment.getPrincipalCompleted(currency).plus(scheduledRepayment.getInterestPaid(currency))) + .plus(scheduledRepayment.getFeeChargesPaid(currency)).plus(scheduledRepayment.getPenaltyChargesPaid(currency)); cumulativeTotalWaivedOnInstallments = cumulativeTotalWaivedOnInstallments.plus(scheduledRepayment.getInterestWaived(currency)); } @@ -1630,9 +1869,11 @@ public class Loan extends AbstractAuditableCustom { this.loanTransactions.add(loanTransaction); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, loanCurrency(), this.repaymentScheduleInstallments); + + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } return loanTransaction; @@ -1663,11 +1904,15 @@ public class Loan extends AbstractAuditableCustom { LoanTransaction loanTransaction = null; if (isOpen()) { - // 1. check total outstanding - final Money outstanding = getTotalOutstanding(); + final Money outstanding = Money.of(loanCurrency(), this.totalOutstanding); if (outstanding.isGreaterThanZero() && getInArrearsTolerance().isGreaterThanOrEqualTo(outstanding)) { - updateLoanForClosure(closureDate, loanLifecycleStateMachine, changes); + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, LoanStatus.fromInt(this.loanStatus)); + if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { + this.loanStatus = statusEnum.getValue(); + changes.put("status", LoanEnumerations.status(this.loanStatus)); + } + this.closedOnDate = closureDate.toDate(); loanTransaction = LoanTransaction.writeoff(this, closureDate); boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, loanTransactions); @@ -1679,11 +1924,12 @@ public class Loan extends AbstractAuditableCustom { this.loanTransactions.add(loanTransaction); - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); loanRepaymentScheduleTransactionProcessor.handleWriteOff(loanTransaction, loanCurrency(), this.repaymentScheduleInstallments); + updateLoanSummaryDerivedFields(this.loanSummaryWrapper); } else if (outstanding.isGreaterThanZero()) { final String errorMessage = "A loan with money outstanding cannot be closed"; throw new InvalidLoanStateTransitionException("close", "loan.has.money.outstanding", errorMessage, outstanding.toString()); @@ -1696,7 +1942,12 @@ public class Loan extends AbstractAuditableCustom { // TODO - KW - technically should set somewhere that this loan // has // 'overpaid' amount - updateLoanForClosure(closureDate, loanLifecycleStateMachine, changes); + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, LoanStatus.fromInt(this.loanStatus)); + if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { + this.loanStatus = statusEnum.getValue(); + changes.put("status", LoanEnumerations.status(this.loanStatus)); + } + this.closedOnDate = closureDate.toDate(); } else if (totalLoanOverpayment.isGreaterThanZero()) { final String errorMessage = "The loan is marked as 'Overpaid' and cannot be moved to 'Closed (obligations met)."; throw new InvalidLoanStateTransitionException("close", "loan.is.overpaid", errorMessage, totalLoanOverpayment.toString()); @@ -1706,26 +1957,6 @@ public class Loan extends AbstractAuditableCustom { return loanTransaction; } - private Money getTotalOutstanding() { - Money totalOutstanding = Money.zero(loanCurrency()); - - final LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); - totalOutstanding = wrapper.calculateTotalOutstanding(loanCurrency(), this.repaymentScheduleInstallments); - - return totalOutstanding; - } - - private void updateLoanForClosure(final LocalDate closureDate, final LoanLifecycleStateMachine loanLifecycleStateMachine, - final Map changes) { - - final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, LoanStatus.fromInt(this.loanStatus)); - if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { - this.loanStatus = statusEnum.getValue(); - changes.put("status", LoanEnumerations.status(this.loanStatus)); - } - this.closedOnDate = closureDate.toDate(); - } - /** * Behaviour added to comply with capability of previous mifos product to * support easier transition to mifosx platform. @@ -1773,73 +2004,34 @@ public class Loan extends AbstractAuditableCustom { return status().isSubmittedAndPendingApproval(); } - public boolean isApproved() { - return status().isApproved(); - } - - public boolean isNotApproved() { - return !isApproved(); - } - - public boolean isWaitingForDisbursal() { - return this.isApproved() && this.isNotDisbursed(); - } - - public boolean isNotDisbursed() { + private boolean isNotDisbursed() { return !this.isDisbursed(); } - public boolean isDisbursed() { + private boolean isDisbursed() { return hasDisbursementTransaction(); } - public boolean isUndoDisbursalAllowed() { - return isDisbursed() && this.hasNoRepaymentTransaction(); - } - - public boolean isClosed() { + private boolean isClosed() { return status().isClosed() || this.isCancelled(); } - public boolean isCancelled() { + private boolean isCancelled() { return this.isRejected() || this.isWithdrawn(); } - public boolean isWithdrawn() { + private boolean isWithdrawn() { return status().isWithdrawnByClient(); } - public boolean isRejected() { + private boolean isRejected() { return status().isRejected(); } - public boolean isNotClosed() { - return !this.isClosed(); - } - - public boolean isOpen() { + private boolean isOpen() { return status().isActive(); } - public boolean isOpenWithNoRepaymentMade() { - return this.isOpen() && hasNoRepaymentTransaction(); - } - - private boolean hasNoRepaymentTransaction() { - return !hasRepaymentTransaction(); - } - - private boolean hasRepaymentTransaction() { - boolean hasRepaymentTransaction = false; - for (LoanTransaction loanTransaction : this.loanTransactions) { - if (loanTransaction.isRepayment()) { - hasRepaymentTransaction = true; - break; - } - } - return hasRepaymentTransaction; - } - private boolean hasDisbursementTransaction() { boolean hasRepaymentTransaction = false; for (LoanTransaction loanTransaction : this.loanTransactions) { @@ -1851,35 +2043,11 @@ public class Loan extends AbstractAuditableCustom { return hasRepaymentTransaction; } - public boolean isOpenWithRepaymentMade() { - return this.isOpen() && this.hasRepaymentTransaction(); - } - - public List getRepaymentScheduleInstallments() { - return this.repaymentScheduleInstallments; - } - - public String getExternalId() { - return this.externalId; - } - - public void setExternalId(final String externalSystemIdentifer) { - if (StringUtils.isNotBlank(externalSystemIdentifer)) { - this.externalId = externalSystemIdentifer.trim(); - } else { - this.externalId = null; - } - } - - public LocalDate getSubmittedOnDate() { + private LocalDate getSubmittedOnDate() { return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.submittedOnDate), null); } - public LocalDate getRejectedOnDate() { - return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.rejectedOnDate), null); - } - - public LocalDate getApprovedOnDate() { + private LocalDate getApprovedOnDate() { LocalDate date = null; if (this.approvedOnDate != null) { date = new LocalDate(this.approvedOnDate); @@ -1887,35 +2055,7 @@ public class Loan extends AbstractAuditableCustom { return date; } - public LocalDate getDisbursedOnDate() { - LocalDate date = null; - if (this.actualDisbursementDate != null) { - date = new LocalDate(this.actualDisbursementDate); - } - return date; - } - - public LocalDate getClosedOnDate() { - LocalDate date = null; - if (this.closedOnDate != null) { - date = new LocalDate(this.closedOnDate); - } - return date; - } - - public LocalDate getWrittenOffOnDate() { - LocalDate date = null; - if (this.writtenOffOnDate != null) { - date = new LocalDate(this.writtenOffOnDate); - } - return date; - } - - public Date getExpectedDisbursedOnDate() { - return this.expectedDisbursementDate; - } - - public LocalDate getExpectedDisbursedOnLocalDate() { + private LocalDate getExpectedDisbursedOnLocalDate() { LocalDate expectedDisbursementDate = null; if (this.expectedDisbursementDate != null) { expectedDisbursementDate = new LocalDate(this.expectedDisbursementDate); @@ -1923,15 +2063,7 @@ public class Loan extends AbstractAuditableCustom { return expectedDisbursementDate; } - public LocalDate getExpectedFirstRepaymentOnDate() { - LocalDate firstRepaymentDate = null; - if (this.expectedFirstRepaymentOnDate != null) { - firstRepaymentDate = new LocalDate(this.expectedFirstRepaymentOnDate); - } - return firstRepaymentDate; - } - - public LocalDate getDisbursementDate() { + private LocalDate getDisbursementDate() { LocalDate disbursementDate = getExpectedDisbursedOnLocalDate(); if (this.actualDisbursementDate != null) { disbursementDate = new LocalDate(this.actualDisbursementDate); @@ -1939,52 +2071,24 @@ public class Loan extends AbstractAuditableCustom { return disbursementDate; } - public LocalDate getExpectedMaturityDate() { - LocalDate possibleMaturityDate = null; - if (this.expectedMaturityDate != null) { - possibleMaturityDate = new LocalDate(this.expectedMaturityDate); + private LocalDate getExpectedFirstRepaymentOnDate() { + LocalDate firstRepaymentDate = null; + if (this.expectedFirstRepaymentOnDate != null) { + firstRepaymentDate = new LocalDate(this.expectedFirstRepaymentOnDate); } - return possibleMaturityDate; + return firstRepaymentDate; } - public LocalDate getActualMaturityDate() { - LocalDate possibleMaturityDate = null; - if (this.actualMaturityDate != null) { - possibleMaturityDate = new LocalDate(this.actualMaturityDate); - } - return possibleMaturityDate; - } - - public LocalDate getMaturityDate() { - LocalDate possibleMaturityDate = null; - - if (this.expectedMaturityDate != null) { - possibleMaturityDate = new LocalDate(this.expectedMaturityDate); - } - if (this.actualMaturityDate != null) { - possibleMaturityDate = new LocalDate(this.actualMaturityDate); - } - return possibleMaturityDate; - } - - public Set getCharges() { - return charges; - } - - public void setCharges(final Set charges) { - this.charges = charges; - } - - public void addRepaymentScheduleInstallment(final LoanRepaymentScheduleInstallment installment) { + private void addRepaymentScheduleInstallment(final LoanRepaymentScheduleInstallment installment) { installment.updateLoan(this); this.repaymentScheduleInstallments.add(installment); } - public boolean isActualDisbursedOnDateEarlierOrLaterThanExpected(final LocalDate actualDisbursedOnDate) { + private boolean isActualDisbursedOnDateEarlierOrLaterThanExpected(final LocalDate actualDisbursedOnDate) { return !new LocalDate(this.expectedDisbursementDate).isEqual(actualDisbursedOnDate); } - public boolean isRepaymentScheduleRegenerationRequiredForDisbursement(final LocalDate actualDisbursementDate) { + private boolean isRepaymentScheduleRegenerationRequiredForDisbursement(final LocalDate actualDisbursementDate) { return isActualDisbursedOnDateEarlierOrLaterThanExpected(actualDisbursementDate); } @@ -2029,10 +2133,6 @@ public class Loan extends AbstractAuditableCustom { return this.loanRepaymentScheduleDetail.getInArrearsTolerance(); } - public boolean identifiedBy(final String identifier) { - return identifier.equalsIgnoreCase(this.externalId) || identifier.equalsIgnoreCase(this.getId().toString()); - } - public boolean hasIdentifyOf(final Long loanId) { return loanId.equals(this.getId()); } @@ -2049,7 +2149,7 @@ public class Loan extends AbstractAuditableCustom { return matchesCurrentLoanOfficer; } - public LocalDate getInterestChargedFromDate() { + private LocalDate getInterestChargedFromDate() { LocalDate interestChargedFrom = null; if (this.interestChargedFromDate != null) { interestChargedFrom = new LocalDate(this.interestChargedFromDate); @@ -2057,29 +2157,11 @@ public class Loan extends AbstractAuditableCustom { return interestChargedFrom; } - public LocalDate getLoanStatusSinceDate() { - - LocalDate statusSinceDate = getSubmittedOnDate(); - if (isApproved()) { - statusSinceDate = new LocalDate(this.approvedOnDate); - } - - if (isDisbursed()) { - statusSinceDate = new LocalDate(this.actualDisbursementDate); - } - - if (isClosed()) { - statusSinceDate = new LocalDate(this.closedOnDate); - } - - return statusSinceDate; - } - public Money getPrincpal() { return this.loanRepaymentScheduleDetail.getPrincipal(); } - public Money getTotalChargesDueAtDisbursement() { + private Money getTotalChargesDueAtDisbursement() { return Money.of(getCurrency(), this.totalChargesDueAtDisbursement); } @@ -2155,10 +2237,6 @@ public class Loan extends AbstractAuditableCustom { return latestRecordWithNoEndDate; } - public Client getClient() { - return client; - } - public Long getClientId() { Long clientId = null; if (this.client != null) { @@ -2223,4 +2301,11 @@ public class Loan extends AbstractAuditableCustom { accountingBridgeData.put("newLoanTransactions", newLoanTransactions); return accountingBridgeData; } + + public void setHelpers(final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanSummaryWrapper loanSummaryWrapper, + final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory) { + this.loanLifecycleStateMachine = loanLifecycleStateMachine; + this.loanSummaryWrapper = loanSummaryWrapper; + this.transactionProcessorFactory = transactionProcessorFactory; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java index b6f2555fa..9ab626877 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java @@ -51,10 +51,10 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus private BigDecimal principalWrittenOff; @Column(name = "interest_amount", scale = 6, precision = 19, nullable = true) - private BigDecimal interest; + private BigDecimal interestCharged; @Column(name = "interest_completed_derived", scale = 6, precision = 19, nullable = true) - private BigDecimal interestCompleted; + private BigDecimal interestPaid; @Column(name = "interest_waived_derived", scale = 6, precision = 19, nullable = true) private BigDecimal interestWaived; @@ -63,10 +63,10 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus private BigDecimal interestWrittenOff; @Column(name = "fee_charges_amount", scale = 6, precision = 19, nullable = true) - private BigDecimal feeCharges; + private BigDecimal feeChargesCharged; @Column(name = "fee_charges_completed_derived", scale = 6, precision = 19, nullable = true) - private BigDecimal feeChargesCompleted; + private BigDecimal feeChargesPaid; @Column(name = "fee_charges_writtenoff_derived", scale = 6, precision = 19, nullable = true) private BigDecimal feeChargesWrittenOff; @@ -78,7 +78,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus private BigDecimal penaltyCharges; @Column(name = "penalty_charges_completed_derived", scale = 6, precision = 19, nullable = true) - private BigDecimal penaltyChargesCompleted; + private BigDecimal penaltyChargesPaid; @Column(name = "penalty_charges_writtenoff_derived", scale = 6, precision = 19, nullable = true) private BigDecimal penaltyChargesWrittenOff; @@ -104,8 +104,8 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus this.fromDate = fromDate.toDateMidnight().toDate(); this.dueDate = dueDate.toDateMidnight().toDate(); this.principal = defaultToNullIfZero(principal); - this.interest = defaultToNullIfZero(interest); - this.feeCharges = defaultToNullIfZero(feeCharges); + this.interestCharged = defaultToNullIfZero(interest); + this.feeChargesCharged = defaultToNullIfZero(feeCharges); this.penaltyCharges = defaultToNullIfZero(penaltyCharges); this.completed = false; } @@ -156,12 +156,12 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus return getPrincipal(currency).minus(principalAccountedFor); } - public Money getInterest(final MonetaryCurrency currency) { - return Money.of(currency, this.interest); + public Money getInterestCharged(final MonetaryCurrency currency) { + return Money.of(currency, this.interestCharged); } - public Money getInterestCompleted(final MonetaryCurrency currency) { - return Money.of(currency, this.interestCompleted); + public Money getInterestPaid(final MonetaryCurrency currency) { + return Money.of(currency, this.interestPaid); } public Money getInterestWaived(final MonetaryCurrency currency) { @@ -173,17 +173,17 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus } public Money getInterestOutstanding(final MonetaryCurrency currency) { - final Money interestAccountedFor = getInterestCompleted(currency).plus(getInterestWaived(currency)).plus( + final Money interestAccountedFor = getInterestPaid(currency).plus(getInterestWaived(currency)).plus( getInterestWrittenOff(currency)); - return getInterest(currency).minus(interestAccountedFor); + return getInterestCharged(currency).minus(interestAccountedFor); } - public Money getFeeCharges(final MonetaryCurrency currency) { - return Money.of(currency, this.feeCharges); + public Money getFeeChargesCharged(final MonetaryCurrency currency) { + return Money.of(currency, this.feeChargesCharged); } - public Money getFeeChargesCompleted(final MonetaryCurrency currency) { - return Money.of(currency, this.feeChargesCompleted); + public Money getFeeChargesPaid(final MonetaryCurrency currency) { + return Money.of(currency, this.feeChargesPaid); } public Money getFeeChargesWaived(final MonetaryCurrency currency) { @@ -195,17 +195,17 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus } public Money getFeeChargesOutstanding(final MonetaryCurrency currency) { - final Money feeChargesAccountedFor = getFeeChargesCompleted(currency).plus(getFeeChargesWaived(currency)).plus( + final Money feeChargesAccountedFor = getFeeChargesPaid(currency).plus(getFeeChargesWaived(currency)).plus( getFeeChargesWrittenOff(currency)); - return getFeeCharges(currency).minus(feeChargesAccountedFor); + return getFeeChargesCharged(currency).minus(feeChargesAccountedFor); } - public Money getPenaltyCharges(final MonetaryCurrency currency) { + public Money getPenaltyChargesCharged(final MonetaryCurrency currency) { return Money.of(currency, this.penaltyCharges); } - public Money getPenaltyChargesCompleted(final MonetaryCurrency currency) { - return Money.of(currency, this.penaltyChargesCompleted); + public Money getPenaltyChargesPaid(final MonetaryCurrency currency) { + return Money.of(currency, this.penaltyChargesPaid); } public Money getPenaltyChargesWaived(final MonetaryCurrency currency) { @@ -217,9 +217,9 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus } public Money getPenaltyChargesOutstanding(final MonetaryCurrency currency) { - final Money feeChargesAccountedFor = getPenaltyChargesCompleted(currency).plus(getPenaltyChargesWaived(currency)).plus( + final Money feeChargesAccountedFor = getPenaltyChargesPaid(currency).plus(getPenaltyChargesWaived(currency)).plus( getPenaltyChargesWrittenOff(currency)); - return getPenaltyCharges(currency).minus(feeChargesAccountedFor); + return getPenaltyChargesCharged(currency).minus(feeChargesAccountedFor); } public boolean isInterestDue(final MonetaryCurrency currency) { @@ -227,7 +227,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus } public Money getTotalPrincipalAndInterest(final MonetaryCurrency currency) { - return getPrincipal(currency).plus(getInterest(currency)); + return getPrincipal(currency).plus(getInterestCharged(currency)); } public Money getTotalOutstanding(final MonetaryCurrency currency) { @@ -258,13 +258,13 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus public void resetDerivedComponents() { this.principalCompleted = null; this.principalWrittenOff = null; - this.interestCompleted = null; + this.interestPaid = null; this.interestWaived = null; this.interestWrittenOff = null; - this.feeChargesCompleted = null; + this.feeChargesPaid = null; this.feeChargesWaived = null; this.feeChargesWrittenOff = null; - this.penaltyChargesCompleted = null; + this.penaltyChargesPaid = null; this.penaltyChargesWaived = null; this.penaltyChargesWrittenOff = null; @@ -278,14 +278,14 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus final Money penaltyChargesDue = getPenaltyChargesOutstanding(currency); if (transactionAmountRemaining.isGreaterThanOrEqualTo(penaltyChargesDue)) { - this.penaltyChargesCompleted = getPenaltyChargesCompleted(currency).plus(penaltyChargesDue).getAmount(); + this.penaltyChargesPaid = getPenaltyChargesPaid(currency).plus(penaltyChargesDue).getAmount(); penaltyPortionOfTransaction = penaltyPortionOfTransaction.plus(penaltyChargesDue); } else { - this.penaltyChargesCompleted = getPenaltyChargesCompleted(currency).plus(transactionAmountRemaining).getAmount(); + this.penaltyChargesPaid = getPenaltyChargesPaid(currency).plus(transactionAmountRemaining).getAmount(); penaltyPortionOfTransaction = penaltyPortionOfTransaction.plus(transactionAmountRemaining); } - this.penaltyChargesCompleted = defaultToNullIfZero(this.penaltyChargesCompleted); + this.penaltyChargesPaid = defaultToNullIfZero(this.penaltyChargesPaid); this.completed = getTotalOutstanding(currency).isZero(); @@ -299,14 +299,14 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus final Money feeChargesDue = getFeeChargesOutstanding(currency); if (transactionAmountRemaining.isGreaterThanOrEqualTo(feeChargesDue)) { - this.feeChargesCompleted = getFeeChargesCompleted(currency).plus(feeChargesDue).getAmount(); + this.feeChargesPaid = getFeeChargesPaid(currency).plus(feeChargesDue).getAmount(); feePortionOfTransaction = feePortionOfTransaction.plus(feeChargesDue); } else { - this.feeChargesCompleted = getFeeChargesCompleted(currency).plus(transactionAmountRemaining).getAmount(); + this.feeChargesPaid = getFeeChargesPaid(currency).plus(transactionAmountRemaining).getAmount(); feePortionOfTransaction = feePortionOfTransaction.plus(transactionAmountRemaining); } - this.feeChargesCompleted = defaultToNullIfZero(this.feeChargesCompleted); + this.feeChargesPaid = defaultToNullIfZero(this.feeChargesPaid); this.completed = getTotalOutstanding(currency).isZero(); @@ -320,14 +320,14 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus final Money interestDue = getInterestOutstanding(currency); if (transactionAmountRemaining.isGreaterThanOrEqualTo(interestDue)) { - this.interestCompleted = getInterestCompleted(currency).plus(interestDue).getAmount(); + this.interestPaid = getInterestPaid(currency).plus(interestDue).getAmount(); interestPortionOfTransaction = interestPortionOfTransaction.plus(interestDue); } else { - this.interestCompleted = getInterestCompleted(currency).plus(transactionAmountRemaining).getAmount(); + this.interestPaid = getInterestPaid(currency).plus(transactionAmountRemaining).getAmount(); interestPortionOfTransaction = interestPortionOfTransaction.plus(transactionAmountRemaining); } - this.interestCompleted = defaultToNullIfZero(this.interestCompleted); + this.interestPaid = defaultToNullIfZero(this.interestPaid); this.completed = getTotalOutstanding(currency).isZero(); @@ -455,7 +455,7 @@ public final class LoanRepaymentScheduleInstallment extends AbstractAuditableCus public void updateChargePortion(final Money feeChargesDue, final Money feeChargesWaived, final Money feeChargesWrittenOff, final Money penaltyChargesDue, final Money penaltyChargesWaived, final Money penaltyChargesWrittenOff) { - this.feeCharges = defaultToNullIfZero(feeChargesDue.getAmount()); + this.feeChargesCharged = defaultToNullIfZero(feeChargesDue.getAmount()); this.feeChargesWaived = defaultToNullIfZero(feeChargesWaived.getAmount()); this.feeChargesWrittenOff = defaultToNullIfZero(feeChargesWrittenOff.getAmount()); this.penaltyCharges = defaultToNullIfZero(penaltyChargesDue.getAmount()); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanScheduleWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java similarity index 88% rename from mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanScheduleWrapper.java rename to mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java index 3a567a0ae..c83f1d63e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanScheduleWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleProcessingWrapper.java @@ -15,27 +15,9 @@ import org.mifosplatform.organisation.monetary.domain.Money; /** * A wrapper around loan schedule related data exposing needed behaviour by * loan. - * - * This wrapper should be side-effect free. It should not attempt to change - * state of loan parts passed through to it. */ -public class LoanScheduleWrapper { +public class LoanRepaymentScheduleProcessingWrapper { - public Money calculateTotalOutstanding(final MonetaryCurrency currency, final List installments) { - - Money cumulativeValue = Money.zero(currency); - - for (LoanRepaymentScheduleInstallment scheduledRepayment : installments) { - cumulativeValue = cumulativeValue.plus(scheduledRepayment.getTotalOutstanding(currency)); - } - - return cumulativeValue; - } - - /** - * FIXME - KW - this is not a side effect free approach so move this into a - * specific wrapper than makes this obvious from the read-only wrapper. - */ public void reprocess(final MonetaryCurrency currency, final LocalDate disbursementDate, final List repaymentPeriods, final Set loanCharges) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleTransactionProcessorFactory.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleTransactionProcessorFactory.java index 39814486c..4abd71eb5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleTransactionProcessorFactory.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanRepaymentScheduleTransactionProcessorFactory.java @@ -6,36 +6,35 @@ package org.mifosplatform.portfolio.loanaccount.domain; import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy; +import org.springframework.stereotype.Component; - -/** - * - */ +@Component public class LoanRepaymentScheduleTransactionProcessorFactory { - public LoanRepaymentScheduleTransactionProcessor determineProcessor(final LoanTransactionProcessingStrategy transactionProcessingStrategy) { + public LoanRepaymentScheduleTransactionProcessor determineProcessor( + final LoanTransactionProcessingStrategy transactionProcessingStrategy) { - LoanRepaymentScheduleTransactionProcessor processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); - - if (transactionProcessingStrategy != null) { - - if (transactionProcessingStrategy.isStandardMifosStrategy()) { - processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); - } - - if (transactionProcessingStrategy.isHeavensfamilyStrategy()) { - processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); - } - - if (transactionProcessingStrategy.isCreocoreStrategy()) { - processor = new CreocoreLoanRepaymentScheduleTransactionProcessor(); - } - - if (transactionProcessingStrategy.isIndianRBIStrategy()) { - processor = new RBILoanRepaymentScheduleTransactionProcessor(); - } - } - - return processor; - } + LoanRepaymentScheduleTransactionProcessor processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); + + if (transactionProcessingStrategy != null) { + + if (transactionProcessingStrategy.isStandardMifosStrategy()) { + processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); + } + + if (transactionProcessingStrategy.isHeavensfamilyStrategy()) { + processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); + } + + if (transactionProcessingStrategy.isCreocoreStrategy()) { + processor = new CreocoreLoanRepaymentScheduleTransactionProcessor(); + } + + if (transactionProcessingStrategy.isIndianRBIStrategy()) { + processor = new RBILoanRepaymentScheduleTransactionProcessor(); + } + } + + return processor; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummaryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummaryWrapper.java new file mode 100644 index 000000000..dc8ed57d2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummaryWrapper.java @@ -0,0 +1,215 @@ +package org.mifosplatform.portfolio.loanaccount.domain; + +import java.util.List; + +import org.joda.time.LocalDate; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.organisation.monetary.domain.Money; +import org.springframework.stereotype.Component; + +/** + * A wrapper for dealing with side-effect free functionality related to a loans + * transactions and repayment schedule. + */ +@Component +public final class LoanSummaryWrapper { + + public Money calculateTotalPrincipalRepaid(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPrincipalCompleted(currency)); + } + return total; + } + + public Money calculateTotalPrincipalWrittenOff(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPrincipalWrittenOff(currency)); + } + return total; + } + + public Money calculateTotalPrincipalOverdueOn(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate overdueAsOf) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + if (installment.isOverdueOn(overdueAsOf)) { + total = total.plus(installment.getPrincipalOutstanding(currency)); + } + } + return total; + } + + public Money calculateTotalInterestCharged(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getInterestCharged(currency)); + } + return total; + } + + public Money calculateTotalInterestRepaid(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getInterestPaid(currency)); + } + return total; + } + + public Money calculateTotalInterestWaived(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getInterestWaived(currency)); + } + return total; + } + + public Money calculateTotalInterestWrittenOff(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getInterestWrittenOff(currency)); + } + return total; + } + + public Money calculateTotalInterestOverdueOn(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate overdueAsOf) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + if (installment.isOverdueOn(overdueAsOf)) { + total = total.plus(installment.getInterestOutstanding(currency)); + } + } + return total; + } + + public Money calculateTotalFeeChargesCharged(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getFeeChargesCharged(currency)); + } + return total; + } + + public Money calculateTotalFeeChargesRepaid(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getFeeChargesPaid(currency)); + } + return total; + } + + public Money calculateTotalFeeChargesWaived(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getFeeChargesWaived(currency)); + } + return total; + } + + public Money calculateTotalFeeChargesWrittenOff(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getFeeChargesWrittenOff(currency)); + } + return total; + } + + public Money calculateTotalFeeChargesOverdueOn(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate overdueAsOf) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + if (installment.isOverdueOn(overdueAsOf)) { + total = total.plus(installment.getFeeChargesOutstanding(currency)); + } + } + return total; + } + + public Money calculateTotalPenaltyChargesCharged(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPenaltyChargesCharged(currency)); + } + return total; + } + + public Money calculateTotalPenaltyChargesRepaid(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPenaltyChargesPaid(currency)); + } + return total; + } + + public Money calculateTotalPenaltyChargesWaived(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPenaltyChargesWaived(currency)); + } + return total; + } + + public Money calculateTotalPenaltyChargesWrittenOff(final List repaymentScheduleInstallments, + final MonetaryCurrency currency) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + total = total.plus(installment.getPenaltyChargesWrittenOff(currency)); + } + return total; + } + + public Money calculateTotalPenaltyChargesOverdueOn(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate overdueAsOf) { + Money total = Money.zero(currency); + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + if (installment.isOverdueOn(overdueAsOf)) { + total = total.plus(installment.getPenaltyChargesOutstanding(currency)); + } + } + return total; + } + + public Money calculateTotalOverdueOn(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate overdueAsOf) { + + final Money principalOverdue = calculateTotalPrincipalOverdueOn(repaymentScheduleInstallments, currency, overdueAsOf); + final Money interestOverdue = calculateTotalInterestOverdueOn(repaymentScheduleInstallments, currency, overdueAsOf); + final Money feeChargesOverdue = calculateTotalFeeChargesOverdueOn(repaymentScheduleInstallments, currency, overdueAsOf); + final Money penaltyChargesOverdue = calculateTotalPenaltyChargesOverdueOn(repaymentScheduleInstallments, currency, overdueAsOf); + + return principalOverdue.plus(interestOverdue).plus(feeChargesOverdue).plus(penaltyChargesOverdue); + } + + public LocalDate determineOverdueSinceDateFrom(final List repaymentScheduleInstallments, + final MonetaryCurrency currency, final LocalDate from) { + + LocalDate overdueSince = null; + final Money totalOverdue = calculateTotalOverdueOn(repaymentScheduleInstallments, currency, from); + if (totalOverdue.isGreaterThanZero()) { + for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { + if (installment.isOverdueOn(from)) { + if (overdueSince == null || overdueSince.isAfter(installment.getDueDate())) { + overdueSince = installment.getDueDate(); + } + } + } + } + + return overdueSince; + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanScheduleData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanScheduleData.java index f7dd740ef..aa8e6076f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanScheduleData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanScheduleData.java @@ -14,131 +14,32 @@ import org.mifosplatform.organisation.monetary.data.CurrencyData; * Immutable data object to represent aspects of a loan schedule such as: * *
    - *
  • summary information - the totals for each part of schedule monitored
  • - *
  • repayment schedule - the principal due, outstanding balance and cost of - * loan items such as interest and charges
  • + *
  • Totals information - the totals for each part of repayment schedule + * monitored.
  • + *
  • Repayment schedule - the principal due, outstanding balance and cost of + * loan items such as interest and charges (both fees and penalties)
  • *
*/ +@SuppressWarnings("unused") public class LoanScheduleData { - @SuppressWarnings("unused") - private final Integer loanTermInDays; - /** * The currency associated with all monetary values in loan schedule. */ - @SuppressWarnings("unused") private final CurrencyData currency; - - /** - * The cumulative total of all money (principal) disbursed to the loan - * applicant. - */ - @SuppressWarnings("unused") - private final BigDecimal cumulativePrincipalDisbursed; - - /** - * The cumulative total of all principalDue for each period of - * loan schedule. (originalPrincipal) - */ - @SuppressWarnings("unused") - private final BigDecimal cumulativePrincipalDue; - @SuppressWarnings("unused") - private final BigDecimal cumulativePrincipalPaid; - @SuppressWarnings("unused") - private final BigDecimal cumulativePrincipalWrittenOff; - @SuppressWarnings("unused") - private final BigDecimal cumulativePrincipalOutstanding; - - /** - * The cumulative total of interest expected on any principal disbursed. - * (originalInterest) - */ - @SuppressWarnings("unused") - private final BigDecimal cumulativeInterestExpected; - @SuppressWarnings("unused") - private final BigDecimal cumulativeInterestPaid; - @SuppressWarnings("unused") - private final BigDecimal cumulativeInterestWaived; - @SuppressWarnings("unused") - private final BigDecimal cumulativeInterestWrittenOff; - @SuppressWarnings("unused") - private final BigDecimal cumulativeInterestOutstanding; - - /** - * The cumulative total of all fee charges applied on the loan to date. - */ - @SuppressWarnings("unused") - private final BigDecimal cumulativeFeeChargesToDate; - @SuppressWarnings("unused") - private final BigDecimal cumulativeFeeChargesPaid; - @SuppressWarnings("unused") - private final BigDecimal cumulativeFeeChargesWaived; - @SuppressWarnings("unused") - private final BigDecimal cumulativeFeeChargesWrittenOff; - @SuppressWarnings("unused") - private final BigDecimal cumulativeFeeChargesOutstanding; - - @SuppressWarnings("unused") - private final BigDecimal cumulativePenaltyChargesToDate; - @SuppressWarnings("unused") - private final BigDecimal cumulativePenaltyChargesPaid; - @SuppressWarnings("unused") - private final BigDecimal cumulativePenaltyChargesWaived; - @SuppressWarnings("unused") - private final BigDecimal cumulativePenaltyChargesWrittenOff; - @SuppressWarnings("unused") - private final BigDecimal cumulativePenaltyChargesOutstanding; - - /** - * The cumulative total of all costs on the loan. Costs tracked are: - *
    - *
  • Interest
  • - *
  • Charges (fees and penalties)
  • - *
- */ - @SuppressWarnings("unused") - private final BigDecimal totalCostOfLoan; - - /** - * The sum of principalDisbursed and - * totalCostOfLoan. (originalTotal) - */ - @SuppressWarnings("unused") - private final BigDecimal totalExpectedRepayment; - - /** - * The cumulative sum of all repayments to date. (totalPaid) - */ - @SuppressWarnings("unused") - private final BigDecimal totalPaidToDate; - - /** - * The cumulative sum of all waivers to date. - */ - @SuppressWarnings("unused") - private final BigDecimal totalWaivedToDate; - - /** - * The cumulative sum of all waivers to date. - */ - @SuppressWarnings("unused") - private final BigDecimal totalWrittenOffToDate; - - /** - * The cumulative sum of all principal, interest & charges outstanding. - */ + private final Integer loanTermInDays; + private final BigDecimal totalPrincipalDisbursed; + private final BigDecimal totalPrincipalExpected; + private final BigDecimal totalPrincipalPaid; + private final BigDecimal totalInterestCharged; + private final BigDecimal totalFeeChargesCharged; + private final BigDecimal totalPenaltyChargesCharged; + private final BigDecimal totalWaived; + private final BigDecimal totalWrittenOff; + private final BigDecimal totalRepaymentExpected; + private final BigDecimal totalRepayment; private final BigDecimal totalOutstanding; - /** - * The amount by which this loan is is arrears. - * - * Different to outstanding as arrears is based on whether a portion of the - * total outstanding is late and above any tolerance setting. - */ - @SuppressWarnings("unused") - private final BigDecimal totalInArrears; - /** * periods is collection of data objects containing specific * information to each period of the loan schedule including disbursement @@ -146,148 +47,28 @@ public class LoanScheduleData { */ private final Collection periods; - public LoanScheduleData() { - this.cumulativePrincipalDisbursed = null; - this.cumulativePrincipalPaid = null; - this.cumulativePrincipalWrittenOff = null; - this.cumulativePrincipalDue = null; - this.cumulativePrincipalOutstanding = null; - - this.cumulativeInterestExpected = null; - this.cumulativeInterestPaid = null; - this.cumulativeInterestWaived = null; - this.cumulativeInterestWrittenOff = null; - this.cumulativeInterestOutstanding = null; - - this.cumulativeFeeChargesToDate = null; - this.cumulativeFeeChargesPaid = null; - this.cumulativeFeeChargesWaived = null; - this.cumulativeFeeChargesWrittenOff = null; - this.cumulativeFeeChargesOutstanding = null; - - this.cumulativePenaltyChargesToDate = null; - this.cumulativePenaltyChargesPaid = null; - this.cumulativePenaltyChargesWaived = null; - this.cumulativePenaltyChargesWrittenOff = null; - this.cumulativePenaltyChargesOutstanding = null; - - this.totalCostOfLoan = null; - - this.totalExpectedRepayment = null; - this.totalPaidToDate = null; - this.totalWaivedToDate = null; - this.totalWrittenOffToDate = null; - this.totalOutstanding = null; - this.totalInArrears = null; - - this.currency = null; - this.periods = null; - this.loanTermInDays = null; - } - public LoanScheduleData(final CurrencyData currency, final Collection periods, final Integer loanTermInDays, - final BigDecimal cumulativePrincipalDisbursed, final BigDecimal cumulativePrincipalDue, - final BigDecimal cumulativePrincipalOutstanding, final BigDecimal cumulativeInterestExpected, - final BigDecimal cumulativeFeeChargesToDate, final BigDecimal totalExpectedRepayment) { + final BigDecimal totalPrincipalDisbursed, final BigDecimal totalPrincipalExpected, final BigDecimal totalPrincipalPaid, + final BigDecimal totalInterestCharged, final BigDecimal totalFeeChargesCharged, final BigDecimal totalPenaltyChargesCharged, + final BigDecimal totalWaived, final BigDecimal totalWrittenOff, final BigDecimal totalRepaymentExpected, + final BigDecimal totalRepayment, final BigDecimal totalOutstanding) { this.currency = currency; this.periods = periods; this.loanTermInDays = loanTermInDays; - - this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed; - this.cumulativePrincipalDue = cumulativePrincipalDue; - this.cumulativePrincipalPaid = null; - this.cumulativePrincipalWrittenOff = null; - this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding; - - this.cumulativeInterestExpected = cumulativeInterestExpected; - this.cumulativeInterestPaid = null; - this.cumulativeInterestWaived = null; - this.cumulativeInterestWrittenOff = null; - this.cumulativeInterestOutstanding = null; - - this.cumulativeFeeChargesToDate = cumulativeFeeChargesToDate; - this.cumulativeFeeChargesPaid = null; - this.cumulativeFeeChargesWaived = null; - this.cumulativeFeeChargesWrittenOff = null; - this.cumulativeFeeChargesOutstanding = null; - - this.cumulativePenaltyChargesToDate = null; - this.cumulativePenaltyChargesPaid = null; - this.cumulativePenaltyChargesWaived = null; - this.cumulativePenaltyChargesWrittenOff = null; - this.cumulativePenaltyChargesOutstanding = null; - - if (cumulativeFeeChargesToDate != null) { - this.totalCostOfLoan = cumulativeInterestExpected.add(cumulativeFeeChargesToDate); - } else if (cumulativeInterestExpected != null) { - this.totalCostOfLoan = cumulativeInterestExpected; - } else { - this.totalCostOfLoan = null; - } - - this.totalExpectedRepayment = totalExpectedRepayment; - this.totalPaidToDate = BigDecimal.ZERO; - this.totalWaivedToDate = BigDecimal.ZERO; - this.totalWrittenOffToDate = BigDecimal.ZERO; - this.totalOutstanding = totalExpectedRepayment; - this.totalInArrears = BigDecimal.ZERO; - } - - /* - * Used when fully populating - */ - public LoanScheduleData(final CurrencyData currency, final Collection periods, final Integer loanTermInDays, - final BigDecimal cumulativePrincipalDisbursed, final BigDecimal cumulativePrincipalDue, - final BigDecimal cumulativePrincipalPaid, final BigDecimal cumulativePrincipalWrittenOff, - final BigDecimal cumulativePrincipalOutstanding, final BigDecimal cumulativeInterestExpected, - final BigDecimal cumulativeInterestPaid, final BigDecimal cumulativeInterestWaived, - final BigDecimal cumulativeInterestWrittenOff, final BigDecimal cumulativeInterestOutstanding, - final BigDecimal cumulativeFeeChargesToDate, final BigDecimal cumulativeFeeChargesPaid, - final BigDecimal cumulativeFeeChargesWaived, final BigDecimal cumulativeFeeChargesWrittenOff, - final BigDecimal cumulativeFeeChargesOutstanding, final BigDecimal cumulativePenaltyChargesToDate, - final BigDecimal cumulativePenaltyChargesPaid, final BigDecimal cumulativePenaltyChargesWaived, - final BigDecimal cumulativePenaltyChargesWrittenOff, final BigDecimal cumulativePenaltyChargesOutstanding, - final BigDecimal totalCostOfLoan, final BigDecimal totalExpectedRepayment, final BigDecimal totalPaidToDate, - final BigDecimal totalWaivedToDate, final BigDecimal totalWrittenOffToDate, final BigDecimal totalOutstanding, - final BigDecimal totalInArrears) { - this.currency = currency; - this.periods = periods; - this.loanTermInDays = loanTermInDays; - - this.cumulativePrincipalDisbursed = cumulativePrincipalDisbursed; - this.cumulativePrincipalDue = cumulativePrincipalDue; - this.cumulativePrincipalPaid = cumulativePrincipalPaid; - this.cumulativePrincipalWrittenOff = cumulativePrincipalWrittenOff; - this.cumulativePrincipalOutstanding = cumulativePrincipalOutstanding; - this.cumulativeInterestExpected = cumulativeInterestExpected; - this.cumulativeInterestPaid = cumulativeInterestPaid; - this.cumulativeInterestWrittenOff = cumulativeInterestWrittenOff; - this.cumulativeInterestWaived = cumulativeInterestWaived; - this.cumulativeInterestOutstanding = cumulativeInterestOutstanding; - this.cumulativeFeeChargesToDate = cumulativeFeeChargesToDate; - this.cumulativeFeeChargesPaid = cumulativeFeeChargesPaid; - this.cumulativeFeeChargesWaived = cumulativeFeeChargesWaived; - this.cumulativeFeeChargesWrittenOff = cumulativeFeeChargesWrittenOff; - this.cumulativeFeeChargesOutstanding = cumulativeFeeChargesOutstanding; - this.cumulativePenaltyChargesToDate = cumulativePenaltyChargesToDate; - this.cumulativePenaltyChargesPaid = cumulativePenaltyChargesPaid; - this.cumulativePenaltyChargesWaived = cumulativePenaltyChargesWaived; - this.cumulativePenaltyChargesWrittenOff = cumulativePenaltyChargesWrittenOff; - this.cumulativePenaltyChargesOutstanding = cumulativePenaltyChargesOutstanding; - this.totalCostOfLoan = totalCostOfLoan; - this.totalExpectedRepayment = totalExpectedRepayment; - this.totalPaidToDate = totalPaidToDate; - this.totalWaivedToDate = totalWaivedToDate; - this.totalWrittenOffToDate = totalWrittenOffToDate; + this.totalPrincipalDisbursed = totalPrincipalDisbursed; + this.totalPrincipalExpected = totalPrincipalExpected; + this.totalPrincipalPaid = totalPrincipalPaid; + this.totalInterestCharged = totalInterestCharged; + this.totalFeeChargesCharged = totalFeeChargesCharged; + this.totalPenaltyChargesCharged = totalPenaltyChargesCharged; + this.totalWaived = totalWaived; + this.totalWrittenOff = totalWrittenOff; + this.totalRepaymentExpected = totalRepaymentExpected; + this.totalRepayment = totalRepayment; this.totalOutstanding = totalOutstanding; - this.totalInArrears = totalInArrears; } public Collection getPeriods() { return periods; } - - public BigDecimal totalOutstanding() { - return this.totalOutstanding; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java index 5dc61852a..17bed9155 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/data/LoanSchedulePeriodData.java @@ -16,439 +16,381 @@ import org.joda.time.LocalDate; */ public class LoanSchedulePeriodData { - private final Integer period; - private final LocalDate fromDate; - private final LocalDate dueDate; - private final Integer daysInPeriod; - private final BigDecimal principalDisbursed; - @SuppressWarnings("unused") - private final BigDecimal principalOriginalDue; - private final BigDecimal principalDue; - private final BigDecimal principalPaid; - private final BigDecimal principalWrittenOff; - private final BigDecimal principalOutstanding; - @SuppressWarnings("unused") - private final BigDecimal principalLoanBalanceOutstanding; - @SuppressWarnings("unused") - private final BigDecimal interestOriginalDue; - private final BigDecimal interestDue; - private final BigDecimal interestPaid; - private final BigDecimal interestWaived; - private final BigDecimal interestWrittenOff; - private final BigDecimal interestOutstanding; - private final BigDecimal feeChargesDue; - private final BigDecimal feeChargesPaid; - private final BigDecimal feeChargesWaived; - private final BigDecimal feeChargesWrittenOff; - private final BigDecimal feeChargesOutstanding; - private final BigDecimal penaltyChargesDue; - private final BigDecimal penaltyChargesPaid; - private final BigDecimal penaltyChargesWaived; - private final BigDecimal penaltyChargesWrittenOff; - private final BigDecimal penaltyChargesOutstanding; - - @SuppressWarnings("unused") - private final BigDecimal totalOriginalDueForPeriod; - @SuppressWarnings("unused") - private final BigDecimal totalDueForPeriod; - @SuppressWarnings("unused") - private final BigDecimal totalPaidForPeriod; - @SuppressWarnings("unused") - private final BigDecimal totalWaivedForPeriod; - @SuppressWarnings("unused") - private final BigDecimal totalWrittenOffForPeriod; - private final BigDecimal totalOutstandingForPeriod; - private final BigDecimal totalOverdue; - @SuppressWarnings("unused") - private final BigDecimal totalActualCostOfLoanForPeriod; + private final Integer period; + private final LocalDate fromDate; + private final LocalDate dueDate; + private final Integer daysInPeriod; + private final BigDecimal principalDisbursed; + @SuppressWarnings("unused") + private final BigDecimal principalOriginalDue; + private final BigDecimal principalDue; + private final BigDecimal principalPaid; + private final BigDecimal principalWrittenOff; + private final BigDecimal principalOutstanding; + @SuppressWarnings("unused") + private final BigDecimal principalLoanBalanceOutstanding; + @SuppressWarnings("unused") + private final BigDecimal interestOriginalDue; + private final BigDecimal interestDue; + private final BigDecimal interestPaid; + private final BigDecimal interestWaived; + private final BigDecimal interestWrittenOff; + private final BigDecimal interestOutstanding; + private final BigDecimal feeChargesDue; + private final BigDecimal feeChargesPaid; + private final BigDecimal feeChargesWaived; + private final BigDecimal feeChargesWrittenOff; + private final BigDecimal feeChargesOutstanding; + private final BigDecimal penaltyChargesDue; + private final BigDecimal penaltyChargesPaid; + private final BigDecimal penaltyChargesWaived; + private final BigDecimal penaltyChargesWrittenOff; + private final BigDecimal penaltyChargesOutstanding; - public static LoanSchedulePeriodData disbursementOnlyPeriod( - final LocalDate disbursementDate, - final BigDecimal principalDisbursed, - final BigDecimal feeChargesDueAtTimeOfDisbursement, - final boolean isDisbursed) { - Integer periodNumber = Integer.valueOf(0); - LocalDate from = null; - return new LoanSchedulePeriodData(periodNumber, from, disbursementDate, principalDisbursed, feeChargesDueAtTimeOfDisbursement, isDisbursed); - } - - public static LoanSchedulePeriodData repaymentOnlyPeriod( - final Integer periodNumber, - final LocalDate fromDate, - final LocalDate dueDate, - final BigDecimal principalDue, - final BigDecimal principalOutstanding, - final BigDecimal interestDueOnPrincipalOutstanding, - final BigDecimal feeChargesDueForPeriod, - final BigDecimal penaltyChargesDueForPeriod, - final BigDecimal totalDueForPeriod) { - - return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, principalDue, principalOutstanding, - interestDueOnPrincipalOutstanding, feeChargesDueForPeriod, penaltyChargesDueForPeriod, totalDueForPeriod); - } - - public static LoanSchedulePeriodData repaymentPeriodWithPayments( - @SuppressWarnings("unused") final Long loanId, - final Integer periodNumber, - final LocalDate fromDate, - final LocalDate dueDate, - final BigDecimal principalOriginalDue, - final BigDecimal principalPaid, - final BigDecimal principalWrittenOff, - final BigDecimal principalOutstanding, - final BigDecimal outstandingPrincipalBalanceOfLoan, - final BigDecimal interestDueOnPrincipalOutstanding, - final BigDecimal interestPaid, - final BigDecimal interestWaived, - final BigDecimal interestWrittenOff, - final BigDecimal interestOutstanding, - final BigDecimal feeChargesDue, - final BigDecimal feeChargesPaid, - final BigDecimal feeChargesWaived, - final BigDecimal feeChargesWrittenOff, - final BigDecimal feeChargesOutstanding, - final BigDecimal penaltyChargesDue, - final BigDecimal penaltyChargesPaid, - final BigDecimal penaltyChargesWaived, - final BigDecimal penaltyChargesWrittenOff, - final BigDecimal penaltyChargesOutstanding, - final BigDecimal totalDueForPeriod, - final BigDecimal totalPaid, - final BigDecimal totalWaived, - final BigDecimal totalWrittenOff, - final BigDecimal totalOutstanding, - final BigDecimal totalActualCostOfLoanForPeriod) { - - return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, - principalOriginalDue, principalPaid, principalWrittenOff, principalOutstanding, outstandingPrincipalBalanceOfLoan, - interestDueOnPrincipalOutstanding, interestPaid, interestWaived, interestWrittenOff, interestOutstanding, - feeChargesDue, feeChargesPaid, feeChargesWaived, feeChargesWrittenOff, feeChargesOutstanding, - penaltyChargesDue, penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, penaltyChargesOutstanding, - totalDueForPeriod, totalPaid, totalWaived, totalWrittenOff, totalOutstanding, totalActualCostOfLoanForPeriod); - } - - /* - * constructor used for creating period on loan schedule that is only a disbursement (typically first period) - */ - private LoanSchedulePeriodData( - final Integer periodNumber, - final LocalDate fromDate, - final LocalDate dueDate, - final BigDecimal principalDisbursed, - final BigDecimal chargesDueAtTimeOfDisbursement, - final boolean isDisbursed) { - this.period = periodNumber; - this.fromDate = fromDate; - this.dueDate = dueDate; - if (fromDate != null) { - this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); - } else { - this.daysInPeriod = null; - } - this.principalDisbursed = principalDisbursed; - this.principalOriginalDue = null; - this.principalDue = null; - this.principalPaid = null; - this.principalWrittenOff = null; - this.principalOutstanding = null; - this.principalLoanBalanceOutstanding = principalDisbursed; - - this.interestOriginalDue = null; - this.interestDue = null; - this.interestPaid = null; - this.interestWaived = null; - this.interestWrittenOff = null; - this.interestOutstanding = null; - - this.feeChargesDue = chargesDueAtTimeOfDisbursement; - if (isDisbursed) { - this.feeChargesPaid = chargesDueAtTimeOfDisbursement; - this.feeChargesWaived = null; - this.feeChargesWrittenOff = null; - this.feeChargesOutstanding = null; - } else { - this.feeChargesPaid = null; - this.feeChargesWaived = null; - this.feeChargesWrittenOff = null; - this.feeChargesOutstanding = chargesDueAtTimeOfDisbursement; - } - - this.penaltyChargesDue = null; - this.penaltyChargesPaid = null; - this.penaltyChargesWaived = null; - this.penaltyChargesWrittenOff = null; - this.penaltyChargesOutstanding = null; - - this.totalOriginalDueForPeriod = chargesDueAtTimeOfDisbursement; - this.totalDueForPeriod = chargesDueAtTimeOfDisbursement; - this.totalPaidForPeriod = this.feeChargesPaid; - this.totalWaivedForPeriod = null; - this.totalWrittenOffForPeriod = null; - this.totalOutstandingForPeriod = this.feeChargesOutstanding; - this.totalActualCostOfLoanForPeriod = this.feeChargesDue; - if (dueDate.isBefore(new LocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } - } - - private LoanSchedulePeriodData( - final Integer periodNumber, - final LocalDate fromDate, - final LocalDate dueDate, - final BigDecimal principalOriginalDue, - final BigDecimal principalOutstanding, - final BigDecimal interestDueOnPrincipalOutstanding, - final BigDecimal feeChargesDueForPeriod, - final BigDecimal penaltyChargesDueForPeriod, - final BigDecimal totalDueForPeriod) { - this.period = periodNumber; - this.fromDate = fromDate; - this.dueDate = dueDate; - if (fromDate != null) { - this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); - } else { - this.daysInPeriod = null; - } - this.principalDisbursed = null; - this.principalOriginalDue = principalOriginalDue; - this.principalDue = principalOriginalDue; - this.principalPaid = null; - this.principalWrittenOff = null; - this.principalOutstanding = principalOriginalDue; - this.principalLoanBalanceOutstanding = principalOutstanding; - - this.interestOriginalDue = interestDueOnPrincipalOutstanding; - this.interestDue = interestDueOnPrincipalOutstanding; - this.interestPaid = null; - this.interestWaived = null; - this.interestWrittenOff = null; - this.interestOutstanding = interestDueOnPrincipalOutstanding; - - this.feeChargesDue = feeChargesDueForPeriod; - this.feeChargesPaid = null; - this.feeChargesWaived = null; - this.feeChargesWrittenOff = null; - this.feeChargesOutstanding = null; - - this.penaltyChargesDue = penaltyChargesDueForPeriod; - this.penaltyChargesPaid = null; - this.penaltyChargesWaived = null; - this.penaltyChargesWrittenOff = null; - this.penaltyChargesOutstanding = null; - - this.totalOriginalDueForPeriod = totalDueForPeriod; - this.totalDueForPeriod = totalDueForPeriod; - this.totalPaidForPeriod = BigDecimal.ZERO; - this.totalWaivedForPeriod = null; - this.totalWrittenOffForPeriod = null; - this.totalOutstandingForPeriod = totalDueForPeriod; - this.totalActualCostOfLoanForPeriod = interestDueOnPrincipalOutstanding.add(feeChargesDueForPeriod); - - if (dueDate.isBefore(new LocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } - } - - /* - * Used for creating loan schedule periods with full information on expected principal, interest & charges along with what portion of each is paid. - */ - private LoanSchedulePeriodData( - final Integer periodNumber, - final LocalDate fromDate, - final LocalDate dueDate, - final BigDecimal principalOriginalDue, - final BigDecimal principalPaid, - final BigDecimal principalWrittenOff, - final BigDecimal principalOutstanding, - final BigDecimal principalLoanBalanceOutstanding, - final BigDecimal interestDueOnPrincipalOutstanding, - final BigDecimal interestPaid, - final BigDecimal interestWaived, - final BigDecimal interestWrittenOff, - final BigDecimal interestOutstanding, - final BigDecimal feeChargesDue, - final BigDecimal feeChargesPaid, - final BigDecimal feeChargesWaived, - final BigDecimal feeChargesWrittenOff, - final BigDecimal feeChargesOutstanding, - final BigDecimal penaltyChargesDue, - final BigDecimal penaltyChargesPaid, - final BigDecimal penaltyChargesWaived, - final BigDecimal penaltyChargesWrittenOff, - final BigDecimal penaltyChargesOutstanding, - final BigDecimal totalDueForPeriod, - final BigDecimal totalPaid, - final BigDecimal totalWaived, - final BigDecimal totalWrittenOff, - final BigDecimal totalOutstanding, - final BigDecimal totalActualCostOfLoanForPeriod) { - this.period = periodNumber; - this.fromDate = fromDate; - this.dueDate = dueDate; - if (fromDate != null) { - this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); - } else { - this.daysInPeriod = null; - } - this.principalDisbursed = null; - this.principalOriginalDue = principalOriginalDue; - this.principalDue = principalOriginalDue; - this.principalPaid = principalPaid; - this.principalWrittenOff = principalWrittenOff; - this.principalOutstanding = principalOutstanding; - this.principalLoanBalanceOutstanding = principalLoanBalanceOutstanding; - - this.interestOriginalDue = interestDueOnPrincipalOutstanding; - this.interestDue = interestDueOnPrincipalOutstanding; - this.interestPaid = interestPaid; - this.interestWaived = interestWaived; - this.interestWrittenOff = interestWrittenOff; - this.interestOutstanding = interestOutstanding; - - this.feeChargesDue = feeChargesDue; - this.feeChargesPaid = feeChargesPaid; - this.feeChargesWaived = feeChargesWaived; - this.feeChargesWrittenOff = feeChargesWrittenOff; - this.feeChargesOutstanding = feeChargesOutstanding; - - this.penaltyChargesDue = penaltyChargesDue; - this.penaltyChargesPaid = penaltyChargesPaid; - this.penaltyChargesWaived = penaltyChargesWaived; - this.penaltyChargesWrittenOff = penaltyChargesWrittenOff; - this.penaltyChargesOutstanding = penaltyChargesOutstanding; - - this.totalOriginalDueForPeriod = totalDueForPeriod; - this.totalDueForPeriod = totalDueForPeriod; - this.totalPaidForPeriod = totalPaid; - this.totalWaivedForPeriod = totalWaived; - this.totalWrittenOffForPeriod = totalWrittenOff; - this.totalOutstandingForPeriod = totalOutstanding; - this.totalActualCostOfLoanForPeriod = totalActualCostOfLoanForPeriod; - - if (dueDate.isBefore(new LocalDate())) { - this.totalOverdue = this.totalOutstandingForPeriod; - } else { - this.totalOverdue = null; - } - } - - private BigDecimal defaultToZeroIfNull(final BigDecimal possibleNullValue) { - BigDecimal value = BigDecimal.ZERO; - if (possibleNullValue != null) { - value = possibleNullValue; - } - return value; - } + @SuppressWarnings("unused") + private final BigDecimal totalOriginalDueForPeriod; + @SuppressWarnings("unused") + private final BigDecimal totalDueForPeriod; + @SuppressWarnings("unused") + private final BigDecimal totalPaidForPeriod; + @SuppressWarnings("unused") + private final BigDecimal totalWaivedForPeriod; + @SuppressWarnings("unused") + private final BigDecimal totalWrittenOffForPeriod; + private final BigDecimal totalOutstandingForPeriod; + private final BigDecimal totalOverdue; + @SuppressWarnings("unused") + private final BigDecimal totalActualCostOfLoanForPeriod; - public boolean isRepaymentPeriod() { - boolean isRepaymentPeriod = false; - if (principalDue != null && this.interestDue != null) { - isRepaymentPeriod = BigDecimal.ZERO.compareTo(this.principalDue) == -1 || BigDecimal.ZERO.compareTo(this.interestDue) == -1; - } - return isRepaymentPeriod; - } + public static LoanSchedulePeriodData disbursementOnlyPeriod(final LocalDate disbursementDate, final BigDecimal principalDisbursed, + final BigDecimal feeChargesDueAtTimeOfDisbursement, final boolean isDisbursed) { + Integer periodNumber = Integer.valueOf(0); + LocalDate from = null; + return new LoanSchedulePeriodData(periodNumber, from, disbursementDate, principalDisbursed, feeChargesDueAtTimeOfDisbursement, + isDisbursed); + } - public Integer periodNumber() { - return this.period; - } + public static LoanSchedulePeriodData repaymentOnlyPeriod(final Integer periodNumber, final LocalDate fromDate, final LocalDate dueDate, + final BigDecimal principalDue, final BigDecimal principalOutstanding, final BigDecimal interestDueOnPrincipalOutstanding, + final BigDecimal feeChargesDueForPeriod, final BigDecimal penaltyChargesDueForPeriod, final BigDecimal totalDueForPeriod) { - public LocalDate periodFromDate() { - return this.fromDate; - } - - public LocalDate periodDueDate() { - return this.dueDate; - } - - public Integer daysInPeriod() { - return this.daysInPeriod; - } - - public BigDecimal principalDisbursed() { - return defaultToZeroIfNull(this.principalDisbursed); - } + return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, principalDue, principalOutstanding, + interestDueOnPrincipalOutstanding, feeChargesDueForPeriod, penaltyChargesDueForPeriod, totalDueForPeriod); + } - public BigDecimal principalDue() { - return defaultToZeroIfNull(this.principalDue); - } + public static LoanSchedulePeriodData repaymentPeriodWithPayments(@SuppressWarnings("unused") final Long loanId, + final Integer periodNumber, final LocalDate fromDate, final LocalDate dueDate, final BigDecimal principalOriginalDue, + final BigDecimal principalPaid, final BigDecimal principalWrittenOff, final BigDecimal principalOutstanding, + final BigDecimal outstandingPrincipalBalanceOfLoan, final BigDecimal interestDueOnPrincipalOutstanding, + final BigDecimal interestPaid, final BigDecimal interestWaived, final BigDecimal interestWrittenOff, + final BigDecimal interestOutstanding, final BigDecimal feeChargesDue, final BigDecimal feeChargesPaid, + final BigDecimal feeChargesWaived, final BigDecimal feeChargesWrittenOff, final BigDecimal feeChargesOutstanding, + final BigDecimal penaltyChargesDue, final BigDecimal penaltyChargesPaid, final BigDecimal penaltyChargesWaived, + final BigDecimal penaltyChargesWrittenOff, final BigDecimal penaltyChargesOutstanding, final BigDecimal totalDueForPeriod, + final BigDecimal totalPaid, final BigDecimal totalWaived, final BigDecimal totalWrittenOff, final BigDecimal totalOutstanding, + final BigDecimal totalActualCostOfLoanForPeriod) { - public BigDecimal principalPaid() { - return defaultToZeroIfNull(this.principalPaid); - } - - public BigDecimal principalWrittenOff() { - return defaultToZeroIfNull(this.principalWrittenOff); - } - - public BigDecimal principalOutstanding() { - return defaultToZeroIfNull(this.principalOutstanding); - } - - public BigDecimal interestDue() { - return defaultToZeroIfNull(this.interestDue); - } + return new LoanSchedulePeriodData(periodNumber, fromDate, dueDate, principalOriginalDue, principalPaid, principalWrittenOff, + principalOutstanding, outstandingPrincipalBalanceOfLoan, interestDueOnPrincipalOutstanding, interestPaid, interestWaived, + interestWrittenOff, interestOutstanding, feeChargesDue, feeChargesPaid, feeChargesWaived, feeChargesWrittenOff, + feeChargesOutstanding, penaltyChargesDue, penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, + penaltyChargesOutstanding, totalDueForPeriod, totalPaid, totalWaived, totalWrittenOff, totalOutstanding, + totalActualCostOfLoanForPeriod); + } - public BigDecimal interestPaid() { - return defaultToZeroIfNull(this.interestPaid); - } + /* + * constructor used for creating period on loan schedule that is only a + * disbursement (typically first period) + */ + private LoanSchedulePeriodData(final Integer periodNumber, final LocalDate fromDate, final LocalDate dueDate, + final BigDecimal principalDisbursed, final BigDecimal chargesDueAtTimeOfDisbursement, final boolean isDisbursed) { + this.period = periodNumber; + this.fromDate = fromDate; + this.dueDate = dueDate; + if (fromDate != null) { + this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); + } else { + this.daysInPeriod = null; + } + this.principalDisbursed = principalDisbursed; + this.principalOriginalDue = null; + this.principalDue = null; + this.principalPaid = null; + this.principalWrittenOff = null; + this.principalOutstanding = null; + this.principalLoanBalanceOutstanding = principalDisbursed; - public BigDecimal interestWaived() { - return defaultToZeroIfNull(this.interestWaived); - } - - public BigDecimal interestWrittenOff() { - return defaultToZeroIfNull(this.interestWrittenOff); - } + this.interestOriginalDue = null; + this.interestDue = null; + this.interestPaid = null; + this.interestWaived = null; + this.interestWrittenOff = null; + this.interestOutstanding = null; - public BigDecimal interestOutstanding() { - return defaultToZeroIfNull(this.interestOutstanding); - } + this.feeChargesDue = chargesDueAtTimeOfDisbursement; + if (isDisbursed) { + this.feeChargesPaid = chargesDueAtTimeOfDisbursement; + this.feeChargesWaived = null; + this.feeChargesWrittenOff = null; + this.feeChargesOutstanding = null; + } else { + this.feeChargesPaid = null; + this.feeChargesWaived = null; + this.feeChargesWrittenOff = null; + this.feeChargesOutstanding = chargesDueAtTimeOfDisbursement; + } - public BigDecimal feeChargesDue() { - return defaultToZeroIfNull(this.feeChargesDue); - } - - public BigDecimal feeChargesWaived() { - return defaultToZeroIfNull(this.feeChargesWaived); - } - - public BigDecimal feeChargesWrittenOff() { - return defaultToZeroIfNull(this.feeChargesWrittenOff); - } + this.penaltyChargesDue = null; + this.penaltyChargesPaid = null; + this.penaltyChargesWaived = null; + this.penaltyChargesWrittenOff = null; + this.penaltyChargesOutstanding = null; - public BigDecimal feeChargesPaid() { - return defaultToZeroIfNull(this.feeChargesPaid); - } + this.totalOriginalDueForPeriod = chargesDueAtTimeOfDisbursement; + this.totalDueForPeriod = chargesDueAtTimeOfDisbursement; + this.totalPaidForPeriod = this.feeChargesPaid; + this.totalWaivedForPeriod = null; + this.totalWrittenOffForPeriod = null; + this.totalOutstandingForPeriod = this.feeChargesOutstanding; + this.totalActualCostOfLoanForPeriod = this.feeChargesDue; + if (dueDate.isBefore(new LocalDate())) { + this.totalOverdue = this.totalOutstandingForPeriod; + } else { + this.totalOverdue = null; + } + } - public BigDecimal feeChargesOutstanding() { - return defaultToZeroIfNull(this.feeChargesOutstanding); - } - - public BigDecimal penaltyChargesDue() { - return defaultToZeroIfNull(this.penaltyChargesDue); - } - - public BigDecimal penaltyChargesWaived() { - return defaultToZeroIfNull(this.penaltyChargesWaived); - } - - public BigDecimal penaltyChargesWrittenOff() { - return defaultToZeroIfNull(this.penaltyChargesWrittenOff); - } + private LoanSchedulePeriodData(final Integer periodNumber, final LocalDate fromDate, final LocalDate dueDate, + final BigDecimal principalOriginalDue, final BigDecimal principalOutstanding, + final BigDecimal interestDueOnPrincipalOutstanding, final BigDecimal feeChargesDueForPeriod, + final BigDecimal penaltyChargesDueForPeriod, final BigDecimal totalDueForPeriod) { + this.period = periodNumber; + this.fromDate = fromDate; + this.dueDate = dueDate; + if (fromDate != null) { + this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); + } else { + this.daysInPeriod = null; + } + this.principalDisbursed = null; + this.principalOriginalDue = principalOriginalDue; + this.principalDue = principalOriginalDue; + this.principalPaid = null; + this.principalWrittenOff = null; + this.principalOutstanding = principalOriginalDue; + this.principalLoanBalanceOutstanding = principalOutstanding; - public BigDecimal penaltyChargesPaid() { - return defaultToZeroIfNull(this.penaltyChargesPaid); - } + this.interestOriginalDue = interestDueOnPrincipalOutstanding; + this.interestDue = interestDueOnPrincipalOutstanding; + this.interestPaid = null; + this.interestWaived = null; + this.interestWrittenOff = null; + this.interestOutstanding = interestDueOnPrincipalOutstanding; - public BigDecimal penaltyChargesOutstanding() { - return defaultToZeroIfNull(this.penaltyChargesOutstanding); - } + this.feeChargesDue = feeChargesDueForPeriod; + this.feeChargesPaid = null; + this.feeChargesWaived = null; + this.feeChargesWrittenOff = null; + this.feeChargesOutstanding = null; - public BigDecimal totalOverdue() { - return defaultToZeroIfNull(this.totalOverdue); - } + this.penaltyChargesDue = penaltyChargesDueForPeriod; + this.penaltyChargesPaid = null; + this.penaltyChargesWaived = null; + this.penaltyChargesWrittenOff = null; + this.penaltyChargesOutstanding = null; + + this.totalOriginalDueForPeriod = totalDueForPeriod; + this.totalDueForPeriod = totalDueForPeriod; + this.totalPaidForPeriod = BigDecimal.ZERO; + this.totalWaivedForPeriod = null; + this.totalWrittenOffForPeriod = null; + this.totalOutstandingForPeriod = totalDueForPeriod; + this.totalActualCostOfLoanForPeriod = interestDueOnPrincipalOutstanding.add(feeChargesDueForPeriod); + + if (dueDate.isBefore(new LocalDate())) { + this.totalOverdue = this.totalOutstandingForPeriod; + } else { + this.totalOverdue = null; + } + } + + /* + * Used for creating loan schedule periods with full information on expected + * principal, interest & charges along with what portion of each is paid. + */ + private LoanSchedulePeriodData(final Integer periodNumber, final LocalDate fromDate, final LocalDate dueDate, + final BigDecimal principalOriginalDue, final BigDecimal principalPaid, final BigDecimal principalWrittenOff, + final BigDecimal principalOutstanding, final BigDecimal principalLoanBalanceOutstanding, + final BigDecimal interestDueOnPrincipalOutstanding, final BigDecimal interestPaid, final BigDecimal interestWaived, + final BigDecimal interestWrittenOff, final BigDecimal interestOutstanding, final BigDecimal feeChargesDue, + final BigDecimal feeChargesPaid, final BigDecimal feeChargesWaived, final BigDecimal feeChargesWrittenOff, + final BigDecimal feeChargesOutstanding, final BigDecimal penaltyChargesDue, final BigDecimal penaltyChargesPaid, + final BigDecimal penaltyChargesWaived, final BigDecimal penaltyChargesWrittenOff, final BigDecimal penaltyChargesOutstanding, + final BigDecimal totalDueForPeriod, final BigDecimal totalPaid, final BigDecimal totalWaived, final BigDecimal totalWrittenOff, + final BigDecimal totalOutstanding, final BigDecimal totalActualCostOfLoanForPeriod) { + this.period = periodNumber; + this.fromDate = fromDate; + this.dueDate = dueDate; + if (fromDate != null) { + this.daysInPeriod = Days.daysBetween(this.fromDate, this.dueDate).getDays(); + } else { + this.daysInPeriod = null; + } + this.principalDisbursed = null; + this.principalOriginalDue = principalOriginalDue; + this.principalDue = principalOriginalDue; + this.principalPaid = principalPaid; + this.principalWrittenOff = principalWrittenOff; + this.principalOutstanding = principalOutstanding; + this.principalLoanBalanceOutstanding = principalLoanBalanceOutstanding; + + this.interestOriginalDue = interestDueOnPrincipalOutstanding; + this.interestDue = interestDueOnPrincipalOutstanding; + this.interestPaid = interestPaid; + this.interestWaived = interestWaived; + this.interestWrittenOff = interestWrittenOff; + this.interestOutstanding = interestOutstanding; + + this.feeChargesDue = feeChargesDue; + this.feeChargesPaid = feeChargesPaid; + this.feeChargesWaived = feeChargesWaived; + this.feeChargesWrittenOff = feeChargesWrittenOff; + this.feeChargesOutstanding = feeChargesOutstanding; + + this.penaltyChargesDue = penaltyChargesDue; + this.penaltyChargesPaid = penaltyChargesPaid; + this.penaltyChargesWaived = penaltyChargesWaived; + this.penaltyChargesWrittenOff = penaltyChargesWrittenOff; + this.penaltyChargesOutstanding = penaltyChargesOutstanding; + + this.totalOriginalDueForPeriod = totalDueForPeriod; + this.totalDueForPeriod = totalDueForPeriod; + this.totalPaidForPeriod = totalPaid; + this.totalWaivedForPeriod = totalWaived; + this.totalWrittenOffForPeriod = totalWrittenOff; + this.totalOutstandingForPeriod = totalOutstanding; + this.totalActualCostOfLoanForPeriod = totalActualCostOfLoanForPeriod; + + if (dueDate.isBefore(new LocalDate())) { + this.totalOverdue = this.totalOutstandingForPeriod; + } else { + this.totalOverdue = null; + } + } + + private BigDecimal defaultToZeroIfNull(final BigDecimal possibleNullValue) { + BigDecimal value = BigDecimal.ZERO; + if (possibleNullValue != null) { + value = possibleNullValue; + } + return value; + } + + public boolean isRepaymentPeriod() { + boolean isRepaymentPeriod = false; + if (principalDue != null && this.interestDue != null) { + isRepaymentPeriod = BigDecimal.ZERO.compareTo(this.principalDue) == -1 || BigDecimal.ZERO.compareTo(this.interestDue) == -1; + } + return isRepaymentPeriod; + } + + public Integer periodNumber() { + return this.period; + } + + public LocalDate periodFromDate() { + return this.fromDate; + } + + public LocalDate periodDueDate() { + return this.dueDate; + } + + public Integer daysInPeriod() { + return this.daysInPeriod; + } + + public BigDecimal principalDisbursed() { + return defaultToZeroIfNull(this.principalDisbursed); + } + + public BigDecimal principalDue() { + return defaultToZeroIfNull(this.principalDue); + } + + public BigDecimal principalPaid() { + return defaultToZeroIfNull(this.principalPaid); + } + + public BigDecimal principalWrittenOff() { + return defaultToZeroIfNull(this.principalWrittenOff); + } + + public BigDecimal principalOutstanding() { + return defaultToZeroIfNull(this.principalOutstanding); + } + + public BigDecimal interestDue() { + return defaultToZeroIfNull(this.interestDue); + } + + public BigDecimal interestPaid() { + return defaultToZeroIfNull(this.interestPaid); + } + + public BigDecimal interestWaived() { + return defaultToZeroIfNull(this.interestWaived); + } + + public BigDecimal interestWrittenOff() { + return defaultToZeroIfNull(this.interestWrittenOff); + } + + public BigDecimal interestOutstanding() { + return defaultToZeroIfNull(this.interestOutstanding); + } + + public BigDecimal feeChargesDue() { + return defaultToZeroIfNull(this.feeChargesDue); + } + + public BigDecimal feeChargesWaived() { + return defaultToZeroIfNull(this.feeChargesWaived); + } + + public BigDecimal feeChargesWrittenOff() { + return defaultToZeroIfNull(this.feeChargesWrittenOff); + } + + public BigDecimal feeChargesPaid() { + return defaultToZeroIfNull(this.feeChargesPaid); + } + + public BigDecimal feeChargesOutstanding() { + return defaultToZeroIfNull(this.feeChargesOutstanding); + } + + public BigDecimal penaltyChargesDue() { + return defaultToZeroIfNull(this.penaltyChargesDue); + } + + public BigDecimal penaltyChargesWaived() { + return defaultToZeroIfNull(this.penaltyChargesWaived); + } + + public BigDecimal penaltyChargesWrittenOff() { + return defaultToZeroIfNull(this.penaltyChargesWrittenOff); + } + + public BigDecimal penaltyChargesPaid() { + return defaultToZeroIfNull(this.penaltyChargesPaid); + } + + public BigDecimal penaltyChargesOutstanding() { + return defaultToZeroIfNull(this.penaltyChargesOutstanding); + } + + public BigDecimal totalOverdue() { + return defaultToZeroIfNull(this.totalOverdue); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualInstallmentsAmortizationLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualInstallmentsAmortizationLoanScheduleGenerator.java index 0bb00cf4f..03ff228c8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualInstallmentsAmortizationLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualInstallmentsAmortizationLoanScheduleGenerator.java @@ -70,10 +70,17 @@ public class EqualInstallmentsAmortizationLoanScheduleGenerator implements Amort periods.add(disbursementPeriod); int loanTermInDays = Integer.valueOf(0); - BigDecimal cumulativePrincipalDisbursed = loanScheduleInfo.getPrincipal().getAmount(); - BigDecimal cumulativePrincipalDue = BigDecimal.ZERO; - BigDecimal cumulativeInterestExpected = BigDecimal.ZERO; - BigDecimal totalExpectedRepayment = chargesDueAtTimeOfDisbursement; + BigDecimal totalPrincipalDisbursed = principalDisbursed.getAmount(); + BigDecimal totalPrincipalExpected = BigDecimal.ZERO; + BigDecimal totalPrincipalPaid = BigDecimal.ZERO; + BigDecimal totalInterestCharged = BigDecimal.ZERO; + BigDecimal totalFeeChargesCharged = BigDecimal.ZERO; + BigDecimal totalPenaltyChargesCharged = BigDecimal.ZERO; + BigDecimal totalWaived = BigDecimal.ZERO; + BigDecimal totalWrittenOff = BigDecimal.ZERO; + BigDecimal totalRepaymentExpected = chargesDueAtTimeOfDisbursement; + BigDecimal totalRepayment = BigDecimal.ZERO; + BigDecimal totalOutstanding = BigDecimal.ZERO; LocalDate startDate = disbursementDate; int periodNumber = 1; @@ -138,21 +145,20 @@ public class EqualInstallmentsAmortizationLoanScheduleGenerator implements Amort // handle cumulative fields loanTermInDays += daysInPeriod; - cumulativePrincipalDue = cumulativePrincipalDue.add(principalForInstallment.getAmount()); - cumulativeInterestExpected = cumulativeInterestExpected.add(interestForInstallment.getAmount()); - totalExpectedRepayment = totalExpectedRepayment.add(totalInstallmentDue.getAmount()); + totalPrincipalExpected = totalPrincipalExpected.add(principalForInstallment.getAmount()); + totalInterestCharged = totalInterestCharged.add(interestForInstallment.getAmount()); + totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount()); startDate = scheduledDueDate; periodNumber++; } - final BigDecimal cumulativePrincipalOutstanding = cumulativePrincipalDisbursed.subtract(cumulativePrincipalDue); + final CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), + monetaryCurrency.getDigitsAfterDecimal(), currency.getDisplaySymbol(), currency.getNameCode()); - CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), monetaryCurrency.getDigitsAfterDecimal(), - currency.getDisplaySymbol(), currency.getNameCode()); - - return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue, - cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment); + return new LoanScheduleData(currencyData, periods, loanTermInDays, totalPrincipalDisbursed, totalPrincipalExpected, + totalPrincipalPaid, totalInterestCharged, totalFeeChargesCharged, totalPenaltyChargesCharged, totalWaived, totalWrittenOff, + totalRepaymentExpected, totalRepayment, totalOutstanding); } private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set loanCharges, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualPrincipalAmortizationLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualPrincipalAmortizationLoanScheduleGenerator.java index 0b322e70a..7bd9270cf 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualPrincipalAmortizationLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/EqualPrincipalAmortizationLoanScheduleGenerator.java @@ -24,123 +24,125 @@ import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail; public class EqualPrincipalAmortizationLoanScheduleGenerator implements AmortizationLoanScheduleGenerator { - private final PeriodicInterestRateCalculator periodicInterestRateCalculator = new PeriodicInterestRateCalculator(); - private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator(); - - @Override - public LoanScheduleData generate( - final ApplicationCurrency currency, - final LoanProductRelatedDetail loanScheduleInfo, - final LocalDate disbursementDate, - final LocalDate interestCalculatedFrom, - final BigDecimal periodInterestRateForRepaymentPeriod, - final LocalDate idealDisbursementDateBasedOnFirstRepaymentDate, - final List scheduledDates, - final Set loanCharges) { + private final PeriodicInterestRateCalculator periodicInterestRateCalculator = new PeriodicInterestRateCalculator(); + private final PaymentPeriodsInOneYearCalculator paymentPeriodsInOneYearCalculator = new DefaultPaymentPeriodsInOneYearCalculator(); - final Collection periods = new ArrayList(); - - // 1. we know 'principal' must be equal over repayments so use this to calculate interest and thus total repayment due. - final MonetaryCurrency monetaryCurrency = loanScheduleInfo.getPrincipal().getCurrency(); - Money totalDuePerInstallment = Money.zero(monetaryCurrency); + @Override + public LoanScheduleData generate(final ApplicationCurrency currency, final LoanProductRelatedDetail loanScheduleInfo, + final LocalDate disbursementDate, final LocalDate interestCalculatedFrom, + final BigDecimal periodInterestRateForRepaymentPeriod, final LocalDate idealDisbursementDateBasedOnFirstRepaymentDate, + final List scheduledDates, final Set loanCharges) { - Money outstandingBalance = loanScheduleInfo.getPrincipal(); - Money principalDisbursed = loanScheduleInfo.getPrincipal(); - Money totalPrincipal = Money.zero(monetaryCurrency); - Money totalInterest = Money.zero(monetaryCurrency); - - double interestCalculationGraceOnRepaymentPeriodFraction = this.paymentPeriodsInOneYearCalculator.calculateRepaymentPeriodAsAFractionOfDays(loanScheduleInfo.getRepaymentPeriodFrequencyType(), - loanScheduleInfo.getRepayEvery(), interestCalculatedFrom, scheduledDates, idealDisbursementDateBasedOnFirstRepaymentDate); - - BigDecimal chargesDueAtTimeOfDisbursement = BigDecimal.ZERO; - for (LoanCharge loanCharge : loanCharges) { - if (loanCharge.isDueAtDisbursement()) { - chargesDueAtTimeOfDisbursement = chargesDueAtTimeOfDisbursement.add(loanCharge.amount()); - } - } - - BigDecimal cumulativeChargesToDate = chargesDueAtTimeOfDisbursement; - - // create entries of disbursement period on loan schedule - final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod(disbursementDate, principalDisbursed.getAmount(), chargesDueAtTimeOfDisbursement, false); - periods.add(disbursementPeriod); - - int loanTermInDays = Integer.valueOf(0); - BigDecimal cumulativePrincipalDisbursed = principalDisbursed.getAmount(); - BigDecimal cumulativePrincipalDue = BigDecimal.ZERO; - BigDecimal cumulativeInterestExpected = BigDecimal.ZERO; - BigDecimal totalExpectedRepayment = chargesDueAtTimeOfDisbursement; - - LocalDate startDate = disbursementDate; - int periodNumber = 1; - for (LocalDate scheduledDueDate : scheduledDates) { + final Collection periods = new ArrayList(); - // number of days from startDate to this scheduledDate - int daysInPeriod = Days.daysBetween(startDate.toDateMidnight().toDateTime(), scheduledDueDate.toDateMidnight().toDateTime()).getDays(); - - Money interestForInstallment = this.periodicInterestRateCalculator.calculateInterestOn(outstandingBalance, periodInterestRateForRepaymentPeriod, daysInPeriod, loanScheduleInfo); - Money principalForInstallment = this.periodicInterestRateCalculator.calculatePrincipalOn(totalDuePerInstallment, interestForInstallment, loanScheduleInfo); - - if (interestCalculationGraceOnRepaymentPeriodFraction >= Integer.valueOf(1).doubleValue()) { - Money graceOnInterestForRepaymentPeriod = interestForInstallment; - interestForInstallment = interestForInstallment.minus(graceOnInterestForRepaymentPeriod); - interestCalculationGraceOnRepaymentPeriodFraction = interestCalculationGraceOnRepaymentPeriodFraction - Integer.valueOf(1).doubleValue(); - } else if (interestCalculationGraceOnRepaymentPeriodFraction > Double.valueOf("0.25") && interestCalculationGraceOnRepaymentPeriodFraction < Integer.valueOf(1).doubleValue()) { - Money graceOnInterestForRepaymentPeriod = interestForInstallment.multipliedBy(interestCalculationGraceOnRepaymentPeriodFraction); - interestForInstallment = interestForInstallment.minus(graceOnInterestForRepaymentPeriod); - interestCalculationGraceOnRepaymentPeriodFraction = Double.valueOf("0"); - } - - totalPrincipal = totalPrincipal.plus(principalForInstallment); - totalInterest = totalInterest.plus(interestForInstallment); - - if (periodNumber == loanScheduleInfo.getNumberOfRepayments()) { - Money principalDifference = totalPrincipal.minus(loanScheduleInfo.getPrincipal()); - if (principalDifference.isLessThanZero()) { - principalForInstallment = principalForInstallment.plus(principalDifference.abs()); - } else if (principalDifference.isGreaterThanZero()) { - principalForInstallment = principalForInstallment.minus(principalDifference.abs()); - } - } + // 1. we know 'principal' must be equal over repayments so use this to + // calculate interest and thus total repayment due. + final MonetaryCurrency monetaryCurrency = loanScheduleInfo.getPrincipal().getCurrency(); + Money totalDuePerInstallment = Money.zero(monetaryCurrency); - outstandingBalance = outstandingBalance.minus(principalForInstallment); - - Money feeChargesForInstallment = Money.zero(monetaryCurrency); - Money penaltyChargesForInstallment = Money.zero(monetaryCurrency); - Money totalInstallmentDue = principalForInstallment.plus(interestForInstallment).plus(feeChargesForInstallment); - cumulativeChargesToDate = cumulativeChargesToDate.add(feeChargesForInstallment.getAmount()); - - LoanSchedulePeriodData installment = LoanSchedulePeriodData.repaymentOnlyPeriod(periodNumber, startDate, - scheduledDueDate, - principalForInstallment.getAmount(), - outstandingBalance.getAmount(), - interestForInstallment.getAmount(), - feeChargesForInstallment.getAmount(), - penaltyChargesForInstallment.getAmount(), - totalInstallmentDue.getAmount()); + Money outstandingBalance = loanScheduleInfo.getPrincipal(); + Money principalDisbursed = loanScheduleInfo.getPrincipal(); + Money totalPrincipal = Money.zero(monetaryCurrency); + Money totalInterest = Money.zero(monetaryCurrency); - periods.add(installment); - - // handle cumulative fields - loanTermInDays += daysInPeriod; - cumulativePrincipalDue = cumulativePrincipalDue.add(principalForInstallment.getAmount()); - cumulativeInterestExpected = cumulativeInterestExpected.add(interestForInstallment.getAmount()); - totalExpectedRepayment = totalExpectedRepayment.add(totalInstallmentDue.getAmount()); - startDate = scheduledDueDate; + double interestCalculationGraceOnRepaymentPeriodFraction = this.paymentPeriodsInOneYearCalculator + .calculateRepaymentPeriodAsAFractionOfDays(loanScheduleInfo.getRepaymentPeriodFrequencyType(), + loanScheduleInfo.getRepayEvery(), interestCalculatedFrom, scheduledDates, + idealDisbursementDateBasedOnFirstRepaymentDate); - periodNumber++; - } - - final BigDecimal cumulativePrincipalOutstanding = cumulativePrincipalDisbursed.subtract(cumulativePrincipalDue); - - CurrencyData currencyData = new CurrencyData( - currency.getCode(), - currency.getName(), - monetaryCurrency.getDigitsAfterDecimal(), - currency.getDisplaySymbol(), - currency.getNameCode()); - - return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue, - cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment); - } + BigDecimal chargesDueAtTimeOfDisbursement = BigDecimal.ZERO; + for (LoanCharge loanCharge : loanCharges) { + if (loanCharge.isDueAtDisbursement()) { + chargesDueAtTimeOfDisbursement = chargesDueAtTimeOfDisbursement.add(loanCharge.amount()); + } + } + + BigDecimal cumulativeChargesToDate = chargesDueAtTimeOfDisbursement; + + // create entries of disbursement period on loan schedule + final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod(disbursementDate, + principalDisbursed.getAmount(), chargesDueAtTimeOfDisbursement, false); + periods.add(disbursementPeriod); + + int loanTermInDays = Integer.valueOf(0); + BigDecimal totalPrincipalDisbursed = principalDisbursed.getAmount(); + BigDecimal totalPrincipalExpected = BigDecimal.ZERO; + BigDecimal totalPrincipalPaid = BigDecimal.ZERO; + BigDecimal totalInterestCharged = BigDecimal.ZERO; + BigDecimal totalFeeChargesCharged = BigDecimal.ZERO; + BigDecimal totalPenaltyChargesCharged = BigDecimal.ZERO; + BigDecimal totalWaived = BigDecimal.ZERO; + BigDecimal totalWrittenOff = BigDecimal.ZERO; + BigDecimal totalRepaymentExpected = chargesDueAtTimeOfDisbursement; + BigDecimal totalRepayment = BigDecimal.ZERO; + BigDecimal totalOutstanding = BigDecimal.ZERO; + + LocalDate startDate = disbursementDate; + int periodNumber = 1; + for (LocalDate scheduledDueDate : scheduledDates) { + + // number of days from startDate to this scheduledDate + int daysInPeriod = Days.daysBetween(startDate.toDateMidnight().toDateTime(), scheduledDueDate.toDateMidnight().toDateTime()) + .getDays(); + + Money interestForInstallment = this.periodicInterestRateCalculator.calculateInterestOn(outstandingBalance, + periodInterestRateForRepaymentPeriod, daysInPeriod, loanScheduleInfo); + Money principalForInstallment = this.periodicInterestRateCalculator.calculatePrincipalOn(totalDuePerInstallment, + interestForInstallment, loanScheduleInfo); + + if (interestCalculationGraceOnRepaymentPeriodFraction >= Integer.valueOf(1).doubleValue()) { + Money graceOnInterestForRepaymentPeriod = interestForInstallment; + interestForInstallment = interestForInstallment.minus(graceOnInterestForRepaymentPeriod); + interestCalculationGraceOnRepaymentPeriodFraction = interestCalculationGraceOnRepaymentPeriodFraction + - Integer.valueOf(1).doubleValue(); + } else if (interestCalculationGraceOnRepaymentPeriodFraction > Double.valueOf("0.25") + && interestCalculationGraceOnRepaymentPeriodFraction < Integer.valueOf(1).doubleValue()) { + Money graceOnInterestForRepaymentPeriod = interestForInstallment + .multipliedBy(interestCalculationGraceOnRepaymentPeriodFraction); + interestForInstallment = interestForInstallment.minus(graceOnInterestForRepaymentPeriod); + interestCalculationGraceOnRepaymentPeriodFraction = Double.valueOf("0"); + } + + totalPrincipal = totalPrincipal.plus(principalForInstallment); + totalInterest = totalInterest.plus(interestForInstallment); + + if (periodNumber == loanScheduleInfo.getNumberOfRepayments()) { + Money principalDifference = totalPrincipal.minus(loanScheduleInfo.getPrincipal()); + if (principalDifference.isLessThanZero()) { + principalForInstallment = principalForInstallment.plus(principalDifference.abs()); + } else if (principalDifference.isGreaterThanZero()) { + principalForInstallment = principalForInstallment.minus(principalDifference.abs()); + } + } + + outstandingBalance = outstandingBalance.minus(principalForInstallment); + + Money feeChargesForInstallment = Money.zero(monetaryCurrency); + Money penaltyChargesForInstallment = Money.zero(monetaryCurrency); + Money totalInstallmentDue = principalForInstallment.plus(interestForInstallment).plus(feeChargesForInstallment); + cumulativeChargesToDate = cumulativeChargesToDate.add(feeChargesForInstallment.getAmount()); + + LoanSchedulePeriodData installment = LoanSchedulePeriodData.repaymentOnlyPeriod(periodNumber, startDate, scheduledDueDate, + principalForInstallment.getAmount(), outstandingBalance.getAmount(), interestForInstallment.getAmount(), + feeChargesForInstallment.getAmount(), penaltyChargesForInstallment.getAmount(), totalInstallmentDue.getAmount()); + + periods.add(installment); + + // handle cumulative fields + loanTermInDays += daysInPeriod; + totalPrincipalExpected = totalPrincipalExpected.add(principalForInstallment.getAmount()); + totalInterestCharged = totalInterestCharged.add(interestForInstallment.getAmount()); + totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount()); + startDate = scheduledDueDate; + + periodNumber++; + } + + final CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), + monetaryCurrency.getDigitsAfterDecimal(), currency.getDisplaySymbol(), currency.getNameCode()); + + return new LoanScheduleData(currencyData, periods, loanTermInDays, totalPrincipalDisbursed, totalPrincipalExpected, + totalPrincipalPaid, totalInterestCharged, totalFeeChargesCharged, totalPenaltyChargesCharged, totalWaived, totalWrittenOff, + totalRepaymentExpected, totalRepayment, totalOutstanding); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatMethodLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatMethodLoanScheduleGenerator.java index 6ff9564c1..851aa507b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatMethodLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/FlatMethodLoanScheduleGenerator.java @@ -75,10 +75,17 @@ public class FlatMethodLoanScheduleGenerator implements LoanScheduleGenerator { periods.add(disbursementPeriod); int loanTermInDays = Integer.valueOf(0); - BigDecimal cumulativePrincipalDisbursed = principalDisbursed.getAmount(); - BigDecimal cumulativePrincipalDue = BigDecimal.ZERO; - BigDecimal cumulativeInterestExpected = BigDecimal.ZERO; - BigDecimal totalExpectedRepayment = chargesDueAtTimeOfDisbursement; + BigDecimal totalPrincipalDisbursed = principalDisbursed.getAmount(); + BigDecimal totalPrincipalExpected = BigDecimal.ZERO; + BigDecimal totalPrincipalPaid = BigDecimal.ZERO; + BigDecimal totalInterestCharged = BigDecimal.ZERO; + BigDecimal totalFeeChargesCharged = BigDecimal.ZERO; + BigDecimal totalPenaltyChargesCharged = BigDecimal.ZERO; + BigDecimal totalWaived = BigDecimal.ZERO; + BigDecimal totalWrittenOff = BigDecimal.ZERO; + BigDecimal totalRepaymentExpected = chargesDueAtTimeOfDisbursement; + BigDecimal totalRepayment = BigDecimal.ZERO; + BigDecimal totalOutstanding = BigDecimal.ZERO; LocalDate startDate = disbursementDate; int periodNumber = 1; @@ -128,21 +135,20 @@ public class FlatMethodLoanScheduleGenerator implements LoanScheduleGenerator { // handle cumulative fields loanTermInDays += daysInPeriod; - cumulativePrincipalDue = cumulativePrincipalDue.add(principalPerInstallment.getAmount()); - cumulativeInterestExpected = cumulativeInterestExpected.add(interestPerInstallment.getAmount()); - totalExpectedRepayment = totalExpectedRepayment.add(totalInstallmentDue.getAmount()); + totalPrincipalExpected = totalPrincipalExpected.add(principalPerInstallment.getAmount()); + totalInterestCharged = totalInterestCharged.add(interestPerInstallment.getAmount()); + totalRepaymentExpected = totalRepaymentExpected.add(totalInstallmentDue.getAmount()); startDate = scheduledDueDate; periodNumber++; } - final BigDecimal cumulativePrincipalOutstanding = cumulativePrincipalDisbursed.subtract(cumulativePrincipalDue); + final CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), + monetaryCurrency.getDigitsAfterDecimal(), currency.getDisplaySymbol(), currency.getNameCode()); - CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), monetaryCurrency.getDigitsAfterDecimal(), - currency.getDisplaySymbol(), currency.getNameCode()); - - return new LoanScheduleData(currencyData, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue, - cumulativePrincipalOutstanding, cumulativeInterestExpected, cumulativeChargesToDate, totalExpectedRepayment); + return new LoanScheduleData(currencyData, periods, loanTermInDays, totalPrincipalDisbursed, totalPrincipalExpected, + totalPrincipalPaid, totalInterestCharged, totalFeeChargesCharged, totalPenaltyChargesCharged, totalWaived, totalWrittenOff, + totalRepaymentExpected, totalRepayment, totalOutstanding); } private Money cumulativeFeeChargesDueWithin(final LocalDate periodStart, final LocalDate periodEnd, final Set loanCharges, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java index effe4f452..6c1c9667e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java @@ -33,8 +33,10 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanCollateral; import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; +import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.mifosplatform.portfolio.loanaccount.exception.LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeDeleted; import org.mifosplatform.portfolio.loanaccount.exception.LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified; import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException; @@ -76,6 +78,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private final LoanCollateralAssembler loanCollateralAssembler; private final AprCalculator aprCalculator; private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory; + private final LoanSummaryWrapper loanSummaryWrapper; + private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; @Autowired public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper, @@ -85,7 +89,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final LoanCollateralAssembler loanCollateralAssembler, final LoanRepository loanRepository, final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService, final ClientRepository clientRepository, final LoanProductRepository loanProductRepository, - final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory) { + final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final LoanSummaryWrapper loanSummaryWrapper, + final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory) { this.context = context; this.fromJsonHelper = fromJsonHelper; this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator; @@ -100,6 +105,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa this.clientRepository = clientRepository; this.loanProductRepository = loanProductRepository; this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory; + this.loanSummaryWrapper = loanSummaryWrapper; + this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -231,7 +238,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa final LoanScheduleData loanSchedule = this.calculationPlatformService.calculateLoanSchedule(query); existingLoanApplication.updateLoanSchedule(loanSchedule); - existingLoanApplication.updateLoanScheduleDependentDerivedFields(); } this.loanRepository.saveAndFlush(existingLoanApplication); @@ -439,6 +445,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa private Loan retrieveLoanBy(final Long loanId) { final Loan loan = this.loanRepository.findOne(loanId); if (loan == null) { throw new LoanNotFoundException(loanId); } + loan.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory); return loan; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java index 8d13d7d65..d5db88a8c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java @@ -34,7 +34,9 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanCollateral; import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; +import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository; import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanSchedule; @@ -63,13 +65,17 @@ public class LoanAssembler { private final LoanChargeAssembler loanChargeAssembler; private final LoanCollateralAssembler loanCollateralAssembler; private final FromJsonHelper fromApiJsonHelper; + private final LoanSummaryWrapper loanSummaryWrapper; + private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; @Autowired public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanProductRepository loanProductRepository, final ClientRepository clientRepository, final GroupRepository groupRepository, final FundRepository fundRepository, final LoanTransactionProcessingStrategyRepository loanTransactionProcessingStrategyRepository, final StaffRepository staffRepository, final CodeValueRepositoryWrapper codeValueRepository, - final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler, final LoanCollateralAssembler loanCollateralAssembler) { + final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler, + final LoanCollateralAssembler loanCollateralAssembler, final LoanSummaryWrapper loanSummaryWrapper, + final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory) { this.fromApiJsonHelper = fromApiJsonHelper; this.loanProductRepository = loanProductRepository; this.clientRepository = clientRepository; @@ -81,6 +87,8 @@ public class LoanAssembler { this.loanScheduleAssembler = loanScheduleAssembler; this.loanChargeAssembler = loanChargeAssembler; this.loanCollateralAssembler = loanCollateralAssembler; + this.loanSummaryWrapper = loanSummaryWrapper; + this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; } public Loan assembleFrom(final JsonCommand command, final AppUser currentUser) { @@ -148,8 +156,11 @@ public class LoanAssembler { final LocalDate submittedOnDate = fromApiJsonHelper.extractLocalDateNamed("submittedOnDate", element); if (loanApplication == null) { throw new IllegalStateException("No loan application exists for either a client or group (or both)."); } + loanApplication.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper, + this.loanRepaymentScheduleTransactionProcessorFactory); - loanApplication.loanApplicationSubmittal(currentUser, loanSchedule, defaultLoanLifecycleStateMachine(), submittedOnDate, externalId); + loanApplication + .loanApplicationSubmittal(currentUser, loanSchedule, defaultLoanLifecycleStateMachine(), submittedOnDate, externalId); return loanApplication; } @@ -158,7 +169,7 @@ public class LoanAssembler { List allowedLoanStatuses = Arrays.asList(LoanStatus.values()); return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses); } - + public CodeValue findCodeValueByIdIfProvided(final Long codeValueId) { CodeValue codeValue = null; if (codeValueId != null) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 52550a3db..7123548fa 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -11,6 +11,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; +import org.joda.time.Days; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.domain.JdbcSupport; @@ -31,6 +32,7 @@ import org.mifosplatform.portfolio.loanaccount.data.DisbursementData; import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanApplicationTimelineData; import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData; +import org.mifosplatform.portfolio.loanaccount.data.LoanSummaryData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData; import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData; import org.mifosplatform.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData; @@ -47,8 +49,10 @@ import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations; import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; @@ -90,11 +94,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { String sql = "select " + rm.loanSchema() + " where l.id = ?"; return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { loanId }); - } catch (EmptyResultDataAccessException e) { throw new LoanNotFoundException(loanId); } - } @Override @@ -104,85 +106,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { try { context.authenticatedUser(); - final DisbursementData disbursement = repaymentScheduleRelatedLoanData.disbursementData(); + final LoanScheduleResultSetExtractor fullResultsetExtractor = new LoanScheduleResultSetExtractor( + repaymentScheduleRelatedLoanData); + final String sql = "select " + fullResultsetExtractor.schema() + " where ls.loan_id = ? order by ls.loan_id, ls.installment"; - final LoanScheduleMapper rm = new LoanScheduleMapper(disbursement); - final String sql = "select " + rm.loanScheduleSchema() + " where l.id = ? order by ls.loan_id, ls.installment"; - - final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod( - disbursement.disbursementDate(), disbursement.amount(), - repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement(), disbursement.isDisbursed()); - - final Collection repaymentSchedulePeriods = this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); - - final Collection periods = new ArrayList(repaymentSchedulePeriods.size() + 1); - periods.add(disbursementPeriod); - periods.addAll(repaymentSchedulePeriods); - - LoanSchedulePeriodDataWrapper wrapper = new LoanSchedulePeriodDataWrapper(periods); - - final Integer loanTermInDays = wrapper.deriveCumulativeLoanTermInDays(); - - final BigDecimal cumulativePrincipalDisbursed = wrapper.deriveCumulativePrincipalDisbursed(); - final BigDecimal cumulativePrincipalDue = wrapper.deriveCumulativePrincipalDue(); - final BigDecimal cumulativePrincipalPaid = wrapper.deriveCumulativePrincipalPaid(); - final BigDecimal cumulativePrincipalWrittenOff = wrapper.deriveCumulativePrincipalWrittenOff(); - final BigDecimal cumulativePrincipalOutstanding = wrapper.deriveCumulativePrincipalOutstanding(); - - final BigDecimal cumulativeInterestExpected = wrapper.deriveCumulativeInterestExpected(); - final BigDecimal cumulativeInterestPaid = wrapper.deriveCumulativeInterestPaid(); - final BigDecimal cumulativeInterestWaived = wrapper.deriveCumulativeInterestWaived(); - final BigDecimal cumulativeInterestWrittenOff = wrapper.deriveCumulativeInterestWrittenOff(); - final BigDecimal cumulativeInterestOutstanding = wrapper.deriveCumulativeInterestOutstanding(); - - final BigDecimal cumulativeFeeChargesExpected = wrapper.deriveCumulativeFeeChargesToDate(); - final BigDecimal cumulativeFeeChargesPaid = wrapper.deriveCumulativeFeeChargesPaid(); - final BigDecimal cumulativeFeeChargesWaived = wrapper.deriveCumulativeFeeChargesWaived(); - final BigDecimal cumulativeFeeChargesWrittenOff = wrapper.deriveCumulativeFeeChargesWrittenOff(); - final BigDecimal cumulativeFeeChargesOutstanding = wrapper.deriveCumulativeFeeChargesOutstanding(); - - final BigDecimal cumulativePenaltyChargesExpected = wrapper.deriveCumulativePenaltyChargesToDate(); - final BigDecimal cumulativePenaltyChargesPaid = wrapper.deriveCumulativePenaltyChargesPaid(); - final BigDecimal cumulativePenaltyChargesWaived = wrapper.deriveCumulativePenaltyChargesWaived(); - final BigDecimal cumulativePenaltyChargesWrittenOff = wrapper.deriveCumulativePenaltyChargesWrittenOff(); - final BigDecimal cumulativePenaltyChargesOutstanding = wrapper.deriveCumulativePenaltyChargesOutstanding(); - - final BigDecimal totalExpectedCostOfLoan = cumulativeInterestExpected.add(cumulativeFeeChargesExpected).add( - cumulativePenaltyChargesExpected); - final BigDecimal totalExpectedRepayment = cumulativePrincipalDisbursed.add(totalExpectedCostOfLoan); - - final BigDecimal totalPaidToDate = cumulativePrincipalPaid.add(cumulativeInterestPaid).add(cumulativeFeeChargesPaid) - .add(cumulativePenaltyChargesPaid); - final BigDecimal totalWaivedToDate = cumulativeInterestWaived.add(cumulativeFeeChargesWaived).add( - cumulativePenaltyChargesWaived); - final BigDecimal totalWrittenOffToDate = cumulativePrincipalWrittenOff.add(cumulativeInterestWrittenOff) - .add(cumulativeFeeChargesWrittenOff).add(cumulativePenaltyChargesWrittenOff); - - final BigDecimal totalOutstanding = cumulativePrincipalOutstanding.add(cumulativeInterestOutstanding) - .add(cumulativeFeeChargesOutstanding).add(cumulativePenaltyChargesOutstanding); - - final BigDecimal totalOverdue = wrapper.deriveCumulativeTotalOverdue(); - - final CurrencyData currency = repaymentScheduleRelatedLoanData.getCurrency(); - final MonetaryCurrency monetaryCurrency = new MonetaryCurrency(currency.code(), currency.decimalPlaces()); - final Money tolerance = Money.of(monetaryCurrency, repaymentScheduleRelatedLoanData.getInArrearsTolerance()); - final Money totalOverdueMoney = Money.of(monetaryCurrency, totalOverdue); - boolean isWaiveAllowed = totalOverdueMoney.isGreaterThanZero() - && (tolerance.isGreaterThan(totalOverdueMoney) || tolerance.isEqualTo(totalOverdueMoney)); - - BigDecimal totalInArrears = null; - if (!isWaiveAllowed) { - totalInArrears = totalOverdueMoney.getAmount(); - } - - return new LoanScheduleData(currency, periods, loanTermInDays, cumulativePrincipalDisbursed, cumulativePrincipalDue, - cumulativePrincipalPaid, cumulativePrincipalWrittenOff, cumulativePrincipalOutstanding, cumulativeInterestExpected, - cumulativeInterestPaid, cumulativeInterestWaived, cumulativeInterestWrittenOff, cumulativeInterestOutstanding, - cumulativeFeeChargesExpected, cumulativeFeeChargesPaid, cumulativeFeeChargesWaived, cumulativeFeeChargesWrittenOff, - cumulativeFeeChargesOutstanding, cumulativePenaltyChargesExpected, cumulativePenaltyChargesPaid, - cumulativePenaltyChargesWaived, cumulativePenaltyChargesWrittenOff, cumulativePenaltyChargesOutstanding, - totalExpectedCostOfLoan, totalExpectedRepayment, totalPaidToDate, totalWaivedToDate, totalWrittenOffToDate, - totalOutstanding, totalInArrears); + return this.jdbcTemplate.query(sql, fullResultsetExtractor, new Object[] { loanId }); } catch (EmptyResultDataAccessException e) { throw new LoanNotFoundException(loanId); } @@ -342,9 +270,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.approvedon_date as approvedOnDate, abu.username as approvedByUsername, abu.firstname as approvedByFirstname, abu.lastname as approvedByLastname," + " l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, dbu.username as disbursedByUsername, dbu.firstname as disbursedByFirstname, dbu.lastname as disbursedByLastname," + " l.closedon_date as closedOnDate, cbu.username as closedByUsername, cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname," - + " l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate, l.interest_calculated_from_date as interestChargedFromDate, l.expected_maturedon_date as expectedMaturityDate, " - + " l.total_charges_due_at_disbursement_derived as totalDisbursementCharges," + " l.principal_amount as principal, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery," + " l.nominal_interest_rate_per_period as interestRatePerPeriod, l.annual_nominal_interest_rate as annualInterestRate, " + " l.repayment_period_frequency_enum as repaymentFrequencyType, l.interest_period_frequency_enum as interestRateFrequencyType, " @@ -352,10 +278,47 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.amortization_method_enum as amortizationType, l.interest_method_enum as interestType, l.interest_calculated_in_period_enum as interestCalculationPeriodType," + " l.loan_status_id as lifeCycleStatusId, l.loan_transaction_strategy_id as transactionStrategyId, " + " l.currency_code as currencyCode, l.currency_digits as currencyDigits, rc.`name` as currencyName, rc.display_symbol as currencyDisplaySymbol, rc.internationalized_name_code as currencyNameCode, " - + " l.loan_officer_id as loanOfficerId, s.display_name as loanOfficerName" + " from m_loan l" - + " left join m_client c on c.id = l.client_id" + " left join m_group g on g.id = l.group_id" - + " join m_product_loan lp on lp.id = l.product_id" + " join m_currency rc on rc.`code` = l.currency_code" - + " left join m_fund f on f.id = l.fund_id" + " left join m_staff s on s.id = l.loan_officer_id" + + " l.loan_officer_id as loanOfficerId, s.display_name as loanOfficerName, " + + " l.principal_disbursed_derived as principalDisbursed," + + " l.principal_repaid_derived as principalPaid," + + " l.principal_writtenoff_derived as principalWrittenOff," + + " l.principal_outstanding_derived as principalOutstanding," + + " l.principal_overdue_derived as principalOverdue," + + " l.interest_charged_derived as interestCharged," + + " l.interest_repaid_derived as interestPaid," + + " l.interest_waived_derived as interestWaived," + + " l.interest_writtenoff_derived as interestWrittenOff," + + " l.interest_outstanding_derived as interestOutstanding," + + " l.interest_overdue_derived as interestOverdue," + + " l.fee_charges_charged_derived as feeChargesCharged," + + " l.total_charges_due_at_disbursement_derived as feeChargesDueAtDisbursementCharged," + + " l.fee_charges_repaid_derived as feeChargesPaid," + + " l.fee_charges_waived_derived as feeChargesWaived," + + " l.fee_charges_writtenoff_derived as feeChargesWrittenOff," + + " l.fee_charges_outstanding_derived as feeChargesOutstanding," + + " l.fee_charges_overdue_derived as feeChargesOverdue," + + " l.penalty_charges_charged_derived as penaltyChargesCharged," + + " l.penalty_charges_repaid_derived as penaltyChargesPaid," + + " l.penalty_charges_waived_derived as penaltyChargesWaived," + + " l.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff," + + " l.penalty_charges_outstanding_derived as penaltyChargesOutstanding," + + " l.penalty_charges_overdue_derived as penaltyChargesOverdue," + + " l.total_expected_repayment_derived as totalExpectedRepayment," + + " l.total_repayment_derived as totalRepayment," + + " l.total_expected_costofloan_derived as totalExpectedCostOfLoan," + + " l.total_costofloan_derived as totalCostOfLoan," + + " l.total_waived_derived as totalWaived," + + " l.total_writtenoff_derived as totalWrittenOff," + + " l.total_outstanding_derived as totalOutstanding," + + " l.total_overdue_derived as totalOverdue," + + " l.overdue_since_date_derived as overdueSinceDate" + + " from m_loan l" // + + " left join m_client c on c.id = l.client_id" // + + " left join m_group g on g.id = l.group_id" // + + " join m_product_loan lp on lp.id = l.product_id" // + + " join m_currency rc on rc.`code` = l.currency_code" // + + " left join m_fund f on f.id = l.fund_id" // + + " left join m_staff s on s.id = l.loan_officer_id" // + " left join m_appuser sbu on sbu.id = l.submittedon_userid" + " left join m_appuser rbu on rbu.id = l.rejectedon_userid" + " left join m_appuser wbu on wbu.id = l.withdrawnon_userid" @@ -443,7 +406,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final BigDecimal principal = rs.getBigDecimal("principal"); final BigDecimal inArrearsTolerance = rs.getBigDecimal("inArrearsTolerance"); - final BigDecimal totalFeeChargesAtDisbursement = rs.getBigDecimal("totalDisbursementCharges"); final Integer numberOfRepayments = JdbcSupport.getInteger(rs, "numberOfRepayments"); final Integer repaymentEvery = JdbcSupport.getInteger(rs, "repaymentEvery"); @@ -478,106 +440,212 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final LocalDate expectedFirstRepaymentOnDate = JdbcSupport.getLocalDate(rs, "expectedFirstRepaymentOnDate"); final LocalDate interestChargedFromDate = JdbcSupport.getLocalDate(rs, "interestChargedFromDate"); + final BigDecimal feeChargesDueAtDisbursementCharged = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, + "feeChargesDueAtDisbursementCharged"); + LoanSummaryData loanSummary = null; + if (status.id().intValue() >= 300) { + + // loan summary + final BigDecimal principalDisbursed = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDisbursed"); + final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid"); + final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff"); + final BigDecimal principalOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalOutstanding"); + final BigDecimal principalOverdue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalOverdue"); + + final BigDecimal interestCharged = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestCharged"); + final BigDecimal interestPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestPaid"); + final BigDecimal interestWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWaived"); + final BigDecimal interestWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWrittenOff"); + final BigDecimal interestOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestOutstanding"); + final BigDecimal interestOverdue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestOverdue"); + + final BigDecimal feeChargesCharged = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesCharged"); + final BigDecimal feeChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesPaid"); + final BigDecimal feeChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWaived"); + final BigDecimal feeChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWrittenOff"); + final BigDecimal feeChargesOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesOutstanding"); + final BigDecimal feeChargesOverdue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesOverdue"); + + final BigDecimal penaltyChargesCharged = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesCharged"); + final BigDecimal penaltyChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesPaid"); + final BigDecimal penaltyChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWaived"); + final BigDecimal penaltyChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWrittenOff"); + final BigDecimal penaltyChargesOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesOutstanding"); + final BigDecimal penaltyChargesOverdue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesOverdue"); + + final BigDecimal totalExpectedRepayment = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalExpectedRepayment"); + final BigDecimal totalRepayment = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalRepayment"); + final BigDecimal totalExpectedCostOfLoan = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalExpectedCostOfLoan"); + final BigDecimal totalCostOfLoan = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalCostOfLoan"); + final BigDecimal totalWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalWaived"); + final BigDecimal totalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalWrittenOff"); + final BigDecimal totalOutstanding = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalOutstanding"); + final BigDecimal totalOverdue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalOverdue"); + + final LocalDate overdueSinceDate = JdbcSupport.getLocalDate(rs, "overdueSinceDate"); + + loanSummary = new LoanSummaryData(currencyData, principalDisbursed, principalPaid, principalWrittenOff, + principalOutstanding, principalOverdue, interestCharged, interestPaid, interestWaived, interestWrittenOff, + interestOutstanding, interestOverdue, feeChargesCharged, feeChargesDueAtDisbursementCharged, feeChargesPaid, + feeChargesWaived, feeChargesWrittenOff, feeChargesOutstanding, feeChargesOverdue, penaltyChargesCharged, + penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, penaltyChargesOutstanding, + penaltyChargesOverdue, totalExpectedRepayment, totalRepayment, totalExpectedCostOfLoan, totalCostOfLoan, + totalWaived, totalWrittenOff, totalOutstanding, totalOverdue, overdueSinceDate); + } + return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupId, groupName, groupOfficeId, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, - interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, - totalFeeChargesAtDisbursement); + interestCalculationPeriodType, expectedFirstRepaymentOnDate, interestChargedFromDate, timeline, loanSummary, + feeChargesDueAtDisbursementCharged); } } - private static final class LoanScheduleMapper implements RowMapper { + private static final class LoanScheduleResultSetExtractor implements ResultSetExtractor { + private final CurrencyData currency; + private final DisbursementData disbursement; + private final BigDecimal totalFeeChargesDueAtDisbursement; private LocalDate lastDueDate; private BigDecimal outstandingLoanPrincipalBalance; - public LoanScheduleMapper(final DisbursementData disbursement) { + public LoanScheduleResultSetExtractor(final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData) { + this.currency = repaymentScheduleRelatedLoanData.getCurrency(); + this.disbursement = repaymentScheduleRelatedLoanData.disbursementData(); + this.totalFeeChargesDueAtDisbursement = repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement(); this.lastDueDate = disbursement.disbursementDate(); this.outstandingLoanPrincipalBalance = disbursement.amount(); } - public String loanScheduleSchema() { + public String schema() { return " ls.loan_id as loanId, ls.installment as period, ls.fromdate as fromDate, ls.duedate as dueDate, " + " ls.principal_amount as principalDue, ls.principal_completed_derived as principalPaid, ls.principal_writtenoff_derived as principalWrittenOff, " + " ls.interest_amount as interestDue, ls.interest_completed_derived as interestPaid, ls.interest_waived_derived as interestWaived, ls.interest_writtenoff_derived as interestWrittenOff, " + " ls.fee_charges_amount as feeChargesDue, ls.fee_charges_completed_derived as feeChargesPaid, ls.fee_charges_waived_derived as feeChargesWaived, ls.fee_charges_writtenoff_derived as feeChargesWrittenOff, " + " ls.penalty_charges_amount as penaltyChargesDue, ls.penalty_charges_completed_derived as penaltyChargesPaid, ls.penalty_charges_waived_derived as penaltyChargesWaived, ls.penalty_charges_writtenoff_derived as penaltyChargesWrittenOff " - + " from m_loan l " + " join m_loan_repayment_schedule ls on ls.loan_id = l.id "; + + " from m_loan_repayment_schedule ls "; } @Override - public LoanSchedulePeriodData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException { + public LoanScheduleData extractData(final ResultSet rs) throws SQLException, DataAccessException { - final Long loanId = rs.getLong("loanId"); - final Integer period = JdbcSupport.getInteger(rs, "period"); - LocalDate fromDate = JdbcSupport.getLocalDate(rs, "fromDate"); - final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate"); - final BigDecimal principalDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDue"); - final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid"); - final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff"); + final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod( + this.disbursement.disbursementDate(), this.disbursement.amount(), this.totalFeeChargesDueAtDisbursement, + this.disbursement.isDisbursed()); - // TODO - KW - rather than calculate this here should we put - // calculation on derived column on table like other columns? - final BigDecimal principalOutstanding = principalDue.subtract(principalPaid).subtract(principalWrittenOff); + final Collection periods = new ArrayList(); + periods.add(disbursementPeriod); - final BigDecimal interestExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestDue"); - final BigDecimal interestPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestPaid"); - final BigDecimal interestWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWaived"); - final BigDecimal interestWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWrittenOff"); + final MonetaryCurrency monCurrency = new MonetaryCurrency(this.currency.code(), this.currency.decimalPlaces()); + final BigDecimal totalPrincipalDisbursed = Money.of(monCurrency, this.disbursement.amount()).getAmount(); + Money totalPrincipalExpected = Money.zero(monCurrency); + Money totalPrincipalPaid = Money.zero(monCurrency); + Money totalInterestCharged = Money.zero(monCurrency); + Money totalFeeChargesCharged = Money.zero(monCurrency); + Money totalPenaltyChargesCharged = Money.zero(monCurrency); + Money totalWaived = Money.zero(monCurrency); + Money totalWrittenOff = Money.zero(monCurrency); + Money totalRepaymentExpected = Money.zero(monCurrency); + Money totalRepayment = Money.zero(monCurrency); + Money totalOutstanding = Money.zero(monCurrency); - // TODO - KW - rather than calculate this here should we put - // calculation on derived column on table like other columns? - final BigDecimal interestActualDue = interestExpectedDue.subtract(interestWaived).subtract(interestWrittenOff); - final BigDecimal interestOutstanding = interestActualDue.subtract(interestPaid); + Integer loanTermInDays = Integer.valueOf(0); + while (rs.next()) { - final BigDecimal feeChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesDue"); - final BigDecimal feeChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesPaid"); - final BigDecimal feeChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWaived"); - final BigDecimal feeChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWrittenOff"); + final Long loanId = rs.getLong("loanId"); + final Integer period = JdbcSupport.getInteger(rs, "period"); + LocalDate fromDate = JdbcSupport.getLocalDate(rs, "fromDate"); + final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate"); - final BigDecimal feeChargesActualDue = feeChargesExpectedDue.subtract(feeChargesWaived).subtract(feeChargesWrittenOff); - final BigDecimal feeChargesOutstanding = feeChargesActualDue.subtract(feeChargesPaid); + Integer daysInPeriod = Integer.valueOf(0); + if (fromDate != null) { + daysInPeriod = Days.daysBetween(fromDate, dueDate).getDays(); + loanTermInDays = Integer.valueOf(loanTermInDays.intValue() + daysInPeriod.intValue()); + } - final BigDecimal penaltyChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesDue"); - final BigDecimal penaltyChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesPaid"); - final BigDecimal penaltyChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWaived"); - final BigDecimal penaltyChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWrittenOff"); + final BigDecimal principalDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDue"); + totalPrincipalExpected = totalPrincipalExpected.plus(principalDue); + final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid"); + totalPrincipalPaid = totalPrincipalPaid.plus(principalPaid); + final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff"); - final BigDecimal penaltyChargesActualDue = penaltyChargesExpectedDue.subtract(penaltyChargesWaived).subtract( - penaltyChargesWrittenOff); - final BigDecimal penaltyChargesOutstanding = penaltyChargesActualDue.subtract(penaltyChargesPaid); + final BigDecimal principalOutstanding = principalDue.subtract(principalPaid).subtract(principalWrittenOff); - final BigDecimal totalExpectedCostOfLoanForPeriod = interestExpectedDue.add(feeChargesExpectedDue).add( - penaltyChargesExpectedDue); + final BigDecimal interestExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestDue"); + totalInterestCharged = totalInterestCharged.plus(interestExpectedDue); + final BigDecimal interestPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestPaid"); + final BigDecimal interestWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWaived"); + final BigDecimal interestWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWrittenOff"); - final BigDecimal totalDueForPeriod = principalDue.add(totalExpectedCostOfLoanForPeriod); - final BigDecimal totalPaidForPeriod = principalPaid.add(interestPaid).add(feeChargesPaid).add(penaltyChargesPaid); - final BigDecimal totalWaivedForPeriod = interestWaived.add(feeChargesWaived).add(penaltyChargesWaived); - final BigDecimal totalWrittenOffForPeriod = principalWrittenOff.add(interestWrittenOff).add(feeChargesWrittenOff) - .add(penaltyChargesWrittenOff); - final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding) - .add(penaltyChargesOutstanding); + final BigDecimal interestActualDue = interestExpectedDue.subtract(interestWaived).subtract(interestWrittenOff); + final BigDecimal interestOutstanding = interestActualDue.subtract(interestPaid); - final BigDecimal totalActualCostOfLoanForPeriod = interestActualDue.add(feeChargesActualDue).add(penaltyChargesActualDue); + final BigDecimal feeChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesDue"); + totalFeeChargesCharged = totalFeeChargesCharged.plus(feeChargesExpectedDue); + final BigDecimal feeChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesPaid"); + final BigDecimal feeChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWaived"); + final BigDecimal feeChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWrittenOff"); - if (fromDate == null) { - fromDate = this.lastDueDate; + final BigDecimal feeChargesActualDue = feeChargesExpectedDue.subtract(feeChargesWaived).subtract(feeChargesWrittenOff); + final BigDecimal feeChargesOutstanding = feeChargesActualDue.subtract(feeChargesPaid); + + final BigDecimal penaltyChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesDue"); + totalPenaltyChargesCharged = totalPenaltyChargesCharged.plus(penaltyChargesExpectedDue); + final BigDecimal penaltyChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesPaid"); + final BigDecimal penaltyChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWaived"); + final BigDecimal penaltyChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWrittenOff"); + + final BigDecimal penaltyChargesActualDue = penaltyChargesExpectedDue.subtract(penaltyChargesWaived).subtract( + penaltyChargesWrittenOff); + final BigDecimal penaltyChargesOutstanding = penaltyChargesActualDue.subtract(penaltyChargesPaid); + + final BigDecimal totalExpectedCostOfLoanForPeriod = interestExpectedDue.add(feeChargesExpectedDue).add( + penaltyChargesExpectedDue); + + final BigDecimal totalDueForPeriod = principalDue.add(totalExpectedCostOfLoanForPeriod); + final BigDecimal totalPaidForPeriod = principalPaid.add(interestPaid).add(feeChargesPaid).add(penaltyChargesPaid); + final BigDecimal totalWaivedForPeriod = interestWaived.add(feeChargesWaived).add(penaltyChargesWaived); + totalWaived = totalWaived.plus(totalWaivedForPeriod); + final BigDecimal totalWrittenOffForPeriod = principalWrittenOff.add(interestWrittenOff).add(feeChargesWrittenOff) + .add(penaltyChargesWrittenOff); + totalWrittenOff = totalWrittenOff.plus(totalWrittenOffForPeriod); + final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding) + .add(penaltyChargesOutstanding); + + final BigDecimal totalActualCostOfLoanForPeriod = interestActualDue.add(feeChargesActualDue).add(penaltyChargesActualDue); + + totalRepaymentExpected = totalRepaymentExpected.plus(totalDueForPeriod); + totalRepayment = totalRepayment.plus(totalPaidForPeriod); + totalOutstanding = totalOutstanding.plus(totalOutstandingForPeriod); + + if (fromDate == null) { + fromDate = this.lastDueDate; + } + final BigDecimal outstandingPrincipleBalanceOfLoan = outstandingLoanPrincipalBalance.subtract(principalDue); + + // update based on current period values + this.lastDueDate = dueDate; + outstandingLoanPrincipalBalance = outstandingLoanPrincipalBalance.subtract(principalDue); + + final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.repaymentPeriodWithPayments(loanId, period, fromDate, + dueDate, principalDue, principalPaid, principalWrittenOff, principalOutstanding, outstandingPrincipleBalanceOfLoan, + interestExpectedDue, interestPaid, interestWaived, interestWrittenOff, interestOutstanding, feeChargesExpectedDue, + feeChargesPaid, feeChargesWaived, feeChargesWrittenOff, feeChargesOutstanding, penaltyChargesExpectedDue, + penaltyChargesPaid, penaltyChargesWaived, penaltyChargesWrittenOff, penaltyChargesOutstanding, totalDueForPeriod, + totalPaidForPeriod, totalWaivedForPeriod, totalWrittenOffForPeriod, totalOutstandingForPeriod, + totalActualCostOfLoanForPeriod); + + periods.add(periodData); } - final BigDecimal outstandingPrincipleBalanceOfLoan = outstandingLoanPrincipalBalance.subtract(principalDue); - // update based on current period values - this.lastDueDate = dueDate; - outstandingLoanPrincipalBalance = outstandingLoanPrincipalBalance.subtract(principalDue); - - return LoanSchedulePeriodData.repaymentPeriodWithPayments(loanId, period, fromDate, dueDate, principalDue, principalPaid, - principalWrittenOff, principalOutstanding, outstandingPrincipleBalanceOfLoan, interestExpectedDue, interestPaid, - interestWaived, interestWrittenOff, interestOutstanding, feeChargesExpectedDue, feeChargesPaid, feeChargesWaived, - feeChargesWrittenOff, feeChargesOutstanding, penaltyChargesExpectedDue, penaltyChargesPaid, penaltyChargesWaived, - penaltyChargesWrittenOff, penaltyChargesOutstanding, totalDueForPeriod, totalPaidForPeriod, totalWaivedForPeriod, - totalWrittenOffForPeriod, totalOutstandingForPeriod, totalActualCostOfLoanForPeriod); + return new LoanScheduleData(this.currency, periods, loanTermInDays, totalPrincipalDisbursed, + totalPrincipalExpected.getAmount(), totalPrincipalPaid.getAmount(), totalInterestCharged.getAmount(), + totalFeeChargesCharged.getAmount(), totalPenaltyChargesCharged.getAmount(), totalWaived.getAmount(), + totalWrittenOff.getAmount(), totalRepaymentExpected.getAmount(), totalRepayment.getAmount(), + totalOutstanding.getAmount()); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanSchedulePeriodDataWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanSchedulePeriodDataWrapper.java deleted file mode 100644 index e6ddb032a..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanSchedulePeriodDataWrapper.java +++ /dev/null @@ -1,198 +0,0 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package org.mifosplatform.portfolio.loanaccount.service; - -import java.math.BigDecimal; -import java.util.Collection; - -import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData; - -public class LoanSchedulePeriodDataWrapper { - - private final Collection periods; - - public LoanSchedulePeriodDataWrapper(final Collection periods) { - this.periods = periods; - } - - public BigDecimal deriveCumulativePrincipalDisbursed() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.principalDisbursed()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePrincipalDue() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.principalDue()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePrincipalPaid() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.principalPaid()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePrincipalWrittenOff() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.principalWrittenOff()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePrincipalOutstanding() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.principalOutstanding()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeInterestExpected() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.interestDue()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeInterestPaid() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.interestPaid()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeInterestWaived() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.interestWaived()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeInterestWrittenOff() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.interestWrittenOff()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeInterestOutstanding() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.interestOutstanding()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeFeeChargesToDate() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.feeChargesDue()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeFeeChargesPaid() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.feeChargesPaid()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeFeeChargesWaived() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.feeChargesWaived()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeFeeChargesWrittenOff() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.feeChargesWrittenOff()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeFeeChargesOutstanding() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.feeChargesOutstanding()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePenaltyChargesToDate() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.penaltyChargesDue()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePenaltyChargesPaid() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.penaltyChargesPaid()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePenaltyChargesWaived() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.penaltyChargesWaived()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePenaltyChargesWrittenOff() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.penaltyChargesWrittenOff()); - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativePenaltyChargesOutstanding() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.penaltyChargesOutstanding()); - } - return cumulativeValue; - } - - public Integer deriveCumulativeLoanTermInDays() { - Integer cumulativeValue = Integer.valueOf(0); - for (LoanSchedulePeriodData period : this.periods) { - if (period.daysInPeriod() != null) { - cumulativeValue += period.daysInPeriod(); - } - } - return cumulativeValue; - } - - public BigDecimal deriveCumulativeTotalOverdue() { - BigDecimal cumulativeValue = BigDecimal.ZERO; - for (LoanSchedulePeriodData period : this.periods) { - cumulativeValue = cumulativeValue.add(period.totalOverdue()); - } - return cumulativeValue; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 85dbee061..5481d1b6f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -33,8 +33,10 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge; import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanLifecycleStateMachine; +import org.mifosplatform.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; +import org.mifosplatform.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionRepository; import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException; @@ -63,6 +65,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final LoanChargeRepository loanChargeRepository; private final ApplicationCurrencyRepository applicationCurrencyRepository; private final JournalEntryWritePlatformService journalEntryWritePlatformService; + private final LoanSummaryWrapper loanSummaryWrapper; + private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -70,9 +74,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, final LoanAssembler loanAssembler, final LoanRepository loanRepository, final LoanTransactionRepository loanTransactionRepository, final NoteRepository noteRepository, final ChargeRepositoryWrapper chargeRepository, - final LoanChargeRepository loanChargeRepository, - final ApplicationCurrencyRepository applicationCurrencyRepository, - final JournalEntryWritePlatformService journalEntryWritePlatformService) { + final LoanChargeRepository loanChargeRepository, final ApplicationCurrencyRepository applicationCurrencyRepository, + final JournalEntryWritePlatformService journalEntryWritePlatformService, final LoanSummaryWrapper loanSummaryWrapper, + final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; this.loanAssembler = loanAssembler; @@ -84,6 +88,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.applicationCurrencyRepository = applicationCurrencyRepository; this.journalEntryWritePlatformService = journalEntryWritePlatformService; this.loanUpdateCommandFromApiJsonDeserializer = loanUpdateCommandFromApiJsonDeserializer; + this.loanSummaryWrapper = loanSummaryWrapper; + this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -105,8 +111,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingTransactionIds = new ArrayList(); final List existingReversedTransactionIds = new ArrayList(); - final Map changes = loan.disburse(currentUser, command, defaultLoanLifecycleStateMachine(), currency, - existingTransactionIds, existingReversedTransactionIds); + final Map changes = loan.disburse(currentUser, command, currency, existingTransactionIds, + existingReversedTransactionIds); if (!changes.isEmpty()) { this.loanRepository.save(loan); @@ -142,8 +148,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingTransactionIds = new ArrayList(); final List existingReversedTransactionIds = new ArrayList(); - final Map changes = loan.undoDisbursal(defaultLoanLifecycleStateMachine(), existingTransactionIds, - existingReversedTransactionIds); + final Map changes = loan.undoDisbursal(existingTransactionIds, existingReversedTransactionIds); if (!changes.isEmpty()) { this.loanRepository.save(loan); @@ -576,6 +581,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private Loan retrieveLoanBy(final Long loanId) { final Loan loan = this.loanRepository.findOne(loanId); if (loan == null) { throw new LoanNotFoundException(loanId); } + loan.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper, this.loanRepaymentScheduleTransactionProcessorFactory); return loan; }