merging conflicts for 1.8.0 RELEASE
This commit is contained in:
+1422
-74
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
INSERT INTO `stretchy_report` (`report_name`, `report_type`, `report_subtype`, `report_category`, `report_sql`, `description`, `core_report`, `use_report`) VALUES ('GroupSavingSummary', 'Table', NULL, NULL, 'select ifnull(cur.display_symbol, sa.currency_code) as currency,\ncount(sa.id) as totalSavingAccounts, ifnull(sum(sa.account_balance_derived),0) as totalSavings\nfrom m_group topgroup\njoin m_office o on o.id = topgroup.office_id and o.hierarchy like concat(\'${currentUserHierarchy}\', \'%\')\njoin m_group g on g.hierarchy like concat(topgroup.hierarchy, \'%\')\njoin m_savings_account sa on sa.group_id = g.id\nleft join m_currency cur on cur.code = sa.currency_code\nwhere topgroup.id = ${groupId}\nand sa.activatedon_date is not null\ngroup by sa.currency_code', 'Utility query for getting group or center saving summary details for a group_id', 1, 0);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `m_savings_account_transfer`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL DEFAULT NULL AFTER `currency_digits`;
|
||||
@@ -0,0 +1,30 @@
|
||||
CREATE TABLE `m_meeting` (
|
||||
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
`calendar_instance_id` BIGINT(20) NOT NULL,
|
||||
`meeting_date` DATE NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `unique_calendar_instance_id_meeting_date` (`calendar_instance_id`, `meeting_date`),
|
||||
CONSTRAINT `FK_m_calendar_instance_m_meeting` FOREIGN KEY (`calendar_instance_id`) REFERENCES `m_calendar_instance` (`id`)
|
||||
)
|
||||
COLLATE='latin1_swedish_ci'
|
||||
ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE `m_client_attendance` (
|
||||
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
|
||||
`client_id` BIGINT(20) NOT NULL DEFAULT '0',
|
||||
`meeting_id` BIGINT(20) NOT NULL,
|
||||
`attendance_type_enum` SMALLINT(5) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `unique_client_meeting_attendance` (`client_id`, `meeting_id`),
|
||||
INDEX `FK_m_meeting_m_client_attendance` (`meeting_id`),
|
||||
CONSTRAINT `FK_m_client_m_client_attendance` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FK_m_meeting_m_client_attendance` FOREIGN KEY (`meeting_id`) REFERENCES `m_meeting` (`id`)
|
||||
)
|
||||
COLLATE='utf8_general_ci'
|
||||
ENGINE=InnoDB;
|
||||
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'CREATE_MEETING', 'MEETING', 'CREATE', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'UPDATE_MEETING', 'MEETING', 'UPDATE', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'DELETE_MEETING', 'MEETING', 'DELETE', 0);
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('portfolio', 'SAVEORUPDATEATTENDANCE_MEETING', 'MEETING', 'SAVEORUPDATEATTENDANCE', 0);
|
||||
@@ -0,0 +1,14 @@
|
||||
ALTER TABLE `job`
|
||||
ADD COLUMN `is_misfired` TINYINT(1) NOT NULL DEFAULT '0' AFTER `scheduler_group`;
|
||||
|
||||
CREATE TABLE `scheduler_detail` (
|
||||
`id` SMALLINT(2) NOT NULL AUTO_INCREMENT,
|
||||
`is_suspended` TINYINT(1) NOT NULL DEFAULT '0',
|
||||
`execute_misfired_jobs` TINYINT(1) NOT NULL DEFAULT '1',
|
||||
`reset_scheduler_on_bootup` TINYINT(1) NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`id`)
|
||||
)
|
||||
COLLATE='utf8_general_ci'
|
||||
ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO `scheduler_detail` (`is_suspended`, `execute_misfired_jobs`, `reset_scheduler_on_bootup`) VALUES (FALSE,TRUE,TRUE);
|
||||
@@ -0,0 +1,11 @@
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('portfolio_group', 'TRANSFERCLIENTS_GROUP', 'GROUP', 'TRANSFERCLIENTS', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('portfolio_group', 'TRANSFERCLIENTS_GROUP_CHECKER', 'GROUP', 'TRANSFERCLIENTS', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('portfolio', 'TRANSFER_CLIENT', 'CLIENT', 'TRANSFER', 0);
|
||||
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||
VALUES ('portfolio', 'TRANSFER_CLIENT_CHECKER', 'CLIENT', 'TRANSFER', 0);
|
||||
@@ -0,0 +1,2 @@
|
||||
INSERT INTO `m_permission` (grouping,code,`entity_name`,`action_name`,`can_maker_checker`)
|
||||
values('portfolio_group','ASSIGNSTAFF_GROUP','GROUP','ASSIGNSTAFF',0);
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE m_loan_transaction
|
||||
ADD COLUMN `external_id` VARCHAR(100) NULL DEFAULT NULL AFTER `is_reversed` ,
|
||||
ADD UNIQUE INDEX `external_id_UNIQUE` (`external_id` ASC) ;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `account_type_enum` SMALLINT(5) NOT NULL DEFAULT '1' AFTER `status_enum`;
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`) VALUES ('Post Interest For Savings', 'Post Interest For Savings', '0 0 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0);
|
||||
@@ -0,0 +1,56 @@
|
||||
INSERT INTO `m_permission`
|
||||
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`)
|
||||
VALUES
|
||||
('transaction_savings', 'READ_ACCOUNTTRANSFER', 'ACCOUNTTRANSFER', 'READ', 0),
|
||||
('transaction_savings', 'CREATE_ACCOUNTTRANSFER', 'ACCOUNTTRANSFER', 'CREATE', 1),
|
||||
('transaction_savings', 'CREATE_ACCOUNTTRANSFER_CHECKER', 'ACCOUNTTRANSFER', 'CREATE', 0);
|
||||
|
||||
|
||||
DROP TABLE IF EXISTS `m_savings_account_transfer`;
|
||||
|
||||
CREATE TABLE `m_savings_account_transfer` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`from_office_id` bigint(20) NOT NULL,
|
||||
`to_office_id` bigint(20) NOT NULL,
|
||||
`from_client_id` bigint(20) NOT NULL,
|
||||
`to_client_id` bigint(20) NOT NULL,
|
||||
`from_savings_account_id` bigint(20) DEFAULT NULL,
|
||||
`to_savings_account_id` bigint(20) DEFAULT NULL,
|
||||
`from_loan_account_id` bigint(20) DEFAULT NULL,
|
||||
`to_loan_account_id` bigint(20) DEFAULT NULL,
|
||||
`from_savings_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`from_loan_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`to_savings_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`to_loan_transaction_id` bigint(20) DEFAULT NULL,
|
||||
`is_reversed` tinyint(1) NOT NULL,
|
||||
`transaction_date` date NOT NULL,
|
||||
`currency_code` varchar(3) NOT NULL,
|
||||
`currency_digits` smallint(5) NOT NULL,
|
||||
`amount` decimal(19,6) NOT NULL,
|
||||
`description` varchar(200) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FKTRAN000000001` (`from_office_id`),
|
||||
KEY `FKTRAN000000002` (`from_client_id`),
|
||||
KEY `FKTRAN000000003` (`from_savings_account_id`),
|
||||
KEY `FKTRAN000000004` (`to_office_id`),
|
||||
KEY `FKTRAN000000005` (`to_client_id`),
|
||||
KEY `FKTRAN000000006` (`to_savings_account_id`),
|
||||
KEY `FKTRAN000000007` (`to_loan_account_id`),
|
||||
KEY `FKTRAN000000008` (`from_savings_transaction_id`),
|
||||
KEY `FKTRAN000000009` (`to_savings_transaction_id`),
|
||||
KEY `FKTRAN000000010` (`to_loan_transaction_id`),
|
||||
KEY `FKTRAN000000011` (`from_loan_account_id`),
|
||||
KEY `FKTRAN000000012` (`from_loan_transaction_id`),
|
||||
CONSTRAINT `FKTRAN000000001` FOREIGN KEY (`from_office_id`) REFERENCES `m_office` (`id`),
|
||||
CONSTRAINT `FKTRAN000000002` FOREIGN KEY (`from_client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKTRAN000000003` FOREIGN KEY (`from_savings_account_id`) REFERENCES `m_savings_account` (`id`),
|
||||
CONSTRAINT `FKTRAN000000004` FOREIGN KEY (`to_office_id`) REFERENCES `m_office` (`id`),
|
||||
CONSTRAINT `FKTRAN000000005` FOREIGN KEY (`to_client_id`) REFERENCES `m_client` (`id`),
|
||||
CONSTRAINT `FKTRAN000000006` FOREIGN KEY (`to_savings_account_id`) REFERENCES `m_savings_account` (`id`),
|
||||
CONSTRAINT `FKTRAN000000007` FOREIGN KEY (`to_loan_account_id`) REFERENCES `m_loan` (`id`),
|
||||
CONSTRAINT `FKTRAN000000008` FOREIGN KEY (`from_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000009` FOREIGN KEY (`to_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000010` FOREIGN KEY (`to_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`),
|
||||
CONSTRAINT `FKTRAN000000011` FOREIGN KEY (`from_loan_account_id`) REFERENCES `m_loan` (`id`),
|
||||
CONSTRAINT `FKTRAN000000012` FOREIGN KEY (`from_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
@@ -0,0 +1 @@
|
||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('transaction_savings', 'ADJUSTTRANSACTION_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'ADJUSTTRANSACTION', 0);
|
||||
@@ -0,0 +1,12 @@
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_savings_product`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_loan`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_product_loan`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `currency_digits`;
|
||||
ALTER TABLE `m_currency`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `decimal_places`;
|
||||
ALTER TABLE `m_organisation_currency`
|
||||
ADD COLUMN `currency_multiplesof` SMALLINT(5) NULL AFTER `decimal_places`;
|
||||
@@ -1 +1 @@
|
||||
releaseVersion=1.7.2.RELEASE
|
||||
releaseVersion=1.8.0.RELEASE
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package org.mifosplatform.integrationtests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mifosplatform.integrationtests.common.ClientHelper;
|
||||
import org.mifosplatform.integrationtests.common.GroupHelper;
|
||||
import org.mifosplatform.integrationtests.common.Utils;
|
||||
import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder;
|
||||
import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder;
|
||||
import org.mifosplatform.integrationtests.common.loans.LoanTransactionHelper;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.builder.ResponseSpecBuilder;
|
||||
import com.jayway.restassured.http.ContentType;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
import com.jayway.restassured.specification.ResponseSpecification;
|
||||
|
||||
/**
|
||||
* Group Loan Integration Test for checking Loan Application Repayment
|
||||
* Schedule.
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class GroupLoanIntegrationTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private RequestSpecification requestSpec;
|
||||
private LoanTransactionHelper loanTransactionHelper;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Utils.initializeRESTAssured();
|
||||
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkGroupLoanCreateAndDisburseFlow() {
|
||||
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||
|
||||
Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
|
||||
Integer groupID = GroupHelper.createGroup(requestSpec, responseSpec, true);
|
||||
groupID = GroupHelper.associateClient(requestSpec, responseSpec, groupID.toString(),clientID.toString());
|
||||
|
||||
Integer loanProductID = createLoanProduct();
|
||||
Integer loanID = applyForLoanApplication(groupID, loanProductID);
|
||||
ArrayList<HashMap> loanSchedule = loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, loanID);
|
||||
verifyLoanRepaymentSchedule(loanSchedule);
|
||||
|
||||
}
|
||||
|
||||
private Integer createLoanProduct() {
|
||||
System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
||||
String loanProductJSON = new LoanProductTestBuilder() //
|
||||
.withPrincipal("12,000.00") //
|
||||
.withNumberOfRepayments("4") //
|
||||
.withRepaymentAfterEvery("1") //
|
||||
.withRepaymentTypeAsMonth() //
|
||||
.withinterestRatePerPeriod("1") //
|
||||
.withInterestRateFrequencyTypeAsMonths() //
|
||||
.withAmortizationTypeAsEqualInstallments() //
|
||||
.withInterestTypeAsDecliningBalance() //
|
||||
.build();
|
||||
return loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||
}
|
||||
|
||||
private Integer applyForLoanApplication(final Integer groupID, final Integer loanProductID) {
|
||||
System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
|
||||
String loanApplicationJSON = new LoanApplicationTestBuilder() //
|
||||
.withPrincipal("12,000.00") //
|
||||
.withLoanTermFrequency("4") //
|
||||
.withLoanTermFrequencyAsMonths() //
|
||||
.withNumberOfRepayments("4") //
|
||||
.withRepaymentEveryAfter("1") //
|
||||
.withRepaymentFrequencyTypeAsMonths() //
|
||||
.withInterestRatePerPeriod("2") //
|
||||
.withAmortizationTypeAsEqualInstallments() //
|
||||
.withInterestTypeAsDecliningBalance() //
|
||||
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
|
||||
.withExpectedDisbursementDate("20 September 2011") //
|
||||
.withSubmittedOnDate("20 September 2011") //
|
||||
.withLoanType("group")
|
||||
.build(groupID.toString(), loanProductID.toString());
|
||||
System.out.println(loanApplicationJSON);
|
||||
return loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||
}
|
||||
|
||||
private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule) {
|
||||
System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
|
||||
|
||||
assertEquals("Checking for Due Date for 1st Month", new ArrayList<Integer>(Arrays.asList(2011, 10, 20)),
|
||||
loanSchedule.get(1).get("dueDate"));
|
||||
assertEquals("Checking for Principal Due for 1st Month", new Float("2911.49"), loanSchedule.get(1).get("principalOriginalDue"));
|
||||
assertEquals("Checking for Interest Due for 1st Month", new Float("240.00"), loanSchedule.get(1).get("interestOriginalDue"));
|
||||
|
||||
assertEquals("Checking for Due Date for 2nd Month", new ArrayList<Integer>(Arrays.asList(2011, 11, 20)),
|
||||
loanSchedule.get(2).get("dueDate"));
|
||||
assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.71"), loanSchedule.get(2).get("principalDue"));
|
||||
assertEquals("Checking for Interest Due for 2nd Month", new Float("181.77"), loanSchedule.get(2).get("interestOriginalDue"));
|
||||
|
||||
assertEquals("Checking for Due Date for 3rd Month", new ArrayList<Integer>(Arrays.asList(2011, 12, 20)),
|
||||
loanSchedule.get(3).get("dueDate"));
|
||||
assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.1"), loanSchedule.get(3).get("principalDue"));
|
||||
assertEquals("Checking for Interest Due for 3rd Month", new Float("122.38"), loanSchedule.get(3).get("interestOriginalDue"));
|
||||
|
||||
assertEquals("Checking for Due Date for 4th Month", new ArrayList<Integer>(Arrays.asList(2012, 1, 20)),
|
||||
loanSchedule.get(4).get("dueDate"));
|
||||
assertEquals("Checking for Principal Due for 4th Month", new Float("3089.7"), loanSchedule.get(4).get("principalDue"));
|
||||
assertEquals("Checking for Interest Due for 4th Month", new Float("61.79"), loanSchedule.get(4).get("interestOriginalDue"));
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package org.mifosplatform.integrationtests;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mifosplatform.integrationtests.common.ClientHelper;
|
||||
import org.mifosplatform.integrationtests.common.GroupHelper;
|
||||
import org.mifosplatform.integrationtests.common.Utils;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.builder.ResponseSpecBuilder;
|
||||
import com.jayway.restassured.http.ContentType;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
import com.jayway.restassured.specification.ResponseSpecification;
|
||||
|
||||
/**
|
||||
* Group Test for checking Group: Creation, Activation, Client Association,
|
||||
* Updating & Deletion
|
||||
*/
|
||||
public class GroupTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private RequestSpecification requestSpec;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Utils.initializeRESTAssured();
|
||||
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkGroupFunctions() {
|
||||
Integer clientID = ClientHelper.createClient(requestSpec, responseSpec);
|
||||
Integer groupID = GroupHelper.createGroup(requestSpec, responseSpec);
|
||||
GroupHelper.verifyGroupCreatedOnServer(requestSpec, responseSpec, groupID);
|
||||
|
||||
groupID = GroupHelper.activateGroup(requestSpec, responseSpec, groupID.toString());
|
||||
GroupHelper.verifyGroupActivatedOnServer(requestSpec, responseSpec, groupID, true);
|
||||
|
||||
groupID = GroupHelper.associateClient(requestSpec, responseSpec, groupID.toString(), clientID.toString());
|
||||
GroupHelper.verifyGroupMembers(requestSpec, responseSpec, groupID, clientID);
|
||||
|
||||
groupID = GroupHelper.disAssociateClient(requestSpec, responseSpec, groupID.toString(), clientID.toString());
|
||||
GroupHelper.verifyEmptyGroupMembers(requestSpec, responseSpec, groupID);
|
||||
|
||||
String updatedGroupName = GroupHelper.randomNameGenerator("Group-", 5);
|
||||
groupID = GroupHelper.updateGroup(requestSpec, responseSpec, updatedGroupName, groupID.toString());
|
||||
GroupHelper.verifyGroupDetails(requestSpec, responseSpec, groupID, "name", updatedGroupName);
|
||||
|
||||
groupID = GroupHelper.createGroup(requestSpec, responseSpec);
|
||||
GroupHelper.deleteGroup(requestSpec, responseSpec, groupID.toString());
|
||||
GroupHelper.verifyGroupDeleted(requestSpec, responseSpec, groupID);
|
||||
}
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package org.mifosplatform.integrationtests.common;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
import com.jayway.restassured.specification.ResponseSpecification;
|
||||
|
||||
public class GroupHelper {
|
||||
|
||||
private static final String CREATE_GROUP_URL = "/mifosng-provider/api/v1/groups?tenantIdentifier=default";
|
||||
|
||||
public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
@SuppressWarnings("unused") final boolean active) {
|
||||
System.out.println("---------------------------------CREATING A GROUP---------------------------------------------");
|
||||
return createGroup(requestSpec, responseSpec, "04 March 2011");
|
||||
}
|
||||
|
||||
public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String activationDate) {
|
||||
System.out.println("---------------------------------CREATING A GROUP---------------------------------------------");
|
||||
return Utils.performServerPost(requestSpec, responseSpec, CREATE_GROUP_URL, getTestGroupAsJSON(true, activationDate), "groupId");
|
||||
}
|
||||
|
||||
public static Integer createGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
|
||||
System.out.println("---------------------------------CREATING A GROUP---------------------------------------------");
|
||||
return Utils.performServerPost(requestSpec, responseSpec, CREATE_GROUP_URL, getTestGroupAsJSON(false, ""), "groupId");
|
||||
}
|
||||
|
||||
public static Integer associateClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String groupId, final String clientMember) {
|
||||
String GROUP_ASSOCIATE_URL = "/mifosng-provider/api/v1/groups/" + groupId + "?command=associateClients&tenantIdentifier=default";
|
||||
System.out.println("---------------------------------Associate Client To A GROUP---------------------------------------------");
|
||||
return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, associateClientAsJSON(clientMember), "groupId");
|
||||
}
|
||||
|
||||
public static Integer disAssociateClient(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String groupId, final String clientMember) {
|
||||
String GROUP_ASSOCIATE_URL = "/mifosng-provider/api/v1/groups/" + groupId + "?command=disassociateClients&tenantIdentifier=default";
|
||||
System.out.println("---------------------------------Disassociate Client To A GROUP---------------------------------------------");
|
||||
return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, associateClientAsJSON(clientMember), "groupId");
|
||||
}
|
||||
|
||||
public static Integer activateGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String groupId) {
|
||||
String GROUP_ASSOCIATE_URL = "/mifosng-provider/api/v1/groups/" + groupId + "?command=activate&tenantIdentifier=default";
|
||||
System.out.println("---------------------------------Activate A GROUP---------------------------------------------");
|
||||
return Utils.performServerPost(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, activateGroupAsJSON(""), "groupId");
|
||||
}
|
||||
|
||||
public static Integer updateGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String name,
|
||||
final String groupId) {
|
||||
String GROUP_ASSOCIATE_URL = "/mifosng-provider/api/v1/groups/" + groupId + "?tenantIdentifier=default";
|
||||
System.out.println("---------------------------------UPDATE GROUP---------------------------------------------");
|
||||
return Utils.performServerPut(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, updateGroupAsJSON(name), "groupId");
|
||||
}
|
||||
|
||||
public static Integer deleteGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String groupId) {
|
||||
String GROUP_ASSOCIATE_URL = "/mifosng-provider/api/v1/groups/" + groupId + "?tenantIdentifier=default";
|
||||
System.out.println("---------------------------------DELETE GROUP---------------------------------------------");
|
||||
return Utils.performServerDelete(requestSpec, responseSpec, GROUP_ASSOCIATE_URL, "groupId");
|
||||
}
|
||||
|
||||
public static String getTestGroupAsJSON(final boolean active, final String activationDate) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("officeId", "1");
|
||||
map.put("name", randomNameGenerator("Group_Name_", 5));
|
||||
map.put("externalId", randomIDGenerator("ID_", 7));
|
||||
if (active == true) {
|
||||
map.put("active", "true");
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
map.put("locale", "en");
|
||||
map.put("activationDate", activationDate);
|
||||
} else
|
||||
map.put("active", "false");
|
||||
|
||||
System.out.println("map : " + map);
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
public static String associateClientAsJSON(final String clientMember) {
|
||||
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add(clientMember);
|
||||
map.put("clientMembers", list);
|
||||
System.out.println("map : " + map);
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
public static String activateGroupAsJSON(final String activationDate) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
map.put("locale", "en");
|
||||
if (activationDate != "")
|
||||
map.put("activationDate", activationDate);
|
||||
else
|
||||
map.put("activationDate", "04 March 2011");
|
||||
System.out.println("map : " + map);
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
public static String updateGroupAsJSON(final String name) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("name", name);
|
||||
System.out.println("map : " + map);
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
public static void verifyGroupCreatedOnServer(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID) {
|
||||
System.out.println("------------------------------CHECK GROUP DETAILS------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/" + generatedGroupID + "?tenantIdentifier=default";
|
||||
Integer responseGroupID = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "id");
|
||||
assertEquals("ERROR IN CREATING THE GROUP", generatedGroupID, responseGroupID);
|
||||
}
|
||||
|
||||
public static void verifyGroupDetails(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID, final String field, final String expectedValue) {
|
||||
System.out.println("------------------------------CHECK GROUP DETAILS------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/" + generatedGroupID + "?tenantIdentifier=default";
|
||||
String responseValue = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, field);
|
||||
assertEquals("ERROR IN CREATING THE GROUP", expectedValue, responseValue);
|
||||
}
|
||||
|
||||
public static void verifyGroupActivatedOnServer(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID, final boolean generatedGroupStatus) {
|
||||
System.out.println("------------------------------CHECK GROUP STATUS------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/" + generatedGroupID + "?tenantIdentifier=default";
|
||||
Boolean responseGroupStatus = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "active");
|
||||
assertEquals("ERROR IN ACTIVATING THE GROUP", generatedGroupStatus, responseGroupStatus);
|
||||
}
|
||||
|
||||
public static void verifyGroupMembers(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID, final Integer groupMember) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
System.out.println("------------------------------CHECK GROUP MEMBERS------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/" + generatedGroupID + "?associations=clientMembers&tenantIdentifier=default";
|
||||
list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "clientMembers");
|
||||
assertTrue("ERROR IN GROUP MEMBER", list.toString().contains("id=" + groupMember.toString()));
|
||||
}
|
||||
|
||||
public static void verifyEmptyGroupMembers(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
System.out.println("------------------------------CHECK EMPTY GROUP MEMBER LIST------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/" + generatedGroupID + "?associations=clientMembers&tenantIdentifier=default";
|
||||
list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "clientMembers");
|
||||
assertEquals("GROUP MEMBER LIST NOT EMPTY", list, null);
|
||||
}
|
||||
|
||||
public static void verifyGroupDeleted(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer generatedGroupID) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
System.out.println("------------------------------CHECK GROUP DELETED------------------------------------\n");
|
||||
String GROUP_URL = "/mifosng-provider/api/v1/groups/?tenantIdentifier=default";
|
||||
list = Utils.performServerGet(requestSpec, responseSpec, GROUP_URL, "pageItems");
|
||||
|
||||
assertFalse("GROUP NOT DELETED", list.toString().contains("id=" + generatedGroupID.toString()));
|
||||
}
|
||||
|
||||
public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) {
|
||||
return Utils.randomStringGenerator(prefix, lenOfRandomSuffix);
|
||||
}
|
||||
|
||||
private static String randomIDGenerator(final String prefix, final int lenOfRandomSuffix) {
|
||||
return Utils.randomStringGenerator(prefix, lenOfRandomSuffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
}
|
||||
}
|
||||
+48
-9
@@ -6,8 +6,6 @@ import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.http.conn.HttpHostConnectException;
|
||||
|
||||
@@ -16,13 +14,19 @@ import com.jayway.restassured.path.json.JsonPath;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
import com.jayway.restassured.specification.ResponseSpecification;
|
||||
|
||||
import java.lang.System;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Random;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Utils {
|
||||
|
||||
private static final String LOGIN_URL = "/mifosng-provider/api/v1/authentication?username=mifos&password=password&tenantIdentifier=default";
|
||||
|
||||
|
||||
public static void initializeRESTAssured() {
|
||||
RestAssured.baseURI = "https://localhost";
|
||||
RestAssured.baseURI ="https://localhost";
|
||||
RestAssured.port = 8443;
|
||||
RestAssured.keystore("../keystore.jks", "openmf");
|
||||
}
|
||||
@@ -33,10 +37,11 @@ public class Utils {
|
||||
String json = RestAssured.post(LOGIN_URL).asString();
|
||||
assertThat("Failed to login into mifosx platform", StringUtils.isBlank(json), is(false));
|
||||
return JsonPath.with(json).get("base64EncodedAuthenticationKey");
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (e instanceof HttpHostConnectException) {
|
||||
HttpHostConnectException hh = (HttpHostConnectException) e;
|
||||
fail("Failed to connect to mifosx platform:" + hh.getMessage());
|
||||
fail("Failed to connect to mifosx platform:"+hh.getMessage());
|
||||
}
|
||||
|
||||
throw new RuntimeException(e);
|
||||
@@ -44,18 +49,52 @@ public class Utils {
|
||||
}
|
||||
|
||||
public static <T> T performServerGet(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String getURL, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec).expect().spec(responseSpec).log().ifError().when().get(getURL).andReturn().asString();
|
||||
final String getURL, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec)
|
||||
.expect().spec(responseSpec).log().ifError()
|
||||
.when().get(getURL).andReturn().asString();
|
||||
return (T) from(json).get(jsonAttributeToGetBack);
|
||||
}
|
||||
|
||||
public static <T> T performServerPost(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String postURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec).body(jsonBodyToSend).expect().spec(responseSpec).log().ifError().when().post(postURL)
|
||||
final String postURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec).body(jsonBodyToSend)
|
||||
.expect().spec(responseSpec).log().ifError()
|
||||
.when().post(postURL)
|
||||
.andReturn().asString();
|
||||
return (T) from(json).get(jsonAttributeToGetBack);
|
||||
}
|
||||
|
||||
public static <T> T performServerPut(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String putURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec).body(jsonBodyToSend)
|
||||
.expect().spec(responseSpec).log().ifError()
|
||||
.when().put(putURL)
|
||||
.andReturn().asString();
|
||||
return (T) from(json).get(jsonAttributeToGetBack);
|
||||
}
|
||||
|
||||
public static <T> T performServerDelete(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String deleteURL, final String jsonAttributeToGetBack) {
|
||||
String json = given().spec(requestSpec)
|
||||
.expect().spec(responseSpec).log().ifError()
|
||||
.when().delete(deleteURL)
|
||||
.andReturn().asString();
|
||||
return (T) from(json).get(jsonAttributeToGetBack);
|
||||
}
|
||||
|
||||
public static String convertDateToURLFormat(String dateToBeConvert){
|
||||
SimpleDateFormat oldFormat = new SimpleDateFormat("dd MMMMMM yyyy");
|
||||
SimpleDateFormat newFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
String reformattedStr="";
|
||||
try {
|
||||
reformattedStr = newFormat.format(oldFormat.parse(dateToBeConvert));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return reformattedStr;
|
||||
}
|
||||
|
||||
public static String randomStringGenerator(final String prefix, final int len, final String sourceSetString) {
|
||||
int lengthOfSource = sourceSetString.length();
|
||||
Random rnd = new Random();
|
||||
|
||||
+5
-2
@@ -33,12 +33,15 @@ public class LoanApplicationTestBuilder {
|
||||
private String submittedOnDate = "";
|
||||
private String loanType = "individual";
|
||||
|
||||
public String build(final String clientID, final String loanProductId) {
|
||||
public String build(final String ID, final String loanProductId) {
|
||||
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
map.put("locale", "en_GB");
|
||||
map.put("clientId", clientID);
|
||||
if (loanType == "group")
|
||||
map.put("groupId", ID);
|
||||
else
|
||||
map.put("clientId", ID);
|
||||
map.put("productId", loanProductId);
|
||||
map.put("principal", principal);
|
||||
map.put("loanTermFrequency", loanTermFrequency);
|
||||
|
||||
-1
@@ -33,7 +33,6 @@ public class GLClosure extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "is_deleted", nullable = false)
|
||||
private boolean deleted = true;
|
||||
|
||||
|
||||
-7
@@ -35,20 +35,16 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@JoinColumn(name = "account_id", nullable = false)
|
||||
private GLAccount glAccount;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "reversal_id")
|
||||
private JournalEntry reversalJournalEntry;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "transaction_id", nullable = false, length = 50)
|
||||
private String transactionId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "reversed", nullable = false)
|
||||
private boolean reversed = false;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "manual_entry", nullable = false)
|
||||
private boolean manualEntry = false;
|
||||
|
||||
@@ -62,15 +58,12 @@ public class JournalEntry extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "description", length = 500)
|
||||
private String description;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "entity_type_enum", length = 50)
|
||||
private Integer entityType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "entity_id")
|
||||
private Long entityId;
|
||||
|
||||
|
||||
-1
@@ -20,7 +20,6 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "acc_rule_tags", uniqueConstraints = { @UniqueConstraint(columnNames = { "acc_rule_id", "tag_id", "acc_type_enum" }, name = "UNIQUE_ACCOUNT_RULE_TAGS") })
|
||||
public class AccountingTagRule extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "acc_rule_id", nullable = false)
|
||||
private AccountingRule accountingRule;
|
||||
|
||||
+134
-130
@@ -25,171 +25,175 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "m_portfolio_command_source")
|
||||
public class CommandSource extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "action_name", nullable = true, length = 100)
|
||||
private String actionName;
|
||||
@Column(name = "action_name", nullable = true, length = 100)
|
||||
private String actionName;
|
||||
|
||||
@Column(name = "entity_name", nullable = true, length = 100)
|
||||
private String entityName;
|
||||
@Column(name = "entity_name", nullable = true, length = 100)
|
||||
private String entityName;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "office_id")
|
||||
private Long officeId;
|
||||
@Column(name = "office_id")
|
||||
private Long officeId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "group_id")
|
||||
private Long groupId;
|
||||
@Column(name = "group_id")
|
||||
private Long groupId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "client_id")
|
||||
private Long clientId;
|
||||
@Column(name = "client_id")
|
||||
private Long clientId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "loan_id")
|
||||
private Long loanId;
|
||||
@Column(name = "loan_id")
|
||||
private Long loanId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "savings_account_id")
|
||||
private Long savingsId;
|
||||
@Column(name = "savings_account_id")
|
||||
private Long savingsId;
|
||||
|
||||
@Column(name = "api_get_url", length = 100)
|
||||
private String resourceGetUrl;
|
||||
@Column(name = "api_get_url", length = 100)
|
||||
private String resourceGetUrl;
|
||||
|
||||
@Column(name = "resource_id")
|
||||
private Long resourceId;
|
||||
@Column(name = "resource_id")
|
||||
private Long resourceId;
|
||||
|
||||
@Column(name = "subresource_id")
|
||||
private Long subresourceId;
|
||||
@Column(name = "subresource_id")
|
||||
private Long subresourceId;
|
||||
|
||||
@Column(name = "command_as_json", length = 1000)
|
||||
private String commandAsJson;
|
||||
@Column(name = "command_as_json", length = 1000)
|
||||
private String commandAsJson;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "maker_id", nullable = false)
|
||||
private AppUser maker;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "maker_id", nullable = false)
|
||||
private AppUser maker;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "made_on_date", nullable = false)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date madeOnDate;
|
||||
@Column(name = "made_on_date", nullable = false)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date madeOnDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "checker_id", nullable = true)
|
||||
private AppUser checker;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "checker_id", nullable = true)
|
||||
private AppUser checker;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "checked_on_date", nullable = true)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date checkedOnDate;
|
||||
@Column(name = "checked_on_date", nullable = true)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date checkedOnDate;
|
||||
|
||||
@Column(name = "processing_result_enum", nullable = false)
|
||||
private Integer processingResult;
|
||||
|
||||
@Column(name = "product_id")
|
||||
private Long productId;
|
||||
@Column(name = "processing_result_enum", nullable = false)
|
||||
private Integer processingResult;
|
||||
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker) {
|
||||
return new CommandSource(wrapper.actionName(), wrapper.entityName(), wrapper.getHref(), command.entityId(), command.subentityId(),
|
||||
command.json(), maker, DateTime.now());
|
||||
}
|
||||
@Column(name = "product_id")
|
||||
private Long productId;
|
||||
|
||||
protected CommandSource() {
|
||||
//
|
||||
}
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper,
|
||||
final JsonCommand command, final AppUser maker) {
|
||||
return new CommandSource(wrapper.actionName(), wrapper.entityName(),
|
||||
wrapper.getHref(), command.entityId(), command.subentityId(),
|
||||
command.json(), maker, DateTime.now());
|
||||
}
|
||||
|
||||
private CommandSource(final String actionName, final String entityName, final String href, final Long resourceId,
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker, final DateTime madeOnDateTime) {
|
||||
this.actionName = actionName;
|
||||
this.entityName = entityName;
|
||||
this.resourceGetUrl = href;
|
||||
this.resourceId = resourceId;
|
||||
this.subresourceId = subresourceId;
|
||||
this.commandAsJson = commandSerializedAsJson;
|
||||
this.maker = maker;
|
||||
this.madeOnDate = madeOnDateTime.toDate();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED.getValue();
|
||||
}
|
||||
protected CommandSource() {
|
||||
//
|
||||
}
|
||||
|
||||
public void markAsChecked(final AppUser checker, final DateTime checkedOnDate) {
|
||||
this.checker = checker;
|
||||
this.checkedOnDate = checkedOnDate.toDate();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED.getValue();
|
||||
}
|
||||
private CommandSource(final String actionName, final String entityName,
|
||||
final String href, final Long resourceId, final Long subresourceId,
|
||||
final String commandSerializedAsJson, final AppUser maker,
|
||||
final DateTime madeOnDateTime) {
|
||||
this.actionName = actionName;
|
||||
this.entityName = entityName;
|
||||
this.resourceGetUrl = href;
|
||||
this.resourceId = resourceId;
|
||||
this.subresourceId = subresourceId;
|
||||
this.commandAsJson = commandSerializedAsJson;
|
||||
this.maker = maker;
|
||||
this.madeOnDate = madeOnDateTime.toDate();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED
|
||||
.getValue();
|
||||
}
|
||||
|
||||
public void updateResourceId(final Long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
public void markAsChecked(final AppUser checker,
|
||||
final DateTime checkedOnDate) {
|
||||
this.checker = checker;
|
||||
this.checkedOnDate = checkedOnDate.toDate();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED
|
||||
.getValue();
|
||||
}
|
||||
|
||||
public void updateSubresourceId(final Long subresourceId) {
|
||||
this.subresourceId = subresourceId;
|
||||
}
|
||||
public void updateResourceId(final Long resourceId) {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void updateJsonTo(final String json) {
|
||||
this.commandAsJson = json;
|
||||
}
|
||||
public void updateSubresourceId(final Long subresourceId) {
|
||||
this.subresourceId = subresourceId;
|
||||
}
|
||||
|
||||
public Long resourceId() {
|
||||
return this.resourceId;
|
||||
}
|
||||
public void updateJsonTo(final String json) {
|
||||
this.commandAsJson = json;
|
||||
}
|
||||
|
||||
public Long subresourceId() {
|
||||
return this.subresourceId;
|
||||
}
|
||||
public Long resourceId() {
|
||||
return this.resourceId;
|
||||
}
|
||||
|
||||
public boolean hasJson() {
|
||||
return StringUtils.isNotBlank(this.commandAsJson);
|
||||
}
|
||||
public Long subresourceId() {
|
||||
return this.subresourceId;
|
||||
}
|
||||
|
||||
public String json() {
|
||||
return this.commandAsJson;
|
||||
}
|
||||
public boolean hasJson() {
|
||||
return StringUtils.isNotBlank(this.commandAsJson);
|
||||
}
|
||||
|
||||
public String getActionName() {
|
||||
return this.actionName;
|
||||
}
|
||||
public String json() {
|
||||
return this.commandAsJson;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return this.entityName;
|
||||
}
|
||||
public String getActionName() {
|
||||
return this.actionName;
|
||||
}
|
||||
|
||||
public String getPermissionCode() {
|
||||
return this.actionName + "_" + this.entityName;
|
||||
}
|
||||
public String getEntityName() {
|
||||
return this.entityName;
|
||||
}
|
||||
|
||||
public Long getResourceId() {
|
||||
return this.resourceId;
|
||||
}
|
||||
public String getPermissionCode() {
|
||||
return this.actionName + "_" + this.entityName;
|
||||
}
|
||||
|
||||
public Long getSubresourceId() {
|
||||
return this.subresourceId;
|
||||
}
|
||||
public Long getResourceId() {
|
||||
return this.resourceId;
|
||||
}
|
||||
|
||||
public void markAsAwaitingApproval() {
|
||||
this.processingResult = CommandProcessingResultType.AWAITING_APPROVAL.getValue();
|
||||
}
|
||||
public Long getSubresourceId() {
|
||||
return this.subresourceId;
|
||||
}
|
||||
|
||||
public boolean isMarkedAsAwaitingApproval() {
|
||||
if (this.processingResult.equals(CommandProcessingResultType.AWAITING_APPROVAL.getValue())) return true;
|
||||
public void markAsAwaitingApproval() {
|
||||
this.processingResult = CommandProcessingResultType.AWAITING_APPROVAL
|
||||
.getValue();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
public boolean isMarkedAsAwaitingApproval() {
|
||||
if (this.processingResult
|
||||
.equals(CommandProcessingResultType.AWAITING_APPROVAL
|
||||
.getValue())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateForAudit(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
|
||||
final Long productId) {
|
||||
this.officeId = officeId;
|
||||
this.groupId = groupId;
|
||||
this.clientId = clientId;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.productId = productId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getResourceGetUrl() {
|
||||
return this.resourceGetUrl;
|
||||
}
|
||||
public void updateForAudit(final Long officeId, final Long groupId,
|
||||
final Long clientId, final Long loanId, final Long savingsId,
|
||||
final Long productId) {
|
||||
this.officeId = officeId;
|
||||
this.groupId = groupId;
|
||||
this.clientId = clientId;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
public String getResourceGetUrl() {
|
||||
return this.resourceGetUrl;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
}
|
||||
+29
-1
@@ -413,7 +413,11 @@ public class CommandWrapper {
|
||||
public boolean isUnassignStaff() {
|
||||
return this.actionName.equalsIgnoreCase("UNASSIGNSTAFF") && this.entityName.equalsIgnoreCase("GROUP");
|
||||
}
|
||||
|
||||
|
||||
public boolean isAssignStaff() {
|
||||
return this.actionName.equalsIgnoreCase("ASSIGNSTAFF");
|
||||
}
|
||||
|
||||
public String commandName() {
|
||||
return this.actionName + "_" + this.entityName;
|
||||
}
|
||||
@@ -474,6 +478,10 @@ public class CommandWrapper {
|
||||
return this.actionName.equalsIgnoreCase("UNDOTRANSACTION") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||
}
|
||||
|
||||
public boolean isAdjustSavingsAccountTransaction() {
|
||||
return this.actionName.equalsIgnoreCase("ADJUSTTRANSACTION") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||
}
|
||||
|
||||
public boolean isCalendarResource() {
|
||||
return this.entityName.equalsIgnoreCase("CALENDAR");
|
||||
}
|
||||
@@ -543,6 +551,10 @@ public class CommandWrapper {
|
||||
public boolean isUpdateGroupRole() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("UPDATEROLE");
|
||||
}
|
||||
|
||||
public boolean isTransferClientsBetweenGroups() {
|
||||
return this.entityName.equalsIgnoreCase("GROUP") && this.actionName.equalsIgnoreCase("TRANSFERCLIENTS");
|
||||
}
|
||||
|
||||
public boolean isClientAssignStaff() {
|
||||
return this.actionName.equalsIgnoreCase("ASSIGNSTAFF") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
@@ -551,6 +563,10 @@ public class CommandWrapper {
|
||||
public boolean isClientClose() {
|
||||
return this.actionName.equalsIgnoreCase("CLOSE") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
}
|
||||
|
||||
public boolean isClientTransfer() {
|
||||
return this.actionName.equalsIgnoreCase("TRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
|
||||
}
|
||||
|
||||
public boolean isProductMixResource() {
|
||||
return this.entityName.equalsIgnoreCase("PRODUCTMIX");
|
||||
@@ -559,4 +575,16 @@ public class CommandWrapper {
|
||||
public boolean isSchedulerResource() {
|
||||
return this.entityName.equalsIgnoreCase("SCHEDULER");
|
||||
}
|
||||
|
||||
public boolean isAccountTransferResource() {
|
||||
return this.entityName.equalsIgnoreCase("ACCOUNTTRANSFER");
|
||||
}
|
||||
|
||||
public boolean isMeetingResource() {
|
||||
return this.entityName.equalsIgnoreCase("MEETING");
|
||||
}
|
||||
|
||||
public boolean isSaveOrUpdateAttendance(){
|
||||
return this.actionName.equalsIgnoreCase("SAVEORUPDATEATTENDANCE");
|
||||
}
|
||||
}
|
||||
+111
-30
@@ -342,7 +342,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/clients/" + clientId + "?command=activate&template=true";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder closeClient(final Long clientId) {
|
||||
this.actionName = "CLOSE";
|
||||
this.entityName = "CLIENT";
|
||||
@@ -351,6 +351,15 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/clients/" + clientId + "?command=close&template=true";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder transferClient(final Long clientId) {
|
||||
this.actionName = "TRANSFER";
|
||||
this.entityName = "CLIENT";
|
||||
this.entityId = clientId;
|
||||
this.clientId = clientId;
|
||||
this.href = "/clientId/" + clientId + "?command=transfer";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateClient(final Long clientId) {
|
||||
this.actionName = "UPDATE";
|
||||
@@ -372,30 +381,30 @@ public class CommandWrapperBuilder {
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createDBDatatable(final String json) {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/";
|
||||
this.json = json;
|
||||
return this;
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/";
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateDBDatatable(final String datatable, final String json) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/" + datatable;
|
||||
this.json = json;
|
||||
return this;
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/" + datatable;
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deleteDBDatatable(final String datatable, final String json) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/" + datatable;
|
||||
this.json = json;
|
||||
return this;
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "DATATABLE";
|
||||
this.entityId = null;
|
||||
this.href = "/datatables/" + datatable;
|
||||
this.json = json;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createDatatable(final String datatable, final Long apptableId, final Long datatableId) {
|
||||
@@ -808,6 +817,14 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createAccountTransfer() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "ACCOUNTTRANSFER";
|
||||
this.entityId = null;
|
||||
this.href = "/accounttransfers";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder savingsAccountDeposit(final Long accountId) {
|
||||
this.actionName = "DEPOSIT";
|
||||
this.entityName = "SAVINGSACCOUNT";
|
||||
@@ -837,6 +854,17 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder adjustSavingsAccountTransaction(final Long accountId, final Long transactionId) {
|
||||
this.actionName = "ADJUSTTRANSACTION";
|
||||
this.entityName = "SAVINGSACCOUNT";
|
||||
this.savingsId = accountId;
|
||||
this.entityId = accountId;
|
||||
this.subentityId = transactionId;
|
||||
this.transactionId = transactionId.toString();
|
||||
this.href = "/savingsaccounts/" + accountId + "/transactions/" + transactionId + "?command=modify";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder savingsAccountInterestCalculation(final Long accountId) {
|
||||
this.actionName = "CALCULATEINTEREST";
|
||||
this.entityName = "SAVINGSACCOUNT";
|
||||
@@ -945,7 +973,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/groups/" + groupId + "?command=activate";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder saveGroupCollectionSheet(final Long groupId) {
|
||||
this.actionName = "SAVECOLLECTIONSHEET";
|
||||
this.entityName = "GROUP";
|
||||
@@ -954,7 +982,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/groups/" + groupId + "?command=saveCollectionSheet";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder deleteGroup(final Long groupId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "GROUP";
|
||||
@@ -981,6 +1009,15 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/groups/" + groupId + "?command=disassociateClients";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder transferClientsBetweenGroups(final Long sourceGroupId) {
|
||||
this.actionName = "TRANSFERCLIENTS";
|
||||
this.entityName = "GROUP";
|
||||
this.entityId = sourceGroupId;
|
||||
this.groupId = sourceGroupId;
|
||||
this.href = "/groups/" + sourceGroupId + "?command=transferClients";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder unassignGroupStaff(final Long groupId) {
|
||||
this.actionName = "UNASSIGNSTAFF";
|
||||
@@ -991,6 +1028,15 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder assignGroupStaff(final Long groupId) {
|
||||
this.actionName = "ASSIGNSTAFF";
|
||||
this.entityName = "GROUP";
|
||||
this.entityId = groupId;
|
||||
this.groupId = groupId;
|
||||
this.href = "/groups/" + groupId + "?command=assignStaff";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createCollateral(final Long loanId) {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "COLLATERAL";
|
||||
@@ -1089,7 +1135,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/accountingrules/" + accountingRuleId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder createHoliday() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "HOLIDAY";
|
||||
@@ -1103,7 +1149,7 @@ public class CommandWrapperBuilder {
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = null;
|
||||
this.href = "/groups/"+groupId+"?command=assignRole";
|
||||
this.href = "/groups/" + groupId + "?command=assignRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1112,7 +1158,7 @@ public class CommandWrapperBuilder {
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = roleId;
|
||||
this.href = "/groups/"+groupId+"?command=unassignRole";
|
||||
this.href = "/groups/" + groupId + "?command=unassignRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1121,10 +1167,10 @@ public class CommandWrapperBuilder {
|
||||
this.entityName = "GROUP";
|
||||
this.groupId = groupId;
|
||||
this.entityId = roleId;
|
||||
this.href = "/groups/"+groupId+"?command=updateRole";
|
||||
this.href = "/groups/" + groupId + "?command=updateRole";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder unassignClientStaff(final Long clientId) {
|
||||
this.actionName = "UNASSIGNSTAFF";
|
||||
this.entityName = "CLIENT";
|
||||
@@ -1160,7 +1206,7 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loanproducts/" + productId + "/productmix";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder deleteProductMix(final Long productId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "PRODUCTMIX";
|
||||
@@ -1169,17 +1215,52 @@ public class CommandWrapperBuilder {
|
||||
this.href = "/loanproducts/" + productId + "/productmix";
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder withProduct(final Long productId) {
|
||||
this.productId = productId;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandWrapperBuilder updateJobDetail(final Long jobId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "SCHEDULER";
|
||||
this.entityId = jobId;
|
||||
this.href = "/updateJobDetail/" + jobId+"/updateJobDetail";
|
||||
this.href = "/updateJobDetail/" + jobId + "/updateJobDetail";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createMeeting(final String supportedEntityType, final Long supportedEntityId) {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "MEETING";
|
||||
this.supportedEntityType = supportedEntityType;
|
||||
this.supportedEntityId = supportedEntityId;
|
||||
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/meetings";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateMeeting(final String supportedEntityType, final Long supportedEntityId, final Long meetingId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "MEETING";
|
||||
this.entityId = meetingId;
|
||||
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/meetings/" + meetingId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deleteMeeting(final String supportedEntityType, final Long supportedEntityId, final Long meetingId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "MEETING";
|
||||
this.entityId = meetingId;
|
||||
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/meetings/" + meetingId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder saveOrUpdateAttendance(final Long entityId, final String supportedEntityType, final Long supportedEntityId) {
|
||||
this.actionName = "SAVEORUPDATEATTENDANCE";
|
||||
this.entityName = "MEETING";
|
||||
this.entityId = entityId;
|
||||
this.supportedEntityType = supportedEntityType;
|
||||
this.supportedEntityId = supportedEntityId;
|
||||
this.href = "/" + supportedEntityType + "/" + supportedEntityId + "/meetings/" + entityId + "?command=saveOrUpdateAttendance";
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+28
-1
@@ -105,7 +105,14 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
private NewCommandSourceHandler findCommandHandler(final CommandWrapper wrapper) {
|
||||
NewCommandSourceHandler handler = null;
|
||||
|
||||
if (wrapper.isConfigurationResource()) {
|
||||
if (wrapper.isAccountTransferResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = this.applicationContext.getBean("createAccountTransferCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
}
|
||||
else if (wrapper.isConfigurationResource()) {
|
||||
handler = this.applicationContext.getBean("updateGlobalConfigurationCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDatatableResource()) {
|
||||
if (wrapper.isCreateDatatable()) {
|
||||
@@ -163,6 +170,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("assignClientStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientClose()) {
|
||||
handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isClientTransfer()) {
|
||||
handler = this.applicationContext.getBean("transferClientBetweenBranchesCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -405,6 +414,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("applyAnnualFeeSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSavingsAccountUndoTransaction()) {
|
||||
handler = this.applicationContext.getBean("undoTransactionSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isAdjustSavingsAccountTransaction()) {
|
||||
handler = this.applicationContext.getBean("savingsTransactionAdjustmentCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -441,6 +452,10 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
handler = this.applicationContext.getBean("unassignRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdateGroupRole()) {
|
||||
handler = this.applicationContext.getBean("updateGroupRoleCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isAssignStaff()) {
|
||||
handler = this.applicationContext.getBean("assignGroupStaffCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isTransferClientsBetweenGroups()) {
|
||||
handler = this.applicationContext.getBean("transferClientsBetweenGroupsCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
@@ -511,6 +526,18 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else if (wrapper.isMeetingResource()) {
|
||||
if (wrapper.isCreate()) {
|
||||
handler = this.applicationContext.getBean("createMeetingCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isUpdate()) {
|
||||
handler = this.applicationContext.getBean("updateMeetingCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isDelete()) {
|
||||
handler = this.applicationContext.getBean("deleteMeetingCommandHandler", NewCommandSourceHandler.class);
|
||||
} else if (wrapper.isSaveOrUpdateAttendance()) {
|
||||
handler = this.applicationContext.getBean("updateMeetingAttendanceCommandHandler", NewCommandSourceHandler.class);
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
+68
-55
@@ -22,72 +22,85 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_code_value", uniqueConstraints = { @UniqueConstraint(columnNames = { "code_id", "code_value" }, name = "code_value_duplicate") })
|
||||
@Table(name = "m_code_value", uniqueConstraints = { @UniqueConstraint(columnNames = {
|
||||
"code_id", "code_value" }, name = "code_value_duplicate") })
|
||||
public class CodeValue extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "code_value", length = 100)
|
||||
private String label;
|
||||
@Column(name = "code_value", length = 100)
|
||||
private String label;
|
||||
|
||||
@Column(name = "order_position")
|
||||
private int position;
|
||||
@Column(name = "order_position")
|
||||
private int position;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "code_id", nullable = false)
|
||||
private Code code;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "code_id", nullable = false)
|
||||
private Code code;
|
||||
|
||||
public static CodeValue createNew(Code code, final String label, final int position) {
|
||||
return new CodeValue(code, label, position);
|
||||
}
|
||||
public static CodeValue createNew(final Code code, final String label,
|
||||
final int position) {
|
||||
return new CodeValue(code, label, position);
|
||||
}
|
||||
|
||||
protected CodeValue() {
|
||||
//
|
||||
}
|
||||
protected CodeValue() {
|
||||
//
|
||||
}
|
||||
|
||||
private CodeValue(final Code code, final String label, final int position) {
|
||||
this.code = code;
|
||||
this.label = StringUtils.defaultIfEmpty(label, null);
|
||||
this.position = position;
|
||||
}
|
||||
private CodeValue(final Code code, final String label, final int position) {
|
||||
this.code = code;
|
||||
this.label = StringUtils.defaultIfEmpty(label, null);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String label() {
|
||||
return label;
|
||||
}
|
||||
public String label() {
|
||||
return this.label;
|
||||
}
|
||||
|
||||
public int position() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public static CodeValue fromJson(Code code, final JsonCommand command) {
|
||||
public int position() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
final String label = command.stringValueOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.NAME.getValue());
|
||||
Integer position = command.integerValueSansLocaleOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.POSITION.getValue());
|
||||
if(position == null) position = new Integer(0);
|
||||
return new CodeValue(code, label, position.intValue());
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
public static CodeValue fromJson(final Code code, final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(2);
|
||||
final String label = command
|
||||
.stringValueOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.NAME
|
||||
.getValue());
|
||||
Integer position = command
|
||||
.integerValueSansLocaleOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.POSITION
|
||||
.getValue());
|
||||
if (position == null) {
|
||||
position = new Integer(0);
|
||||
}
|
||||
return new CodeValue(code, label, position.intValue());
|
||||
}
|
||||
|
||||
final String labelParamName = CODEVALUE_JSON_INPUT_PARAMS.NAME.getValue();
|
||||
if (command.isChangeInStringParameterNamed(labelParamName, this.label)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(labelParamName);
|
||||
actualChanges.put(labelParamName, newValue);
|
||||
this.label = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String positionParamName = CODEVALUE_JSON_INPUT_PARAMS.POSITION.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(positionParamName, this.position)) {
|
||||
final Integer newValue = command.integerValueSansLocaleOfParameterNamed(positionParamName);
|
||||
actualChanges.put(positionParamName, newValue);
|
||||
this.position = newValue.intValue();
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
public CodeValueData toData() {
|
||||
return CodeValueData.instance(this.getId(), this.label, this.position);
|
||||
}
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(
|
||||
2);
|
||||
|
||||
final String labelParamName = CODEVALUE_JSON_INPUT_PARAMS.NAME
|
||||
.getValue();
|
||||
if (command.isChangeInStringParameterNamed(labelParamName, this.label)) {
|
||||
final String newValue = command
|
||||
.stringValueOfParameterNamed(labelParamName);
|
||||
actualChanges.put(labelParamName, newValue);
|
||||
this.label = StringUtils.defaultIfEmpty(newValue, null);
|
||||
}
|
||||
|
||||
final String positionParamName = CODEVALUE_JSON_INPUT_PARAMS.POSITION
|
||||
.getValue();
|
||||
if (command.isChangeInIntegerSansLocaleParameterNamed(
|
||||
positionParamName, this.position)) {
|
||||
final Integer newValue = command
|
||||
.integerValueSansLocaleOfParameterNamed(positionParamName);
|
||||
actualChanges.put(positionParamName, newValue);
|
||||
this.position = newValue.intValue();
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public CodeValueData toData() {
|
||||
return CodeValueData.instance(getId(), this.label, this.position);
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -14,10 +14,9 @@ import javax.persistence.UniqueConstraint;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "c_external_service", uniqueConstraints = { @UniqueConstraint(columnNames = ("name")) })
|
||||
@Table(name = "c_external_service", uniqueConstraints = { @UniqueConstraint(columnNames = "name") })
|
||||
public class ExternalService extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
|
||||
-1
@@ -15,7 +15,6 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "c_configuration")
|
||||
public class GlobalConfigurationProperty extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "name", nullable = false)
|
||||
private final String name;
|
||||
|
||||
|
||||
+4
@@ -306,6 +306,10 @@ public final class JsonCommand {
|
||||
final String value = this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand);
|
||||
return StringUtils.defaultIfEmpty(value, "");
|
||||
}
|
||||
|
||||
public String stringValueOfParameterNamedAllowingNull(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
|
||||
boolean isChanged = false;
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ public class DataValidatorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/***FIXME: Vishwas, why does this method have a parameter? Seems wrong***/
|
||||
public DataValidatorBuilder trueOrFalseRequired(final boolean trueOfFalseFieldProvided) {
|
||||
if (!trueOfFalseFieldProvided && !ignoreNullValue) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
|
||||
+17
-3
@@ -44,7 +44,6 @@ public class ScheduledJobDetail extends AbstractPersistable<Long> {
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date previousRunStartTime;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "next_run_time")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date nextRunTime;
|
||||
@@ -69,6 +68,9 @@ public class ScheduledJobDetail extends AbstractPersistable<Long> {
|
||||
@Column(name = "scheduler_group")
|
||||
private Short schedulerGroup;
|
||||
|
||||
@Column(name = "is_misfired")
|
||||
private boolean triggerMisfired;
|
||||
|
||||
protected ScheduledJobDetail() {
|
||||
|
||||
}
|
||||
@@ -109,11 +111,15 @@ public class ScheduledJobDetail extends AbstractPersistable<Long> {
|
||||
this.previousRunStartTime = previousRunStartTime;
|
||||
}
|
||||
|
||||
public Date getNextRunTime() {
|
||||
return this.nextRunTime;
|
||||
}
|
||||
|
||||
public void updateNextRunTime(final Date nextRunTime) {
|
||||
this.nextRunTime = nextRunTime;
|
||||
}
|
||||
|
||||
public void updateJobKey(String jobKey) {
|
||||
public void updateJobKey(final String jobKey) {
|
||||
this.jobKey = jobKey;
|
||||
}
|
||||
|
||||
@@ -125,7 +131,7 @@ public class ScheduledJobDetail extends AbstractPersistable<Long> {
|
||||
return this.currentlyRunning;
|
||||
}
|
||||
|
||||
public void updateCurrentlyRunningStatus(boolean currentlyRunning) {
|
||||
public void updateCurrentlyRunningStatus(final boolean currentlyRunning) {
|
||||
this.currentlyRunning = currentlyRunning;
|
||||
}
|
||||
|
||||
@@ -152,4 +158,12 @@ public class ScheduledJobDetail extends AbstractPersistable<Long> {
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isTriggerMisfired() {
|
||||
return this.triggerMisfired;
|
||||
}
|
||||
|
||||
public void updateTriggerMisfired(boolean triggerMisfired) {
|
||||
this.triggerMisfired = triggerMisfired;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
@@ -1,7 +1,10 @@
|
||||
package org.mifosplatform.infrastructure.jobs.domain;
|
||||
|
||||
import javax.persistence.LockModeType;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
@@ -14,4 +17,9 @@ public interface ScheduledJobDetailRepository extends JpaRepository<ScheduledJob
|
||||
@Query("from ScheduledJobDetail jobDetail where jobDetail.id=:jobId")
|
||||
ScheduledJobDetail findByJobId(@Param("jobId") Long jobId);
|
||||
|
||||
|
||||
@Lock(value=LockModeType.PESSIMISTIC_WRITE)
|
||||
@Query("from ScheduledJobDetail jobDetail where jobDetail.jobKey = :jobKey")
|
||||
ScheduledJobDetail findByJobKeyWithLock(@Param("jobKey") String jobKey);
|
||||
|
||||
}
|
||||
|
||||
+8
-8
@@ -16,39 +16,39 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "job_run_history")
|
||||
public class ScheduledJobRunHistory extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "job_id")
|
||||
@SuppressWarnings("unused")
|
||||
private ScheduledJobDetail scheduledJobDetail;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "version")
|
||||
@SuppressWarnings("unused")
|
||||
private Long version;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "start_time")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@SuppressWarnings("unused")
|
||||
private Date startTime;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "end_time")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@SuppressWarnings("unused")
|
||||
private Date endTime;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "status")
|
||||
@SuppressWarnings("unused")
|
||||
private String status;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "error_message")
|
||||
@SuppressWarnings("unused")
|
||||
private String errorMessage;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "trigger_type")
|
||||
@SuppressWarnings("unused")
|
||||
private String triggerType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "error_log")
|
||||
@SuppressWarnings("unused")
|
||||
private String errorLog;
|
||||
|
||||
public ScheduledJobRunHistory() {
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
package org.mifosplatform.infrastructure.jobs.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "scheduler_detail")
|
||||
public class SchedulerDetail extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "execute_misfired_jobs")
|
||||
private boolean executeInstructionForMisfiredJobs;
|
||||
|
||||
@Column(name = "is_suspended")
|
||||
private boolean suspended;
|
||||
|
||||
@Column(name = "reset_scheduler_on_bootup")
|
||||
private boolean resetSchedulerOnBootup;
|
||||
|
||||
protected SchedulerDetail() {
|
||||
|
||||
}
|
||||
|
||||
public boolean isExecuteInstructionForMisfiredJobs() {
|
||||
return this.executeInstructionForMisfiredJobs;
|
||||
}
|
||||
|
||||
public void updateExecuteInstructionForMisfiredJobs(boolean executeInstructionForMisfiredJobs) {
|
||||
this.executeInstructionForMisfiredJobs = executeInstructionForMisfiredJobs;
|
||||
}
|
||||
|
||||
public boolean isSuspended() {
|
||||
return this.suspended;
|
||||
}
|
||||
|
||||
public void updateSuspendedState(boolean suspended) {
|
||||
this.suspended = suspended;
|
||||
}
|
||||
|
||||
public boolean isResetSchedulerOnBootup() {
|
||||
return this.resetSchedulerOnBootup;
|
||||
}
|
||||
|
||||
public void updateResetSchedulerOnBootup(boolean resetSchedulerOnBootup) {
|
||||
this.resetSchedulerOnBootup = resetSchedulerOnBootup;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.mifosplatform.infrastructure.jobs.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface SchedulerDetailRepository extends JpaRepository<SchedulerDetail, Long>, JpaSpecificationExecutor<SchedulerDetail> {
|
||||
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ public enum JobName {
|
||||
|
||||
UPDATE_LOAN_SUMMARY("Update loan Summary"), UPDATE_LOAN_ARREARS_AGEING("Update Loan Arrears Ageing"), UPDATE_LOAN_PAID_IN_ADVANCE(
|
||||
"Update Loan Paid In Advance"), APPLY_ANNUAL_FEE_FOR_SAVINGS("Apply Annual Fee For Savings"), APPLY_HOLIDAYS_TO_LOANS(
|
||||
"Apply Holidays To Loans");
|
||||
"Apply Holidays To Loans"), POST_INTEREST_FOR_SAVINGS("Post Interest For Savings");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
+53
-42
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -15,6 +14,7 @@ import org.mifosplatform.infrastructure.core.exception.PlatformInternalServerExc
|
||||
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.mifosplatform.infrastructure.jobs.annotation.CronMethodParser;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.SchedulerDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.exception.JobNotFoundException;
|
||||
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
|
||||
import org.quartz.JobDataMap;
|
||||
@@ -24,6 +24,7 @@ import org.quartz.JobListener;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.TriggerListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -50,8 +51,6 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
|
||||
private final TenantDetailsService tenantDetailsService;
|
||||
|
||||
private final HashMap<Long, Boolean> schedulerStatus = new HashMap<Long, Boolean>(2);
|
||||
|
||||
private final HashMap<String, Scheduler> schedulers = new HashMap<String, Scheduler>(4);
|
||||
|
||||
@Autowired
|
||||
@@ -68,24 +67,32 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
for (MifosPlatformTenant tenant : allTenants) {
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
List<ScheduledJobDetail> scheduledJobDetails = this.schedularWritePlatformService.retrieveAllJobs();
|
||||
schedulerStatus.put(tenant.getId(), true);
|
||||
for (ScheduledJobDetail jobDetails : scheduledJobDetails) {
|
||||
scheduleJob(jobDetails);
|
||||
jobDetails.updateTriggerMisfired(false);
|
||||
this.schedularWritePlatformService.saveOrUpdate(jobDetails);
|
||||
}
|
||||
SchedulerDetail schedulerDetail = this.schedularWritePlatformService.retriveSchedulerDetail();
|
||||
if (schedulerDetail.isResetSchedulerOnBootup()) {
|
||||
schedulerDetail.updateSuspendedState(false);
|
||||
this.schedularWritePlatformService.updateSchedulerDetail(schedulerDetail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void executeJob(final ScheduledJobDetail scheduledJobDetail) {
|
||||
public void executeJob(final ScheduledJobDetail scheduledJobDetail, String triggerType) {
|
||||
try {
|
||||
final JobDataMap jobDataMap = new JobDataMap();
|
||||
jobDataMap.put(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE, SchedulerServiceConstants.TRIGGER_TYPE_APPLICATION);
|
||||
if (triggerType == null) {
|
||||
triggerType = SchedulerServiceConstants.TRIGGER_TYPE_APPLICATION;
|
||||
}
|
||||
jobDataMap.put(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE, triggerType);
|
||||
jobDataMap.put(SchedulerServiceConstants.TENANT_IDENTIFIER, ThreadLocalContextUtil.getTenant().getTenantIdentifier());
|
||||
String key = scheduledJobDetail.getJobKey();
|
||||
JobKey jobKey = constructJobKey(key);
|
||||
String schedulerName = getSchedulerName(scheduledJobDetail);
|
||||
Scheduler scheduler = schedulers.get(schedulerName);
|
||||
if (scheduler == null || scheduler.isInStandbyMode() || !scheduler.checkExists(jobKey)) {
|
||||
if (scheduler == null || !scheduler.checkExists(jobKey)) {
|
||||
JobDetail jobDetail = createJobDetail(scheduledJobDetail);
|
||||
String tempSchedulerName = "temp" + scheduledJobDetail.getId();
|
||||
List<Class<? extends JobListener>> listenerClasses = new ArrayList<Class<? extends JobListener>>(2);
|
||||
@@ -101,7 +108,6 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new PlatformInternalServerException("error.msg.sheduler.job.execution.failed", "Job execution failed for job with id:"
|
||||
+ scheduledJobDetail.getId(), scheduledJobDetail.getId());
|
||||
}
|
||||
@@ -128,32 +134,48 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
|
||||
@Override
|
||||
public void pauseScheduler() {
|
||||
schedulerStatus.put(ThreadLocalContextUtil.getTenant().getId(), false);
|
||||
for (Map.Entry<String, Scheduler> schedulerEntry : this.schedulers.entrySet()) {
|
||||
try {
|
||||
String schedulerName = schedulerEntry.getValue().getSchedulerName();
|
||||
if (isCurrentTenantsScheduler(schedulerName)) {
|
||||
schedulerEntry.getValue().standby();
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
SchedulerDetail schedulerDetail = this.schedularWritePlatformService.retriveSchedulerDetail();
|
||||
if (!schedulerDetail.isSuspended()) {
|
||||
schedulerDetail.updateSuspendedState(true);
|
||||
this.schedularWritePlatformService.updateSchedulerDetail(schedulerDetail);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScheduler() {
|
||||
for (Map.Entry<String, Scheduler> schedulerEntry : this.schedulers.entrySet()) {
|
||||
try {
|
||||
String schedulerName = schedulerEntry.getValue().getSchedulerName();
|
||||
if (isCurrentTenantsScheduler(schedulerName)) {
|
||||
schedulerEntry.getValue().start();
|
||||
SchedulerDetail schedulerDetail = this.schedularWritePlatformService.retriveSchedulerDetail();
|
||||
if (schedulerDetail.isSuspended()) {
|
||||
schedulerDetail.updateSuspendedState(false);
|
||||
this.schedularWritePlatformService.updateSchedulerDetail(schedulerDetail);
|
||||
if (schedulerDetail.isExecuteInstructionForMisfiredJobs()) {
|
||||
List<ScheduledJobDetail> scheduledJobDetails = this.schedularWritePlatformService.retrieveAllJobs();
|
||||
for (ScheduledJobDetail jobDetail : scheduledJobDetails) {
|
||||
if (jobDetail.isTriggerMisfired()) {
|
||||
if (jobDetail.isActiveSchedular()) {
|
||||
executeJob(jobDetail, SchedulerServiceConstants.TRIGGER_TYPE_CRON);
|
||||
}
|
||||
String schedulerName = getSchedulerName(jobDetail);
|
||||
Scheduler scheduler = schedulers.get(schedulerName);
|
||||
if (scheduler != null) {
|
||||
String key = jobDetail.getJobKey();
|
||||
JobKey jobKey = constructJobKey(key);
|
||||
try {
|
||||
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
|
||||
for (Trigger trigger : triggers) {
|
||||
if (trigger.getNextFireTime() != null && trigger.getNextFireTime().after(jobDetail.getNextRunTime())) {
|
||||
jobDetail.updateNextRunTime(trigger.getNextFireTime());
|
||||
}
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
jobDetail.updateTriggerMisfired(false);
|
||||
this.schedularWritePlatformService.saveOrUpdate(jobDetail);
|
||||
}
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
schedulerStatus.put(ThreadLocalContextUtil.getTenant().getId(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,23 +188,12 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
public void executeJob(final Long jobId) {
|
||||
ScheduledJobDetail scheduledJobDetail = this.schedularWritePlatformService.findByJobId(jobId);
|
||||
if (scheduledJobDetail == null) { throw new JobNotFoundException(String.valueOf(jobId)); }
|
||||
executeJob(scheduledJobDetail);
|
||||
executeJob(scheduledJobDetail, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSchedulerRunning() {
|
||||
return this.schedulerStatus.get(ThreadLocalContextUtil.getTenant().getId());
|
||||
}
|
||||
|
||||
private boolean isCurrentTenantsScheduler(final String schedulerName) {
|
||||
int beginIndex = SchedulerServiceConstants.SCHEDULER.length();
|
||||
int endIndex = schedulerName.length();
|
||||
if (schedulerName.contains(SchedulerServiceConstants.SCHEDULER_GROUP)) {
|
||||
endIndex = schedulerName.indexOf(SchedulerServiceConstants.SCHEDULER_GROUP);
|
||||
}
|
||||
String tenantId = schedulerName.substring(beginIndex, endIndex);
|
||||
MifosPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
||||
return tenant.getId() == Long.valueOf(tenantId);
|
||||
return !this.schedularWritePlatformService.retriveSchedulerDetail().isSuspended();
|
||||
}
|
||||
|
||||
private void scheduleJob(final ScheduledJobDetail scheduledJobDetails) {
|
||||
@@ -195,9 +206,6 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
JobDetail jobDetail = createJobDetail(scheduledJobDetails);
|
||||
Trigger trigger = createTrigger(scheduledJobDetails, jobDetail);
|
||||
Scheduler scheduler = getScheduler(scheduledJobDetails);
|
||||
if (!this.schedulerStatus.get(ThreadLocalContextUtil.getTenant().getId()) && !scheduler.isInStandbyMode()) {
|
||||
scheduler.standby();
|
||||
}
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
scheduledJobDetails.updateJobKey(getJobKeyAsString(jobDetail.getKey()));
|
||||
scheduledJobDetails.updateNextRunTime(trigger.getNextFireTime());
|
||||
@@ -253,6 +261,9 @@ public class JobRegisterServiceImpl implements JobRegisterService {
|
||||
listenerClasses.add(SchedulerJobListener.class);
|
||||
}
|
||||
schedulerFactoryBean.setGlobalJobListeners(getGlobalListener(listenerClasses));
|
||||
TriggerListener globalTriggerListener = applicationContext.getBean("schedulerTriggerListener", TriggerListener.class);
|
||||
TriggerListener[] globalTriggerListeners = { globalTriggerListener };
|
||||
schedulerFactoryBean.setGlobalTriggerListeners(globalTriggerListeners);
|
||||
Properties quartzProperties = new Properties();
|
||||
quartzProperties.put(SchedulerFactoryBean.PROP_THREAD_COUNT, Integer.toString(noOfThreads));
|
||||
schedulerFactoryBean.setQuartzProperties(quartzProperties);
|
||||
|
||||
+8
-1
@@ -6,6 +6,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.SchedulerDetail;
|
||||
|
||||
public interface SchedularWritePlatformService {
|
||||
|
||||
@@ -21,6 +22,12 @@ public interface SchedularWritePlatformService {
|
||||
|
||||
public ScheduledJobDetail findByJobId(Long jobId);
|
||||
|
||||
CommandProcessingResult updateJobDetail(Long jobId, JsonCommand command);
|
||||
public CommandProcessingResult updateJobDetail(Long jobId, JsonCommand command);
|
||||
|
||||
public SchedulerDetail retriveSchedulerDetail();
|
||||
|
||||
public void updateSchedulerDetail(final SchedulerDetail schedulerDetail);
|
||||
|
||||
public boolean processJobDetailForExecution(String jobKey, String triggerType);
|
||||
|
||||
}
|
||||
|
||||
+44
-1
@@ -1,5 +1,6 @@
|
||||
package org.mifosplatform.infrastructure.jobs.service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -11,6 +12,8 @@ import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetailRepository;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistoryRepository;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.SchedulerDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.SchedulerDetailRepository;
|
||||
import org.mifosplatform.infrastructure.jobs.exception.JobNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -23,13 +26,17 @@ public class SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
|
||||
|
||||
private final ScheduledJobRunHistoryRepository scheduledJobRunHistoryRepository;
|
||||
|
||||
private final SchedulerDetailRepository schedulerDetailRepository;
|
||||
|
||||
private final JobDetailDataValidator dataValidator;
|
||||
|
||||
@Autowired
|
||||
public SchedularWritePlatformServiceJpaRepositoryImpl(final ScheduledJobDetailRepository scheduledJobDetailsRepository,
|
||||
final ScheduledJobRunHistoryRepository scheduledJobRunHistoryRepository, final JobDetailDataValidator dataValidator) {
|
||||
final ScheduledJobRunHistoryRepository scheduledJobRunHistoryRepository, final JobDetailDataValidator dataValidator,
|
||||
final SchedulerDetailRepository schedulerDetailRepository) {
|
||||
this.scheduledJobDetailsRepository = scheduledJobDetailsRepository;
|
||||
this.scheduledJobRunHistoryRepository = scheduledJobRunHistoryRepository;
|
||||
this.schedulerDetailRepository = schedulerDetailRepository;
|
||||
this.dataValidator = dataValidator;
|
||||
}
|
||||
|
||||
@@ -71,6 +78,22 @@ public class SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
|
||||
return this.scheduledJobDetailsRepository.findByJobId(jobId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void updateSchedulerDetail(final SchedulerDetail schedulerDetail) {
|
||||
this.schedulerDetailRepository.save(schedulerDetail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchedulerDetail retriveSchedulerDetail() {
|
||||
SchedulerDetail schedulerDetail = null;
|
||||
List<SchedulerDetail> schedulerDetailList = schedulerDetailRepository.findAll();
|
||||
if (schedulerDetailList != null) {
|
||||
schedulerDetail = schedulerDetailList.get(0);
|
||||
}
|
||||
return schedulerDetail;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult updateJobDetail(final Long jobId, final JsonCommand command) {
|
||||
@@ -89,4 +112,24 @@ public class SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public boolean processJobDetailForExecution(String jobKey, String triggerType) {
|
||||
boolean isStopExecution = false;
|
||||
final ScheduledJobDetail scheduledJobDetail = scheduledJobDetailsRepository.findByJobKeyWithLock(jobKey);
|
||||
if (scheduledJobDetail.isCurrentlyRunning()
|
||||
|| (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && (scheduledJobDetail.getNextRunTime().after(new Date())))) {
|
||||
isStopExecution = true;
|
||||
}
|
||||
final SchedulerDetail schedulerDetail = retriveSchedulerDetail();
|
||||
if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && schedulerDetail.isSuspended()) {
|
||||
scheduledJobDetail.updateTriggerMisfired(true);
|
||||
isStopExecution = true;
|
||||
} else if (!isStopExecution) {
|
||||
scheduledJobDetail.updateCurrentlyRunningStatus(true);
|
||||
}
|
||||
scheduledJobDetailsRepository.save(scheduledJobDetail);
|
||||
return isStopExecution;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-18
@@ -2,12 +2,9 @@ package org.mifosplatform.infrastructure.jobs.service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
|
||||
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobDetail;
|
||||
import org.mifosplatform.infrastructure.jobs.domain.ScheduledJobRunHistory;
|
||||
import org.mifosplatform.infrastructure.jobs.exception.JobInProcessExecution;
|
||||
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.JobKey;
|
||||
@@ -31,12 +28,9 @@ public class SchedulerJobListener implements JobListener {
|
||||
|
||||
private final SchedularWritePlatformService schedularService;
|
||||
|
||||
private final TenantDetailsService tenantDetailsService;
|
||||
|
||||
@Autowired
|
||||
public SchedulerJobListener(final SchedularWritePlatformService schedularService, final TenantDetailsService tenantDetailsService) {
|
||||
public SchedulerJobListener(final SchedularWritePlatformService schedularService) {
|
||||
this.schedularService = schedularService;
|
||||
this.tenantDetailsService = tenantDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,16 +39,7 @@ public class SchedulerJobListener implements JobListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jobToBeExecuted(final JobExecutionContext context) {
|
||||
String tenantIdentifier = context.getTrigger().getJobDataMap().getString(SchedulerServiceConstants.TENANT_IDENTIFIER);
|
||||
MifosPlatformTenant tenant = this.tenantDetailsService.loadTenantById(tenantIdentifier);
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
JobKey key = context.getTrigger().getJobKey();
|
||||
String jobKey = key.getName() + SchedulerServiceConstants.JOB_KEY_SEPERATOR + key.getGroup();
|
||||
final ScheduledJobDetail scheduledJobDetail = schedularService.findByJobKey(jobKey);
|
||||
if (scheduledJobDetail.isCurrentlyRunning()) { throw new JobInProcessExecution(scheduledJobDetail.getJobName()); }
|
||||
scheduledJobDetail.updateCurrentlyRunningStatus(true);
|
||||
this.schedularService.saveOrUpdate(scheduledJobDetail);
|
||||
public void jobToBeExecuted(@SuppressWarnings("unused") final JobExecutionContext context) {
|
||||
|
||||
}
|
||||
|
||||
@@ -93,7 +78,8 @@ public class SchedulerJobListener implements JobListener {
|
||||
if (context.getMergedJobDataMap().containsKey(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE)) {
|
||||
triggerType = context.getMergedJobDataMap().getString(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE);
|
||||
}
|
||||
if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON) {
|
||||
if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && trigger.getNextFireTime() != null
|
||||
&& trigger.getNextFireTime().after(scheduledJobDetails.getNextRunTime())) {
|
||||
scheduledJobDetails.updateNextRunTime(trigger.getNextFireTime());
|
||||
}
|
||||
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package org.mifosplatform.infrastructure.jobs.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
|
||||
import org.mifosplatform.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.Trigger;
|
||||
import org.quartz.Trigger.CompletedExecutionInstruction;
|
||||
import org.quartz.TriggerListener;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SchedulerTriggerListener implements TriggerListener {
|
||||
|
||||
private final String name = "Global trigger Listner";
|
||||
|
||||
private final SchedularWritePlatformService schedularService;
|
||||
|
||||
private final TenantDetailsService tenantDetailsService;
|
||||
|
||||
@Autowired
|
||||
public SchedulerTriggerListener(final SchedularWritePlatformService schedularService, final TenantDetailsService tenantDetailsService) {
|
||||
this.schedularService = schedularService;
|
||||
this.tenantDetailsService = tenantDetailsService;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerFired(@SuppressWarnings("unused") Trigger trigger, @SuppressWarnings("unused") JobExecutionContext context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
|
||||
|
||||
String tenantIdentifier = trigger.getJobDataMap().getString(SchedulerServiceConstants.TENANT_IDENTIFIER);
|
||||
MifosPlatformTenant tenant = this.tenantDetailsService.loadTenantById(tenantIdentifier);
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
JobKey key = trigger.getJobKey();
|
||||
String jobKey = key.getName() + SchedulerServiceConstants.JOB_KEY_SEPERATOR + key.getGroup();
|
||||
String triggerType = SchedulerServiceConstants.TRIGGER_TYPE_CRON;
|
||||
if (context.getMergedJobDataMap().containsKey(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE)) {
|
||||
triggerType = context.getMergedJobDataMap().getString(SchedulerServiceConstants.TRIGGER_TYPE_REFERENCE);
|
||||
}
|
||||
return schedularService.processJobDetailForExecution(jobKey, triggerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerMisfired(@SuppressWarnings("unused") Trigger trigger) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerComplete(@SuppressWarnings("unused") Trigger trigger, @SuppressWarnings("unused") JobExecutionContext context,
|
||||
@SuppressWarnings("unused") CompletedExecutionInstruction triggerInstructionCode) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-2
@@ -30,7 +30,6 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "m_holiday", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "holiday_name") })
|
||||
public class Holiday extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "name", unique = true, nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@@ -49,7 +48,6 @@ public class Holiday extends AbstractPersistable<Long> {
|
||||
@Column(name = "processed", nullable = false)
|
||||
private boolean processed;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
|
||||
+8
-2
@@ -13,6 +13,7 @@ public class CurrencyData {
|
||||
private final String code;
|
||||
private final String name;
|
||||
private final int decimalPlaces;
|
||||
private final Integer inMultiplesOf;
|
||||
private final String displaySymbol;
|
||||
@SuppressWarnings("unused")
|
||||
private final String nameCode;
|
||||
@@ -20,13 +21,14 @@ public class CurrencyData {
|
||||
private final String displayLabel;
|
||||
|
||||
public static CurrencyData blank() {
|
||||
return new CurrencyData("", "", 0, "", "");
|
||||
return new CurrencyData("", "", 0,0, "", "");
|
||||
}
|
||||
|
||||
public CurrencyData(final String code, final String name, final int decimalPlaces, final String displaySymbol, final String nameCode) {
|
||||
public CurrencyData(final String code, final String name, final int decimalPlaces,final Integer inMultiplesOf, final String displaySymbol, final String nameCode) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.displaySymbol = displaySymbol;
|
||||
this.nameCode = nameCode;
|
||||
this.displayLabel = generateDisplayLabel();
|
||||
@@ -40,6 +42,10 @@ public class CurrencyData {
|
||||
return this.decimalPlaces;
|
||||
}
|
||||
|
||||
public Integer currencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
CurrencyData currencyData = (CurrencyData) obj;
|
||||
|
||||
+18
-8
@@ -23,6 +23,9 @@ public class ApplicationCurrency extends AbstractPersistable<Long> {
|
||||
@Column(name = "decimal_places", nullable = false)
|
||||
private final Integer decimalPlaces;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private final Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 50)
|
||||
private final String name;
|
||||
|
||||
@@ -36,19 +39,22 @@ public class ApplicationCurrency extends AbstractPersistable<Long> {
|
||||
this.code = null;
|
||||
this.name = null;
|
||||
this.decimalPlaces = null;
|
||||
this.inMultiplesOf = null;
|
||||
this.nameCode = null;
|
||||
this.displaySymbol = null;
|
||||
}
|
||||
|
||||
public static ApplicationCurrency from(final ApplicationCurrency currency, final int decimalPlaces) {
|
||||
return new ApplicationCurrency(currency.code, currency.name, decimalPlaces, currency.nameCode, currency.displaySymbol);
|
||||
public static ApplicationCurrency from(final ApplicationCurrency currency, final int decimalPlaces, final Integer inMultiplesOf) {
|
||||
return new ApplicationCurrency(currency.code, currency.name, decimalPlaces, inMultiplesOf, currency.nameCode,
|
||||
currency.displaySymbol);
|
||||
}
|
||||
|
||||
private ApplicationCurrency(final String code, final String name, final int decimalPlaces, final String nameCode,
|
||||
final String displaySymbol) {
|
||||
private ApplicationCurrency(final String code, final String name, final int decimalPlaces, final Integer inMultiplesOf,
|
||||
final String nameCode, final String displaySymbol) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.nameCode = nameCode;
|
||||
this.displaySymbol = displaySymbol;
|
||||
}
|
||||
@@ -65,6 +71,10 @@ public class ApplicationCurrency extends AbstractPersistable<Long> {
|
||||
return this.decimalPlaces;
|
||||
}
|
||||
|
||||
public Integer getCurrencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
public String getNameCode() {
|
||||
return nameCode;
|
||||
}
|
||||
@@ -74,14 +84,14 @@ public class ApplicationCurrency extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public CurrencyData toData() {
|
||||
return new CurrencyData(this.code, this.name, this.decimalPlaces, this.displaySymbol, this.nameCode);
|
||||
return new CurrencyData(this.code, this.name, this.decimalPlaces, this.inMultiplesOf, this.displaySymbol, this.nameCode);
|
||||
}
|
||||
|
||||
public CurrencyData toData(final int digitsAfterDecimalSupported) {
|
||||
return new CurrencyData(this.code, this.name, digitsAfterDecimalSupported, this.displaySymbol, this.nameCode);
|
||||
public CurrencyData toData(final int digitsAfterDecimalSupported, final Integer inMultiplesOf) {
|
||||
return new CurrencyData(this.code, this.name, digitsAfterDecimalSupported, inMultiplesOf, this.displaySymbol, this.nameCode);
|
||||
}
|
||||
|
||||
public OrganisationCurrency toOrganisationCurrency() {
|
||||
return new OrganisationCurrency(this.code, this.name, this.decimalPlaces, this.nameCode, this.displaySymbol);
|
||||
return new OrganisationCurrency(this.code, this.name, this.decimalPlaces,this.inMultiplesOf, this.nameCode, this.displaySymbol);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class ApplicationCurrencyRepositoryWrapper {
|
||||
if (defaultApplicationCurrency == null) { throw new CurrencyNotFoundException(currency.getCode()); }
|
||||
|
||||
final ApplicationCurrency applicationCurrency = ApplicationCurrency.from(defaultApplicationCurrency,
|
||||
currency.getDigitsAfterDecimal());
|
||||
currency.getDigitsAfterDecimal(),currency.getCurrencyInMultiplesOf());
|
||||
|
||||
return applicationCurrency;
|
||||
}
|
||||
|
||||
+11
-2
@@ -17,18 +17,23 @@ public class MonetaryCurrency {
|
||||
@Column(name = "currency_digits", nullable = false)
|
||||
private final int digitsAfterDecimal;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private final Integer inMultiplesOf;
|
||||
|
||||
protected MonetaryCurrency() {
|
||||
this.code = null;
|
||||
this.digitsAfterDecimal = 0;
|
||||
this.inMultiplesOf = 0;
|
||||
}
|
||||
|
||||
public MonetaryCurrency(final String code, final int digitsAfterDecimal) {
|
||||
public MonetaryCurrency(final String code, final int digitsAfterDecimal,final Integer inMultiplesOf) {
|
||||
this.code = code;
|
||||
this.digitsAfterDecimal = digitsAfterDecimal;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
}
|
||||
|
||||
public MonetaryCurrency copy() {
|
||||
return new MonetaryCurrency(this.code, this.digitsAfterDecimal);
|
||||
return new MonetaryCurrency(this.code, this.digitsAfterDecimal,this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
@@ -38,4 +43,8 @@ public class MonetaryCurrency {
|
||||
public int getDigitsAfterDecimal() {
|
||||
return digitsAfterDecimal;
|
||||
}
|
||||
|
||||
public Integer getCurrencyInMultiplesOf() {
|
||||
return inMultiplesOf;
|
||||
}
|
||||
}
|
||||
+32
-24
@@ -21,6 +21,9 @@ public class Money implements Comparable<Money> {
|
||||
@Column(name = "currency_digits")
|
||||
private final int currencyDigitsAfterDecimal;
|
||||
|
||||
@Column(name = "currency_multiplesof")
|
||||
private final Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19)
|
||||
private final BigDecimal amount;
|
||||
|
||||
@@ -44,46 +47,47 @@ public class Money implements Comparable<Money> {
|
||||
}
|
||||
|
||||
public static Money of(final MonetaryCurrency currency, final BigDecimal newAmount) {
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), defaultToZeroIfNull(newAmount));
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), defaultToZeroIfNull(newAmount),
|
||||
currency.getCurrencyInMultiplesOf());
|
||||
}
|
||||
|
||||
public static Money zero(final MonetaryCurrency currency) {
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO);
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf());
|
||||
}
|
||||
|
||||
protected Money() {
|
||||
this.currencyCode = null;
|
||||
this.currencyDigitsAfterDecimal = 0;
|
||||
this.inMultiplesOf = 0;
|
||||
this.amount = null;
|
||||
}
|
||||
|
||||
private Money(final String currencyCode, final int digitsAfterDecimal, final BigDecimal amount) {
|
||||
private Money(final String currencyCode, final int digitsAfterDecimal, final BigDecimal amount, final Integer inMultiplesOf) {
|
||||
this.currencyCode = currencyCode;
|
||||
this.currencyDigitsAfterDecimal = digitsAfterDecimal;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
|
||||
final BigDecimal amountZeroed = defaultToZeroIfNull(amount);
|
||||
final BigDecimal amountStripped = amountZeroed.stripTrailingZeros();
|
||||
final BigDecimal amountScaled = amountStripped.setScale(this.currencyDigitsAfterDecimal, RoundingMode.HALF_EVEN);
|
||||
this.amount = amountScaled;
|
||||
|
||||
// TODO - KW - below was test of using floor/ceil functions to support
|
||||
// round monetary amounts into multiples of say 20/50.
|
||||
// if (this.currencyDigitsAfterDecimal == 0) {
|
||||
// double existingVal = amountScaled.doubleValue();
|
||||
// double ceilingOfValue = ceiling(existingVal, Double.valueOf("20.0"));
|
||||
// double floorOfValue = floor(existingVal, Double.valueOf("20.0"));
|
||||
//
|
||||
// double floorDiff = existingVal - floorOfValue;
|
||||
// double ceilDiff = ceilingOfValue - existingVal;
|
||||
//
|
||||
// if (ceilDiff > floorDiff) {
|
||||
// this.amount = BigDecimal.valueOf(floorOfValue);
|
||||
// } else {
|
||||
// this.amount = BigDecimal.valueOf(ceilingOfValue);
|
||||
// }
|
||||
// } else {
|
||||
// this.amount = amountScaled;
|
||||
// }
|
||||
// round monetary amounts into multiplesof say 20/50.
|
||||
if (inMultiplesOf!= null && this.currencyDigitsAfterDecimal == 0 && inMultiplesOf>0 && amountScaled.doubleValue()>0) {
|
||||
double existingVal = amountScaled.doubleValue();
|
||||
double ceilingOfValue = ceiling(existingVal, inMultiplesOf);
|
||||
double floorOfValue = floor(existingVal, inMultiplesOf);
|
||||
|
||||
double floorDiff = existingVal - floorOfValue;
|
||||
double ceilDiff = ceilingOfValue - existingVal;
|
||||
|
||||
if (ceilDiff > floorDiff) {
|
||||
this.amount = BigDecimal.valueOf(floorOfValue);
|
||||
} else {
|
||||
this.amount = BigDecimal.valueOf(ceilingOfValue);
|
||||
}
|
||||
} else {
|
||||
this.amount = amountScaled;
|
||||
}
|
||||
}
|
||||
|
||||
public static double ceiling(final double n, final double s) {
|
||||
@@ -119,7 +123,7 @@ public class Money implements Comparable<Money> {
|
||||
}
|
||||
|
||||
public Money copy() {
|
||||
return new Money(this.currencyCode, this.currencyDigitsAfterDecimal, this.amount.stripTrailingZeros());
|
||||
return new Money(this.currencyCode, this.currencyDigitsAfterDecimal, this.amount.stripTrailingZeros(), this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public Money plus(final Iterable<? extends Money> moniesToAdd) {
|
||||
@@ -263,6 +267,10 @@ public class Money implements Comparable<Money> {
|
||||
return this.currencyDigitsAfterDecimal;
|
||||
}
|
||||
|
||||
public int getCurrencyInMultiplesOf() {
|
||||
return this.inMultiplesOf;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
@@ -298,7 +306,7 @@ public class Money implements Comparable<Money> {
|
||||
}
|
||||
|
||||
private MonetaryCurrency monetaryCurrency() {
|
||||
return new MonetaryCurrency(this.currencyCode, this.currencyDigitsAfterDecimal);
|
||||
return new MonetaryCurrency(this.currencyCode, this.currencyDigitsAfterDecimal, this.inMultiplesOf);
|
||||
}
|
||||
|
||||
public Money zero() {
|
||||
|
||||
+3
-2
@@ -58,14 +58,15 @@ public class CurrencyReadPlatformServiceImpl implements CurrencyReadPlatformServ
|
||||
final String code = rs.getString("code");
|
||||
final String name = rs.getString("name");
|
||||
final int decimalPlaces = JdbcSupport.getInteger(rs, "decimalPlaces");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final String displaySymbol = rs.getString("displaySymbol");
|
||||
final String nameCode = rs.getString("nameCode");
|
||||
|
||||
return new CurrencyData(code, name, decimalPlaces, displaySymbol, nameCode);
|
||||
return new CurrencyData(code, name, decimalPlaces, inMultiplesOf, displaySymbol, nameCode);
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return " c.code as code, c.name as name, c.decimal_places as decimalPlaces, c.display_symbol as displaySymbol, c.internationalized_name_code as nameCode ";
|
||||
return " c.code as code, c.name as name, c.decimal_places as decimalPlaces,c.currency_multiplesof as inMultiplesOf, c.display_symbol as displaySymbol, c.internationalized_name_code as nameCode ";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ import org.springframework.stereotype.Component;
|
||||
public class OfficeTransactionsApiResource {
|
||||
|
||||
private static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "transactionDate", "fromOfficeId",
|
||||
"fromOfficeName", "toOfficeId", "toOfficeIdName", "currencyCode", "digitsAfterDecimal", "transactionAmount", "description",
|
||||
"fromOfficeName", "toOfficeId", "toOfficeIdName", "currencyCode", "digitsAfterDecimal","inMultiplesOf", "transactionAmount", "description",
|
||||
"allowedOffices", "currencyOptions"));
|
||||
|
||||
private final String resourceNameForReadPermissions = "OFFICE";
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.organisation.office.domain;
|
||||
|
||||
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Wrapper for {@link OfficeRepository} that adds NULL checking and Error
|
||||
* handling capabilities
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class OfficeRepositoryWrapper {
|
||||
|
||||
private final OfficeRepository repository;
|
||||
|
||||
@Autowired
|
||||
public OfficeRepositoryWrapper(final OfficeRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public Office findOneWithNotFoundDetection(final Long id) {
|
||||
final Office office = this.repository.findOne(id);
|
||||
if (office == null) { throw new OfficeNotFoundException(id); }
|
||||
return office;
|
||||
}
|
||||
|
||||
public void save(final Office entity) {
|
||||
this.repository.save(entity);
|
||||
}
|
||||
|
||||
public void saveAndFlush(final Office entity) {
|
||||
this.repository.saveAndFlush(entity);
|
||||
}
|
||||
|
||||
public void delete(final Office entity) {
|
||||
this.repository.delete(entity);
|
||||
}
|
||||
}
|
||||
-6
@@ -28,30 +28,24 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "m_office_transaction")
|
||||
public class OfficeTransaction extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "from_office_id")
|
||||
private Office from;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "to_office_id")
|
||||
private Office to;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Date transactionDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "transaction_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal transactionAmount;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "description", nullable = true, length = 100)
|
||||
private String description;
|
||||
|
||||
|
||||
+7
-7
@@ -18,23 +18,21 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "m_organisation_currency")
|
||||
public class OrganisationCurrency extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "code", nullable = false, length = 3)
|
||||
private final String code;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "decimal_places", nullable = false)
|
||||
private final Integer decimalPlaces;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "currency_multiplesof")
|
||||
private final Integer inMultiplesOf;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 50)
|
||||
private final String name;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "internationalized_name_code", nullable = false, length = 50)
|
||||
private final String nameCode;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "display_symbol", nullable = true, length = 10)
|
||||
private final String displaySymbol;
|
||||
|
||||
@@ -42,15 +40,17 @@ public class OrganisationCurrency extends AbstractPersistable<Long> {
|
||||
this.code = null;
|
||||
this.name = null;
|
||||
this.decimalPlaces = null;
|
||||
this.inMultiplesOf = null;
|
||||
this.nameCode = null;
|
||||
this.displaySymbol = null;
|
||||
}
|
||||
|
||||
public OrganisationCurrency(final String code, final String name, final int decimalPlaces, final String nameCode,
|
||||
final String displaySymbol) {
|
||||
public OrganisationCurrency(final String code, final String name, final int decimalPlaces, final Integer inMultiplesOf,
|
||||
final String nameCode, final String displaySymbol) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
this.decimalPlaces = decimalPlaces;
|
||||
this.inMultiplesOf = inMultiplesOf;
|
||||
this.nameCode = nameCode;
|
||||
this.displaySymbol = displaySymbol;
|
||||
}
|
||||
|
||||
+4
-3
@@ -90,7 +90,7 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
|
||||
public String schema() {
|
||||
return " ot.id as id, ot.transaction_date as transactionDate, ot.from_office_id as fromOfficeId, fromoff.name as fromOfficeName, "
|
||||
+ " ot.to_office_id as toOfficeId, tooff.name as toOfficeName, ot.transaction_amount as transactionAmount, ot.description as description, "
|
||||
+ " ot.currency_code as currencyCode, rc.decimal_places as currencyDigits, "
|
||||
+ " ot.currency_code as currencyCode, rc.decimal_places as currencyDigits, rc.currency_multiplesof as inMultiplesOf, "
|
||||
+ " rc.name as currencyName, rc.internationalized_name_code as currencyNameCode, rc.display_symbol as currencyDisplaySymbol "
|
||||
+ " from m_office_transaction ot "
|
||||
+ " left join m_office fromoff on fromoff.id = ot.from_office_id "
|
||||
@@ -112,9 +112,10 @@ public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService
|
||||
String currencyNameCode = rs.getString("currencyNameCode");
|
||||
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
|
||||
CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
BigDecimal transactionAmount = rs.getBigDecimal("transactionAmount");
|
||||
String description = rs.getString("description");
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
final ApplicationCurrency appCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currencyCode);
|
||||
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(appCurrency.getCode(), appCurrency.getDecimalPlaces());
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(appCurrency.getCode(), appCurrency.getDecimalPlaces(),appCurrency.getCurrencyInMultiplesOf());
|
||||
final Money amount = Money.of(currency, command.bigDecimalValueOfParameterNamed("transactionAmount"));
|
||||
|
||||
final OfficeTransaction entity = OfficeTransaction.fromJson(fromOffice, toOffice, amount, command);
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public class StaffApiResource {
|
||||
* {@link StaffData}.
|
||||
*/
|
||||
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "firstname", "lastname", "displayName",
|
||||
"officeId", "officeName", "loanOfficerFlag", "allowedOffices"));
|
||||
"officeId", "officeName", "loanOfficerFlag", "externalId", "allowedOffices"));
|
||||
|
||||
private final String resourceNameForPermissions = "STAFF";
|
||||
|
||||
|
||||
+9
-38
@@ -8,8 +8,7 @@ package org.mifosplatform.organisation.staff.data;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.portfolio.client.data.ClientLoanAccountSummaryData;
|
||||
import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
|
||||
import org.mifosplatform.portfolio.accountdetails.data.LoanAccountSummaryData;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -17,23 +16,23 @@ import org.mifosplatform.portfolio.group.data.GroupAccountSummaryData;
|
||||
public class StaffAccountSummaryCollectionData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final List<ClientSummary> clients;
|
||||
private final List<LoanAccountSummary> clients;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<GroupSummary> groups;
|
||||
private final List<LoanAccountSummary> groups;
|
||||
|
||||
public StaffAccountSummaryCollectionData(final List<ClientSummary> clients, final List<GroupSummary> groups) {
|
||||
public StaffAccountSummaryCollectionData(final List<LoanAccountSummary> clients, final List<LoanAccountSummary> groups) {
|
||||
this.clients = clients;
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
public static final class ClientSummary {
|
||||
public static final class LoanAccountSummary {
|
||||
|
||||
private final Long id;
|
||||
private final String displayName;
|
||||
|
||||
private Collection<ClientLoanAccountSummaryData> loans;
|
||||
private Collection<LoanAccountSummaryData> loans;
|
||||
|
||||
public ClientSummary(Long id, String displayName) {
|
||||
public LoanAccountSummary(Long id, String displayName) {
|
||||
this.id = id;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
@@ -46,41 +45,13 @@ public class StaffAccountSummaryCollectionData {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public Collection<ClientLoanAccountSummaryData> getLoans() {
|
||||
public Collection<LoanAccountSummaryData> getLoans() {
|
||||
return loans;
|
||||
}
|
||||
|
||||
public void setLoans(Collection<ClientLoanAccountSummaryData> loans) {
|
||||
public void setLoans(Collection<LoanAccountSummaryData> loans) {
|
||||
this.loans = loans;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class GroupSummary {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
|
||||
private Collection<GroupAccountSummaryData> loans;
|
||||
|
||||
public GroupSummary(Long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<GroupAccountSummaryData> getLoans() {
|
||||
return loans;
|
||||
}
|
||||
|
||||
public void setLoans(Collection<GroupAccountSummaryData> loans) {
|
||||
this.loans = loans;
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-5
@@ -21,32 +21,34 @@ public class StaffData {
|
||||
private final Long officeId;
|
||||
private final String officeName;
|
||||
private final Boolean isLoanOfficer;
|
||||
private final String externalId;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<OfficeData> allowedOffices;
|
||||
|
||||
public static StaffData templateData(final StaffData staff, final Collection<OfficeData> allowedOffices) {
|
||||
return new StaffData(staff.id, staff.firstname, staff.lastname, staff.displayName, staff.officeId, staff.officeName,
|
||||
staff.isLoanOfficer, allowedOffices);
|
||||
staff.isLoanOfficer, staff.externalId, allowedOffices);
|
||||
}
|
||||
|
||||
public static StaffData lookup(final Long id, final String displayName) {
|
||||
return new StaffData(id, null, null, displayName, null, null, null, null);
|
||||
return new StaffData(id, null, null, displayName, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static StaffData instance(final Long id, final String firstname, final String lastname, final String displayName,
|
||||
final Long officeId, final String officeName, final Boolean isLoanOfficer) {
|
||||
return new StaffData(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, null);
|
||||
final Long officeId, final String officeName, final Boolean isLoanOfficer, final String externalId) {
|
||||
return new StaffData(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, externalId, null);
|
||||
}
|
||||
|
||||
private StaffData(final Long id, final String firstname, final String lastname, final String displayName, final Long officeId,
|
||||
final String officeName, final Boolean isLoanOfficer, final Collection<OfficeData> allowedOffices) {
|
||||
final String officeName, final Boolean isLoanOfficer, final String externalId, final Collection<OfficeData> allowedOffices) {
|
||||
this.id = id;
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.displayName = displayName;
|
||||
this.officeName = officeName;
|
||||
this.isLoanOfficer = isLoanOfficer;
|
||||
this.externalId = externalId;
|
||||
this.officeId = officeId;
|
||||
this.allowedOffices = allowedOffices;
|
||||
}
|
||||
|
||||
+22
-8
@@ -22,7 +22,8 @@ import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") })
|
||||
@Table(name = "m_staff", uniqueConstraints = { @UniqueConstraint(columnNames = { "display_name" }, name = "display_name") ,
|
||||
@UniqueConstraint(columnNames = { "external_id" }, name = "external_id_UNIQUE") })
|
||||
public class Staff extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "firstname", length = 50)
|
||||
@@ -34,6 +35,9 @@ public class Staff extends AbstractPersistable<Long> {
|
||||
@Column(name = "display_name", length = 100)
|
||||
private String displayName;
|
||||
|
||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||
private String externalId;
|
||||
|
||||
// Office to which this employee belongs
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
@@ -46,7 +50,6 @@ public class Staff extends AbstractPersistable<Long> {
|
||||
@Column(name = "organisational_role_enum", nullable = true)
|
||||
private Integer organisationalRoleType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "organisational_role_parent_staff_id", nullable = true)
|
||||
private Staff organisationalRoleParentStaff;
|
||||
@@ -54,29 +57,33 @@ public class Staff extends AbstractPersistable<Long> {
|
||||
public static Staff fromJson(final Office staffOffice, final JsonCommand command) {
|
||||
|
||||
final String firstnameParamName = "firstname";
|
||||
String firstname = command.stringValueOfParameterNamed(firstnameParamName);
|
||||
final String firstname = command.stringValueOfParameterNamed(firstnameParamName);
|
||||
|
||||
final String lastnameParamName = "lastname";
|
||||
String lastname = command.stringValueOfParameterNamed(lastnameParamName);
|
||||
final String lastname = command.stringValueOfParameterNamed(lastnameParamName);
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
final String externalId = command.stringValueOfParameterNamedAllowingNull(externalIdParamName);
|
||||
|
||||
final String isLoanOfficerParamName = "isLoanOfficer";
|
||||
final boolean isLoanOfficer = command.booleanPrimitiveValueOfParameterNamed(isLoanOfficerParamName);
|
||||
|
||||
return new Staff(staffOffice, firstname, lastname, isLoanOfficer);
|
||||
return new Staff(staffOffice, firstname, lastname, externalId, isLoanOfficer);
|
||||
}
|
||||
|
||||
public static Staff createNew(final Office staffOffice, final String firstname, final String lastname, final boolean isLoanOfficer) {
|
||||
return new Staff(staffOffice, firstname, lastname, isLoanOfficer);
|
||||
public static Staff createNew(final Office staffOffice, final String firstname, final String lastname, final String externalId, final boolean isLoanOfficer) {
|
||||
return new Staff(staffOffice, firstname, lastname, externalId, isLoanOfficer);
|
||||
}
|
||||
|
||||
protected Staff() {
|
||||
//
|
||||
}
|
||||
|
||||
private Staff(final Office staffOffice, final String firstname, final String lastname, final boolean isLoanOfficer) {
|
||||
private Staff(final Office staffOffice, final String firstname, final String lastname, final String externalId, final boolean isLoanOfficer) {
|
||||
this.office = staffOffice;
|
||||
this.firstname = StringUtils.defaultIfEmpty(firstname, null);
|
||||
this.lastname = StringUtils.defaultIfEmpty(lastname, null);
|
||||
this.externalId = externalId;
|
||||
this.loanOfficer = isLoanOfficer;
|
||||
deriveDisplayName(firstname);
|
||||
}
|
||||
@@ -125,6 +132,13 @@ public class Staff extends AbstractPersistable<Long> {
|
||||
deriveDisplayName(this.firstname);
|
||||
}
|
||||
|
||||
final String externalIdParamName = "externalId";
|
||||
if (command.isChangeInStringParameterNamed(externalIdParamName, this.externalId)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(externalIdParamName);
|
||||
actualChanges.put(externalIdParamName, newValue);
|
||||
this.externalId = newValue;
|
||||
}
|
||||
|
||||
final String isLoanOfficerParamName = "isLoanOfficer";
|
||||
if (command.isChangeInBooleanParameterNamed(isLoanOfficerParamName, this.loanOfficer)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isLoanOfficerParamName);
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public final class StaffCommandFromApiJsonDeserializer {
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("firstname", "lastname", "officeId", "isLoanOfficer"));
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("firstname", "lastname", "officeId", "externalId", "isLoanOfficer"));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
|
||||
+6
-4
@@ -38,7 +38,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
|
||||
public String schema() {
|
||||
return " s.id as id,s.office_id as officeId, o.name as officeName, s.firstname as firstname, s.lastname as lastname,"
|
||||
+ " s.display_name as displayName, s.is_loan_officer as isLoanOfficer from m_staff s "
|
||||
+ " s.display_name as displayName, s.is_loan_officer as isLoanOfficer, s.external_id as externalId from m_staff s "
|
||||
+ " join m_office o on o.id = s.office_id";
|
||||
}
|
||||
|
||||
@@ -52,8 +52,9 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final boolean isLoanOfficer = rs.getBoolean("isLoanOfficer");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer);
|
||||
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, externalId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +65,7 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("s.id as id, s.office_id as officeId, o.name as officeName,");
|
||||
sqlBuilder.append("s.firstname as firstname, s.lastname as lastname,");
|
||||
sqlBuilder.append("s.display_name as displayName, s.is_loan_officer as isLoanOfficer ");
|
||||
sqlBuilder.append("s.display_name as displayName, s.is_loan_officer as isLoanOfficer, s.external_id as externalId ");
|
||||
sqlBuilder.append("from m_office o ");
|
||||
sqlBuilder.append("join m_office ohierarchy on o.hierarchy like concat(ohierarchy.hierarchy, '%') ");
|
||||
sqlBuilder.append("join m_staff s on s.office_id = ohierarchy.id ");
|
||||
@@ -88,8 +89,9 @@ public class StaffReadPlatformServiceImpl implements StaffReadPlatformService {
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final boolean isLoanOfficer = rs.getBoolean("isLoanOfficer");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer);
|
||||
return StaffData.instance(id, firstname, lastname, displayName, officeId, officeName, isLoanOfficer, externalId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -98,7 +98,7 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements StaffWritePla
|
||||
}
|
||||
|
||||
if (!changesOnly.isEmpty()) {
|
||||
this.staffRepository.save(staffForUpdate);
|
||||
this.staffRepository.saveAndFlush(staffForUpdate);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(staffId)
|
||||
@@ -115,7 +115,14 @@ public class StaffWritePlatformServiceJpaRepositoryImpl implements StaffWritePla
|
||||
*/
|
||||
private void handleStaffDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||
Throwable realCause = dve.getMostSpecificCause();
|
||||
if (realCause.getMessage().contains("display_name")) {
|
||||
|
||||
if (realCause.getMessage().contains("external_id")) {
|
||||
|
||||
final String externalId = command.stringValueOfParameterNamed("externalId");
|
||||
throw new PlatformDataIntegrityException("error.msg.staff.duplicate.externalId", "Staff with externalId `" + externalId
|
||||
+ "` already exists", "externalId", externalId);
|
||||
}
|
||||
else if (realCause.getMessage().contains("display_name")) {
|
||||
final String lastname = command.stringValueOfParameterNamed("lastname");
|
||||
String displayName = lastname;
|
||||
if (!StringUtils.isBlank(displayName)) {
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@ public class WorkingDaysRepositoryWrapper {
|
||||
|
||||
public WorkingDays findOne() {
|
||||
final List<WorkingDays> workingDaysList = this.repository.findAll();
|
||||
|
||||
if (workingDaysList == null || workingDaysList.isEmpty()) {
|
||||
throw new WorkingDaysNotFoundException();
|
||||
}
|
||||
|
||||
if (workingDaysList == null || workingDaysList.isEmpty()) { throw new WorkingDaysNotFoundException(); }
|
||||
return workingDaysList.get(0);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ package org.mifosplatform.organisation.workingdays.service;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.organisation.workingdays.domain.RepaymentRescheduleType;
|
||||
import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarUtils;
|
||||
|
||||
public class WorkingDaysUtil {
|
||||
|
||||
@@ -38,6 +38,6 @@ public class WorkingDaysUtil {
|
||||
}
|
||||
|
||||
public static boolean isWorkingDay(WorkingDays workingDays, final LocalDate date){
|
||||
return CalendarHelper.isValidRedurringDate(workingDays.getRecurrence(), date, date);
|
||||
return CalendarUtils.isValidRedurringDate(workingDays.getRecurrence(), date, date);
|
||||
}
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.account;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransferData;
|
||||
|
||||
public class AccountTransfersApiConstants {
|
||||
|
||||
public static final String ACCOUNT_TRANSFER_RESOURCE_NAME = "accounttransfer";
|
||||
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
|
||||
// savings product and account parameters
|
||||
public static final String idParamName = "id";
|
||||
public static final String fromOfficeIdParamName = "fromOfficeId";
|
||||
public static final String fromClientIdParamName = "fromClientId";
|
||||
public static final String fromAccountIdParamName = "fromAccountId";
|
||||
public static final String fromAccountTypeParamName = "fromAccountType";
|
||||
public static final String toOfficeIdParamName = "toOfficeId";
|
||||
public static final String toClientIdParamName = "toClientId";
|
||||
public static final String toAccountIdParamName = "toAccountId";
|
||||
public static final String toAccountTypeParamName = "toAccountType";
|
||||
|
||||
// transaction parameters
|
||||
public static final String transferDateParamName = "transferDate";
|
||||
public static final String transferAmountParamName = "transferAmount";
|
||||
public static final String transferDescriptionParamName = "transferDescription";
|
||||
|
||||
public static final Set<String> REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName, dateFormatParamName,
|
||||
fromOfficeIdParamName, fromClientIdParamName, fromAccountTypeParamName, fromAccountIdParamName, toOfficeIdParamName,
|
||||
toClientIdParamName, toAccountTypeParamName, toAccountIdParamName, transferDateParamName, transferAmountParamName,
|
||||
transferDescriptionParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
* {@link AccountTransferData}. Where possible, we try to get response
|
||||
* parameters to match those of request parameters.
|
||||
*/
|
||||
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, transferDescriptionParamName,
|
||||
"currency"));
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.account;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public enum PortfolioAccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
LOAN(1, "accountType.loan"), //
|
||||
SAVINGS(2, "accountType.savings");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private PortfolioAccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] integerValues() {
|
||||
final List<Integer> values = new ArrayList<Integer>();
|
||||
for (final PortfolioAccountType enumType : values()) {
|
||||
if (enumType.getValue() > 0) {
|
||||
values.add(enumType.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return values.toArray();
|
||||
}
|
||||
|
||||
public static PortfolioAccountType fromInt(final Integer type) {
|
||||
|
||||
PortfolioAccountType enumType = PortfolioAccountType.INVALID;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
enumType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
enumType = SAVINGS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
public boolean isSavingsAccount() {
|
||||
return this.value == Integer.valueOf(2);
|
||||
}
|
||||
|
||||
public boolean isLoanAccount() {
|
||||
return this.value == Integer.valueOf(1);
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* 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.account.api;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.account.AccountTransfersApiConstants;
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransferData;
|
||||
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/accounttransfers")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class AccountTransfersApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<AccountTransferData> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersApiResource(final PlatformSecurityContext context,
|
||||
final DefaultToApiJsonSerializer<AccountTransferData> toApiJsonSerializer,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final AccountTransfersReadPlatformService accountTransfersReadPlatformService) {
|
||||
this.context = context;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.accountTransfersReadPlatformService = accountTransfersReadPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String template(@QueryParam("fromOfficeId") final Long fromOfficeId, @QueryParam("fromClientId") final Long fromClientId,
|
||||
@QueryParam("fromAccountId") final Long fromAccountId, @QueryParam("fromAccountType") final Integer fromAccountType,
|
||||
@QueryParam("toOfficeId") final Long toOfficeId, @QueryParam("toClientId") final Long toClientId,
|
||||
@QueryParam("toAccountId") final Long toAccountId, @QueryParam("toAccountType") final Integer toAccountType,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME);
|
||||
|
||||
AccountTransferData transferData = this.accountTransfersReadPlatformService.retrieveTemplate(fromOfficeId, fromClientId,
|
||||
fromAccountId, fromAccountType, toOfficeId, toClientId, toAccountId, toAccountType);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, transferData, AccountTransfersApiConstants.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String create(final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createAccountTransfer().withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
|
||||
@QueryParam("externalId") final String externalId, @QueryParam("offset") final Integer offset,
|
||||
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") final String sortOrder) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME);
|
||||
|
||||
final SearchParameters searchParameters = SearchParameters.forLoans(sqlSearch, externalId, offset, limit, orderBy, sortOrder);
|
||||
|
||||
final Page<AccountTransferData> transfers = this.accountTransfersReadPlatformService.retrieveAll(searchParameters);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, transfers, AccountTransfersApiConstants.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{transferId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveOne(@PathParam("transferId") final Long transferId, @Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME);
|
||||
|
||||
AccountTransferData transfer = this.accountTransfersReadPlatformService.retrieveOne(transferId);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, transfer, AccountTransfersApiConstants.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class AccountTransferData {
|
||||
|
||||
private final Long id;
|
||||
private final Boolean reversed;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal transferAmount;
|
||||
private final LocalDate transferDate;
|
||||
private final String transferDescription;
|
||||
private final OfficeData fromOffice;
|
||||
private final ClientData fromClient;
|
||||
private final EnumOptionData fromAccountType;
|
||||
private final PortfolioAccountData fromAccount;
|
||||
private final OfficeData toOffice;
|
||||
private final ClientData toClient;
|
||||
private final EnumOptionData toAccountType;
|
||||
private final PortfolioAccountData toAccount;
|
||||
|
||||
// template
|
||||
private final Collection<OfficeData> fromOfficeOptions;
|
||||
private final Collection<ClientData> fromClientOptions;
|
||||
private final Collection<EnumOptionData> fromAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> fromAccountOptions;
|
||||
private final Collection<OfficeData> toOfficeOptions;
|
||||
private final Collection<ClientData> toClientOptions;
|
||||
private final Collection<EnumOptionData> toAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> toAccountOptions;
|
||||
|
||||
public static AccountTransferData template(final OfficeData fromOffice, final ClientData fromClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final LocalDate transferDate,
|
||||
final OfficeData toOffice, final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions) {
|
||||
final Long id = null;
|
||||
CurrencyData currency = null;
|
||||
if (fromAccount != null) {
|
||||
currency = fromAccount.currency();
|
||||
}
|
||||
|
||||
final BigDecimal transferAmount = BigDecimal.ZERO;
|
||||
final String transferDescription = null;
|
||||
final Boolean reversed = null;
|
||||
return new AccountTransferData(id, reversed, fromOffice, fromClient, fromAccountType, fromAccount, currency, transferAmount,
|
||||
transferDate, transferDescription, toOffice, toClient, toAccountType, toAccount, fromOfficeOptions, fromClientOptions,
|
||||
fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
|
||||
}
|
||||
|
||||
public static AccountTransferData instance(final Long id, final Boolean reversed, final LocalDate transferDate,
|
||||
final CurrencyData currency, final BigDecimal transferAmount, final String transferDescription, final OfficeData fromOffice,
|
||||
final OfficeData toOffice, final ClientData fromClient, final ClientData toClient, final EnumOptionData fromAccountType,
|
||||
final PortfolioAccountData fromAccount, final EnumOptionData toAccountType, final PortfolioAccountData toAccount) {
|
||||
|
||||
return new AccountTransferData(id, reversed, fromOffice, fromClient, fromAccountType, fromAccount, currency, transferAmount,
|
||||
transferDate, transferDescription, toOffice, toClient, toAccountType, toAccount, null, null, null, null, null, null,
|
||||
null, null);
|
||||
}
|
||||
|
||||
public static AccountTransferData transferBasicDetails(final Long id, final CurrencyData currency, final BigDecimal transferAmount,
|
||||
final LocalDate transferDate, final String description, final Boolean reversed) {
|
||||
|
||||
final EnumOptionData fromAccountType = null;
|
||||
final EnumOptionData toAccountType = null;
|
||||
|
||||
return new AccountTransferData(id, reversed, null, null, fromAccountType, null, currency, transferAmount, transferDate,
|
||||
description, null, null, toAccountType, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private AccountTransferData(final Long id, final Boolean reversed, final OfficeData fromOffice, final ClientData fromClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final CurrencyData currency,
|
||||
final BigDecimal transferAmount, final LocalDate transferDate, final String transferDescription, final OfficeData toOffice,
|
||||
final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions) {
|
||||
this.id = id;
|
||||
this.reversed = reversed;
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromAccountType = fromAccountType;
|
||||
this.fromAccount = fromAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toAccountType = toAccountType;
|
||||
this.toAccount = toAccount;
|
||||
|
||||
this.currency = currency;
|
||||
this.transferAmount = transferAmount;
|
||||
this.transferDate = transferDate;
|
||||
this.transferDescription = transferDescription;
|
||||
|
||||
this.fromOfficeOptions = fromOfficeOptions;
|
||||
this.fromClientOptions = fromClientOptions;
|
||||
this.fromAccountTypeOptions = fromAccountTypeOptions;
|
||||
this.fromAccountOptions = fromAccountOptions;
|
||||
this.toOfficeOptions = toOfficeOptions;
|
||||
this.toClientOptions = toClientOptions;
|
||||
this.toAccountTypeOptions = toAccountTypeOptions;
|
||||
this.toAccountOptions = toAccountOptions;
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.REQUEST_DATA_PARAMETERS;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountTypeParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromClientIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromOfficeIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountTypeParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toClientIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toOfficeIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDescriptionParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
public class AccountTransfersDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validate(final JsonCommand command) {
|
||||
|
||||
final String json = command.json();
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(ACCOUNT_TRANSFER_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromOfficeIdParamName).value(fromOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromClientId = fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromClientIdParamName).value(fromClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromAccountId = fromApiJsonHelper.extractLongNamed(fromAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountIdParamName).value(fromAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer fromAccountType = fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountTypeParamName).value(fromAccountType)
|
||||
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
|
||||
|
||||
final Long toOfficeId = fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toOfficeIdParamName).value(toOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toClientId = fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toClientIdParamName).value(toClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toAccountId = fromApiJsonHelper.extractLongNamed(toAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountIdParamName).value(toAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer toAccountType = fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountTypeParamName).value(toAccountType)
|
||||
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
|
||||
|
||||
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed(transferDateParamName, element);
|
||||
baseDataValidator.reset().parameter(transferDateParamName).value(transactionDate).notNull();
|
||||
|
||||
final BigDecimal transactionAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transferAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(transferAmountParamName).value(transactionAmount).notNull().positiveAmount();
|
||||
|
||||
final String transactionDescription = fromApiJsonHelper.extractStringNamed(transferDescriptionParamName, element);
|
||||
baseDataValidator.reset().parameter(transferDescriptionParamName).value(transactionDescription).notBlank().notExceedingLengthOf(200);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class PortfolioAccountData {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
private final String externalId;
|
||||
private final Long groupId;
|
||||
private final String groupName;
|
||||
private final Long clientId;
|
||||
private final String clientName;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final Long fieldOfficerId;
|
||||
private final String fieldOfficerName;
|
||||
private final CurrencyData currency;
|
||||
|
||||
public static PortfolioAccountData lookup(final Long accountId, final String accountNo) {
|
||||
return new PortfolioAccountData(accountId, accountNo, null, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public PortfolioAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName,
|
||||
final Long clientId, final String clientName, final Long productId, final String productName, final Long fieldofficerId,
|
||||
final String fieldofficerName, final CurrencyData currency) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
this.groupId = groupId;
|
||||
this.groupName = groupName;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
this.fieldOfficerId = fieldofficerId;
|
||||
this.fieldOfficerName = fieldofficerName;
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
|
||||
if (obj == null) { return false; }
|
||||
if (obj == this) { return true; }
|
||||
if (obj.getClass() != getClass()) { return false; }
|
||||
final PortfolioAccountData rhs = (PortfolioAccountData) obj;
|
||||
return new EqualsBuilder().append(this.id, rhs.id).append(this.accountNo, rhs.accountNo).append(this.productId, rhs.productId).append(this.productName, rhs.productName).isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37).append(this.id).append(this.accountNo).append(this.productId).append(this.productName).toHashCode();
|
||||
}
|
||||
|
||||
public Long clientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public CurrencyData currency() {
|
||||
return this.currency;
|
||||
}
|
||||
|
||||
public String currencyCode() {
|
||||
return this.currency.code();
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_savings_account_transfer")
|
||||
public class AccountTransfer extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_office_id", nullable = false)
|
||||
private Office fromOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_client_id", nullable = false)
|
||||
private Client fromClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_savings_account_id", nullable = true)
|
||||
private SavingsAccount fromAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_office_id", nullable = false)
|
||||
private Office toOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_client_id", nullable = false)
|
||||
private Client toClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_savings_account_id", nullable = true)
|
||||
private SavingsAccount toSavingsAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_savings_transaction_id", nullable = true)
|
||||
private SavingsAccountTransaction fromTransaction;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_savings_transaction_id", nullable = true)
|
||||
private SavingsAccountTransaction toSavingsTransaction;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_loan_account_id", nullable = true)
|
||||
private Loan toLoanAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_loan_transaction_id", nullable = true)
|
||||
private LoanTransaction toLoanTransaction;
|
||||
|
||||
@Column(name = "is_reversed", nullable = false)
|
||||
private final boolean reversed = false;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "transaction_date")
|
||||
private Date date;
|
||||
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
public static AccountTransfer savingsToSavingsTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
|
||||
final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, final LocalDate transactionDate,
|
||||
final Money transactionAmount, final String description) {
|
||||
|
||||
return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toSavingsAccount, null, withdrawal,
|
||||
deposit, null, transactionDate, transactionAmount, description);
|
||||
}
|
||||
|
||||
public static AccountTransfer savingsToLoanTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount,
|
||||
final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate,
|
||||
final Money transactionAmount, final String description) {
|
||||
return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, null, toLoanAccount, withdrawal, null,
|
||||
loanRepaymentTransaction, transactionDate, transactionAmount, description);
|
||||
}
|
||||
|
||||
protected AccountTransfer() {
|
||||
//
|
||||
}
|
||||
|
||||
private AccountTransfer(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount,
|
||||
final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, final Loan toLoanAccount,
|
||||
final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit,
|
||||
final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate, final Money transactionAmount,
|
||||
final String description) {
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromAccount = fromSavingsAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toSavingsAccount = toSavingsAccount;
|
||||
this.fromTransaction = withdrawal;
|
||||
this.toSavingsTransaction = deposit;
|
||||
this.toLoanAccount = toLoanAccount;
|
||||
this.toLoanTransaction = loanRepaymentTransaction;
|
||||
this.date = transactionDate.toDate();
|
||||
this.currency = transactionAmount.getCurrency();
|
||||
this.amount = transactionAmount.getAmountDefaultedToNullIfZero();
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromClientIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromOfficeIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toClientIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toOfficeIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDescriptionParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
import org.mifosplatform.organisation.office.domain.OfficeRepository;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
@Service
|
||||
public class AccountTransferAssembler {
|
||||
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final OfficeRepository officeRepository;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public AccountTransferAssembler(final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository,
|
||||
final SavingsAccountAssembler savingsAccountAssembler, final FromJsonHelper fromApiJsonHelper) {
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepository = officeRepository;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public AccountTransfer assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccountTransaction withdrawal,
|
||||
final SavingsAccountTransaction deposit) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepository.findOne(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId);
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
|
||||
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), transactionAmount);
|
||||
|
||||
final String description = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
|
||||
return AccountTransfer.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toSavingsAccount,
|
||||
withdrawal, deposit, transactionDate, transactionMonetaryAmount, description);
|
||||
}
|
||||
|
||||
public AccountTransfer assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
|
||||
final Loan toLoanAccount, final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepository.findOne(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
|
||||
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), transactionAmount);
|
||||
|
||||
final String description = command.stringValueOfParameterNamed(transferDescriptionParamName);
|
||||
|
||||
return AccountTransfer.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
|
||||
withdrawal, loanRepaymentTransaction, transactionDate, transactionMonetaryAmount, description);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface AccountTransferRepository extends JpaRepository<AccountTransfer, Long>, JpaSpecificationExecutor<AccountTransfer> {
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* 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.account.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class AccountTransferNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public AccountTransferNotFoundException(final Long id) {
|
||||
super("error.msg.accounttransfer.id.invalid", "Account transfer with identifier " + id + " does not exist", id);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.account.handler;
|
||||
|
||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CreateAccountTransferCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final AccountTransfersWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CreateAccountTransferCommandHandler(final AccountTransfersWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return writePlatformService.create(command);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.portfolio.account.PortfolioAccountType;
|
||||
|
||||
public class AccountTransferEnumerations {
|
||||
|
||||
public static EnumOptionData accountType(final Integer type) {
|
||||
return accountType(PortfolioAccountType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData accountType(final PortfolioAccountType type) {
|
||||
|
||||
EnumOptionData optionData = null;
|
||||
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.LOAN.getValue().longValue(), PortfolioAccountType.LOAN.getCode(),
|
||||
"Loan Account");
|
||||
break;
|
||||
case SAVINGS:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.SAVINGS.getValue().longValue(),
|
||||
PortfolioAccountType.SAVINGS.getCode(), "Savings Account");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransferData;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
|
||||
public interface AccountTransfersReadPlatformService {
|
||||
|
||||
AccountTransferData retrieveTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
|
||||
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType);
|
||||
|
||||
Page<AccountTransferData> retrieveAll(SearchParameters searchParameters);
|
||||
|
||||
AccountTransferData retrieveOne(Long transferId);
|
||||
}
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.commands.exception.UnsupportedCommandException;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
import org.mifosplatform.infrastructure.core.service.Page;
|
||||
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.office.data.OfficeData;
|
||||
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.mifosplatform.portfolio.account.PortfolioAccountType;
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransferData;
|
||||
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
|
||||
import org.mifosplatform.portfolio.account.exception.AccountTransferNotFoundException;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Service
|
||||
public class AccountTransfersReadPlatformServiceImpl implements AccountTransfersReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final ClientReadPlatformService clientReadPlatformService;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
|
||||
|
||||
// mapper
|
||||
private final AccountTransfersMapper accountTransfersMapper;
|
||||
|
||||
// pagination
|
||||
private final PaginationHelper<AccountTransferData> paginationHelper = new PaginationHelper<AccountTransferData>();
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersReadPlatformServiceImpl(final RoutingDataSource dataSource,
|
||||
final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
|
||||
final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
|
||||
|
||||
this.accountTransfersMapper = new AccountTransfersMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountTransferData retrieveTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
|
||||
final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId, final Integer toAccountType) {
|
||||
|
||||
final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
|
||||
final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
|
||||
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions = Arrays.asList(savingsAccountType);
|
||||
final Collection<EnumOptionData> toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
|
||||
|
||||
// TODO - remove this after doing overpaid loan to savings transfers
|
||||
Integer mostRelevantFromAccountType = fromAccountType;
|
||||
if (mostRelevantFromAccountType == null) {
|
||||
mostRelevantFromAccountType = 2; // savings
|
||||
}
|
||||
|
||||
final Integer mostRelevantToAccountType = toAccountType;
|
||||
|
||||
final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
|
||||
final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
|
||||
|
||||
// check for now that only savings account type is passed and used.
|
||||
if (mostRelevantFromAccountType != 2) { throw new UnsupportedCommandException("transferFromLoanAccountNotSupported"); }
|
||||
|
||||
// from settings
|
||||
OfficeData fromOffice = null;
|
||||
ClientData fromClient = null;
|
||||
PortfolioAccountData fromAccount = null;
|
||||
|
||||
OfficeData toOffice = null;
|
||||
ClientData toClient = null;
|
||||
PortfolioAccountData toAccount = null;
|
||||
|
||||
// template
|
||||
Collection<PortfolioAccountData> fromAccountOptions = null;
|
||||
Collection<PortfolioAccountData> toAccountOptions = null;
|
||||
|
||||
Long mostRelevantFromOfficeId = fromOfficeId;
|
||||
Long mostRelevantFromClientId = fromClientId;
|
||||
|
||||
Long mostRelevantToOfficeId = toOfficeId;
|
||||
Long mostRelevantToClientId = toClientId;
|
||||
|
||||
if (fromAccountId != null && mostRelevantFromAccountType == 2) {
|
||||
fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, PortfolioAccountType.SAVINGS.getValue());
|
||||
|
||||
// override provided fromClient with client of account
|
||||
mostRelevantFromClientId = fromAccount.clientId();
|
||||
} else if (fromAccountId != null && mostRelevantFromAccountType == 1) { // loans
|
||||
// fetch loan account
|
||||
}
|
||||
|
||||
if (mostRelevantFromClientId != null) {
|
||||
fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
|
||||
mostRelevantFromOfficeId = fromClient.officeId();
|
||||
|
||||
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(mostRelevantFromAccountType,
|
||||
mostRelevantFromClientId);
|
||||
}
|
||||
|
||||
Collection<OfficeData> fromOfficeOptions = null;
|
||||
Collection<ClientData> fromClientOptions = null;
|
||||
if (mostRelevantFromOfficeId != null) {
|
||||
fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
|
||||
fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
|
||||
}
|
||||
|
||||
// defaults
|
||||
final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
|
||||
Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
|
||||
Collection<ClientData> toClientOptions = null;
|
||||
|
||||
if (toAccountId != null && fromAccount != null) {
|
||||
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType, fromAccount.currencyCode());
|
||||
mostRelevantToClientId = toAccount.clientId();
|
||||
}
|
||||
|
||||
if (mostRelevantToClientId != null) {
|
||||
toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
|
||||
mostRelevantToOfficeId = toClient.officeId();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
}
|
||||
|
||||
if (mostRelevantToOfficeId != null) {
|
||||
toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
|
||||
toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
if (toClientOptions != null && toClientOptions.size() == 1) {
|
||||
toClient = new ArrayList<ClientData>(toClientOptions).get(0);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
}
|
||||
}
|
||||
|
||||
return AccountTransferData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
|
||||
toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
|
||||
toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
|
||||
}
|
||||
|
||||
private Collection<PortfolioAccountData> retrieveToAccounts(final PortfolioAccountData excludeThisAccountFromOptions,
|
||||
final Integer toAccountType, final Long toClientId) {
|
||||
|
||||
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
|
||||
|
||||
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
|
||||
toClientId, currencyCode);
|
||||
if (!CollectionUtils.isEmpty(accountOptions)) {
|
||||
accountOptions.remove(excludeThisAccountFromOptions);
|
||||
} else {
|
||||
accountOptions = null;
|
||||
}
|
||||
|
||||
return accountOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AccountTransferData> retrieveAll(final SearchParameters searchParameters) {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
|
||||
sqlBuilder.append(this.accountTransfersMapper.schema());
|
||||
|
||||
if (searchParameters.isOrderByRequested()) {
|
||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||
|
||||
if (searchParameters.isSortOrderProvided()) {
|
||||
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
|
||||
}
|
||||
}
|
||||
|
||||
if (searchParameters.isLimited()) {
|
||||
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
|
||||
if (searchParameters.isOffset()) {
|
||||
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
final Object[] objectArray = new Object[2];
|
||||
final int arrayPos = 0;
|
||||
final Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos);
|
||||
final String sqlCountRows = "SELECT FOUND_ROWS()";
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
|
||||
this.accountTransfersMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountTransferData retrieveOne(final Long transferId) {
|
||||
|
||||
try {
|
||||
final String sql = "select " + this.accountTransfersMapper.schema() + " where sat.id = ?";
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql, this.accountTransfersMapper, new Object[] { transferId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(transferId);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AccountTransfersMapper implements RowMapper<AccountTransferData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public AccountTransfersMapper() {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("sat.id as id, sat.is_reversed as isReversed,");
|
||||
sqlBuilder.append("sat.transaction_date as transferDate, sat.amount as transferAmount,");
|
||||
sqlBuilder.append("sat.description as transferDescription,");
|
||||
sqlBuilder.append("sat.currency_code as currencyCode, sat.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("sat.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
|
||||
sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
|
||||
sqlBuilder.append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
|
||||
sqlBuilder.append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
|
||||
sqlBuilder.append("toclient.id as toClientId, toclient.display_name as toClientName,");
|
||||
sqlBuilder.append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
|
||||
sqlBuilder.append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
|
||||
sqlBuilder.append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
|
||||
sqlBuilder.append("fromsavtran.id as fromSavingsAccountTransactionId,");
|
||||
sqlBuilder.append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
|
||||
sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
|
||||
sqlBuilder.append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
|
||||
sqlBuilder.append(" FROM m_savings_account_transfer sat ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sat.currency_code ");
|
||||
sqlBuilder.append("join m_office fromoff on fromoff.id = sat.from_office_id ");
|
||||
sqlBuilder.append("join m_office tooff on tooff.id = sat.to_office_id ");
|
||||
sqlBuilder.append("join m_client fromclient on fromclient.id = sat.from_client_id ");
|
||||
sqlBuilder.append("join m_client toclient on toclient.id = sat.to_client_id ");
|
||||
sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = sat.from_savings_account_id ");
|
||||
sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = sat.to_savings_account_id ");
|
||||
sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = sat.to_loan_account_id ");
|
||||
sqlBuilder.append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = sat.from_savings_transaction_id ");
|
||||
sqlBuilder.append("left join m_savings_account_transaction tosavtran on tosavtran.id = sat.to_savings_transaction_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountTransferData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final boolean reversed = rs.getBoolean("isReversed");
|
||||
|
||||
final LocalDate transferDate = JdbcSupport.getLocalDate(rs, "transferDate");
|
||||
final BigDecimal transferAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
|
||||
final String transferDescription = rs.getString("transferDescription");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
|
||||
final String fromOfficeName = rs.getString("fromOfficeName");
|
||||
final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, fromOfficeName, null);
|
||||
|
||||
final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
|
||||
final String toOfficeName = rs.getString("toOfficeName");
|
||||
final OfficeData toOffice = OfficeData.dropdown(toOfficeId, toOfficeName, null);
|
||||
|
||||
final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
|
||||
final String fromClientName = rs.getString("fromClientName");
|
||||
final ClientData fromClient = ClientData.lookup(fromClientId, fromClientName, fromOfficeId, fromOfficeName);
|
||||
|
||||
final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
|
||||
final String toClientName = rs.getString("toClientName");
|
||||
final ClientData toClient = ClientData.lookup(toClientId, toClientName, toOfficeId, toOfficeName);
|
||||
|
||||
final EnumOptionData fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
|
||||
|
||||
final Long fromSavingsAccountId = JdbcSupport.getLong(rs, "fromSavingsAccountId");
|
||||
final String fromSavingsAccountNo = rs.getString("fromSavingsAccountNo");
|
||||
final PortfolioAccountData fromSavingsAccount = PortfolioAccountData.lookup(fromSavingsAccountId, fromSavingsAccountNo);
|
||||
|
||||
PortfolioAccountData toAccount = null;
|
||||
EnumOptionData toAccountType = null;
|
||||
final Long toSavingsAccountId = JdbcSupport.getLong(rs, "toSavingsAccountId");
|
||||
final String toSavingsAccountNo = rs.getString("toSavingsAccountNo");
|
||||
final Long toLoanAccountId = JdbcSupport.getLong(rs, "toLoanAccountId");
|
||||
final String toLoanAccountNo = rs.getString("toLoanAccountNo");
|
||||
|
||||
if (toSavingsAccountId != null) {
|
||||
toAccount = PortfolioAccountData.lookup(toSavingsAccountId, toSavingsAccountNo);
|
||||
toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
|
||||
} else if (toLoanAccountId != null) {
|
||||
toAccount = PortfolioAccountData.lookup(toLoanAccountId, toLoanAccountNo);
|
||||
toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
|
||||
}
|
||||
|
||||
return AccountTransferData.instance(id, reversed, transferDate, currency, transferAmount, transferDescription, fromOffice,
|
||||
toOffice, fromClient, toClient, fromAccountType, fromSavingsAccount, toAccountType, toAccount);
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface AccountTransfersWritePlatformService {
|
||||
|
||||
CommandProcessingResult create(JsonCommand command);
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountTypeParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountTypeParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
|
||||
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.mifosplatform.portfolio.account.PortfolioAccountType;
|
||||
import org.mifosplatform.portfolio.account.data.AccountTransfersDataValidator;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountTransfer;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountTransferAssembler;
|
||||
import org.mifosplatform.portfolio.account.domain.AccountTransferRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountDomainService;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class AccountTransfersWritePlatformServiceImpl implements AccountTransfersWritePlatformService {
|
||||
|
||||
private final AccountTransfersDataValidator accountTransfersDataValidator;
|
||||
private final AccountTransferAssembler accountTransferAssembler;
|
||||
private final AccountTransferRepository accountTransferRepository;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final SavingsAccountDomainService savingsAccountDomainService;
|
||||
private final LoanAssembler loanAccountAssembler;
|
||||
private final LoanAccountDomainService loanAccountDomainService;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValidator accountTransfersDataValidator,
|
||||
final AccountTransferAssembler accountTransferAssembler, final AccountTransferRepository accountTransferRepository,
|
||||
final SavingsAccountAssembler savingsAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService,
|
||||
final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService) {
|
||||
this.accountTransfersDataValidator = accountTransfersDataValidator;
|
||||
this.accountTransferAssembler = accountTransferAssembler;
|
||||
this.accountTransferRepository = accountTransferRepository;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.savingsAccountDomainService = savingsAccountDomainService;
|
||||
this.loanAccountAssembler = loanAssembler;
|
||||
this.loanAccountDomainService = loanAccountDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult create(final JsonCommand command) {
|
||||
|
||||
this.accountTransfersDataValidator.validate(command);
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
|
||||
final Integer fromAccountTypeId = command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName);
|
||||
final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId);
|
||||
|
||||
final Integer toAccountTypeId = command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName);
|
||||
final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId);
|
||||
|
||||
final PaymentDetail paymentDetail = null;
|
||||
Long fromSavingsAccountId = null;
|
||||
Long transferTransactionId = null;
|
||||
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
|
||||
fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId);
|
||||
|
||||
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount, fmt,
|
||||
transactionDate, transactionAmount, paymentDetail);
|
||||
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId);
|
||||
|
||||
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt,
|
||||
transactionDate, transactionAmount, paymentDetail);
|
||||
|
||||
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(command, withdrawal,
|
||||
deposit);
|
||||
this.accountTransferRepository.saveAndFlush(transferTransaction);
|
||||
transferTransactionId = transferTransaction.getId();
|
||||
|
||||
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
|
||||
//
|
||||
fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId);
|
||||
|
||||
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount, fmt,
|
||||
transactionDate, transactionAmount, paymentDetail);
|
||||
|
||||
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
|
||||
|
||||
final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeRepayment(toLoanAccountId,
|
||||
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null);
|
||||
|
||||
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToLoanTransfer(command,
|
||||
fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
|
||||
this.accountTransferRepository.saveAndFlush(transferTransaction);
|
||||
transferTransactionId = transferTransaction.getId();
|
||||
|
||||
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
// FIXME - kw - ADD overpaid loan to savings account transfer support.
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(transferTransactionId);
|
||||
|
||||
if (fromAccountType.isSavingsAccount()) {
|
||||
|
||||
builder.withSavingsId(fromSavingsAccountId);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToLoanAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isLoanAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
|
||||
|
||||
public interface PortfolioAccountReadPlatformService {
|
||||
|
||||
PortfolioAccountData retrieveOne(Long accountId, Integer accountTypeId);
|
||||
|
||||
PortfolioAccountData retrieveOne(Long accountId, Integer accountTypeId, String currencyCode);
|
||||
|
||||
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId);
|
||||
|
||||
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode);
|
||||
}
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.account.PortfolioAccountType;
|
||||
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
|
||||
import org.mifosplatform.portfolio.account.exception.AccountTransferNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccountReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
// mapper
|
||||
private final PortfolioSavingsAccountMapper savingsAccountMapper;
|
||||
private final PortfolioLoanAccountMapper loanAccountMapper;
|
||||
|
||||
@Autowired
|
||||
public PortfolioAccountReadPlatformServiceImpl(final RoutingDataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.savingsAccountMapper = new PortfolioSavingsAccountMapper();
|
||||
this.loanAccountMapper = new PortfolioLoanAccountMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId) {
|
||||
return retrieveOne(accountId, accountTypeId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId, final String currencyCode) {
|
||||
|
||||
Object[] sqlParams = new Object[] {accountId};
|
||||
PortfolioAccountData accountData = null;
|
||||
try {
|
||||
String sql = null;
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId);
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where la.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams = new Object[] {accountId, currencyCode};
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams);
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where sa.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams = new Object[] {accountId, currencyCode};
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(accountId);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId) {
|
||||
return retrieveAllForLookup(accountTypeId, clientId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId, final String currencyCode) {
|
||||
|
||||
Object[] sqlParams = new Object[] {clientId};
|
||||
Collection<PortfolioAccountData> accounts = null;
|
||||
String sql = null;
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId);
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where la.client_id = ? and la.loan_status_id = 300";
|
||||
if (currencyCode != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams = new Object[] {clientId, currencyCode};
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams);
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum = 300";
|
||||
if (currencyCode != null) {
|
||||
sql += " and sa.currency_code = ?";
|
||||
sqlParams = new Object[] {clientId, currencyCode};
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
private static final class PortfolioSavingsAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public PortfolioSavingsAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("sa.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_savings_account sa ");
|
||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = sa.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = sa.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = sa.field_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PortfolioLoanAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public PortfolioLoanAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("la.id as id, la.account_no as accountNo, la.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("lp.id as productId, lp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_loan la ");
|
||||
sqlBuilder.append("join m_product_loan lp ON la.product_id = lp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = la.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = la.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = la.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = la.loan_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency);
|
||||
}
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.accountdetails.data;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a summary of various accounts.
|
||||
*/
|
||||
public class AccountSummaryCollectionData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<LoanAccountSummaryData> loanAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<SavingsAccountSummaryData> savingsAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<LoanAccountSummaryData> memberLoanAccounts;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<SavingsAccountSummaryData> memberSavingsAccounts;
|
||||
|
||||
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
|
||||
final Collection<SavingsAccountSummaryData> savingsAccounts) {
|
||||
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
|
||||
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
|
||||
this.memberLoanAccounts = null;
|
||||
this.memberSavingsAccounts = null;
|
||||
}
|
||||
|
||||
public AccountSummaryCollectionData(final Collection<LoanAccountSummaryData> loanAccounts,
|
||||
final Collection<SavingsAccountSummaryData> savingsAccounts, final Collection<LoanAccountSummaryData> memberLoanAccounts,
|
||||
Collection<SavingsAccountSummaryData> memberSavingsAccounts) {
|
||||
this.loanAccounts = defaultLoanAccountsIfEmpty(loanAccounts);
|
||||
this.savingsAccounts = defaultSavingsAccountsIfEmpty(savingsAccounts);
|
||||
this.memberLoanAccounts = defaultLoanAccountsIfEmpty(memberLoanAccounts);
|
||||
this.memberSavingsAccounts = defaultSavingsAccountsIfEmpty(memberSavingsAccounts);
|
||||
}
|
||||
|
||||
private Collection<LoanAccountSummaryData> defaultLoanAccountsIfEmpty(final Collection<LoanAccountSummaryData> collection) {
|
||||
Collection<LoanAccountSummaryData> returnCollection = null;
|
||||
if (collection != null && !collection.isEmpty()) {
|
||||
returnCollection = collection;
|
||||
}
|
||||
return returnCollection;
|
||||
}
|
||||
|
||||
private Collection<SavingsAccountSummaryData> defaultSavingsAccountsIfEmpty(final Collection<SavingsAccountSummaryData> collection) {
|
||||
Collection<SavingsAccountSummaryData> returnCollection = null;
|
||||
if (collection != null && !collection.isEmpty()) {
|
||||
returnCollection = collection;
|
||||
}
|
||||
return returnCollection;
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -3,16 +3,16 @@
|
||||
* 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.client.data;
|
||||
package org.mifosplatform.portfolio.accountdetails.data;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
|
||||
|
||||
/**
|
||||
* Immutable data object for client loan accounts.
|
||||
* Immutable data object for loan accounts.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientLoanAccountSummaryData {
|
||||
public class LoanAccountSummaryData {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
@@ -23,7 +23,7 @@ public class ClientLoanAccountSummaryData {
|
||||
private final EnumOptionData loanType;
|
||||
private final Integer loanCycle;
|
||||
|
||||
public ClientLoanAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||
public LoanAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||
final String loanProductName, final LoanStatusEnumData loanStatus, final EnumOptionData loanType, final Integer loanCycle) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
+8
-5
@@ -3,18 +3,19 @@
|
||||
* 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.client.data;
|
||||
package org.mifosplatform.portfolio.accountdetails.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||
|
||||
/**
|
||||
* Immutable data object for client savings accounts.
|
||||
* Immutable data object for savings accounts.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ClientSavingsAccountSummaryData {
|
||||
public class SavingsAccountSummaryData {
|
||||
|
||||
private final Long id;
|
||||
private final String accountNo;
|
||||
@@ -24,10 +25,11 @@ public class ClientSavingsAccountSummaryData {
|
||||
private final SavingsAccountStatusEnumData status;
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal accountBalance;
|
||||
private final EnumOptionData accountType;
|
||||
|
||||
public ClientSavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||
public SavingsAccountSummaryData(final Long id, final String accountNo, final String externalId, final Long productId,
|
||||
final String productName, final SavingsAccountStatusEnumData status, final CurrencyData currency,
|
||||
final BigDecimal accountBalance) {
|
||||
final BigDecimal accountBalance, final EnumOptionData accountType) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
@@ -36,5 +38,6 @@ public class ClientSavingsAccountSummaryData {
|
||||
this.status = status;
|
||||
this.currency = currency;
|
||||
this.accountBalance = accountBalance;
|
||||
this.accountType = accountType;
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.accountdetails.domain;
|
||||
|
||||
/**
|
||||
* Enum representation of account types .
|
||||
*/
|
||||
public enum AccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
INDIVIDUAL(1, "accountType.individual"), //
|
||||
GROUP(2, "accountType.group"), //
|
||||
JLG(3, "accountType.jlg");//JLG account given in group context
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private AccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static AccountType fromInt(final Integer accountTypeValue) {
|
||||
|
||||
AccountType enumeration = AccountType.INVALID;
|
||||
switch (accountTypeValue) {
|
||||
case 1:
|
||||
enumeration = AccountType.INDIVIDUAL;
|
||||
break;
|
||||
case 2:
|
||||
enumeration = AccountType.GROUP;
|
||||
break;
|
||||
case 3:
|
||||
enumeration = AccountType.JLG;
|
||||
break;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
public static AccountType fromName(final String name){
|
||||
AccountType accountType = AccountType.INVALID;
|
||||
for (AccountType type : AccountType.values()) {
|
||||
if(type.getName().equals(name)) {
|
||||
accountType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return accountType;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
public boolean isInvalid(){
|
||||
return this.value.equals(AccountType.INVALID.getValue());
|
||||
}
|
||||
|
||||
public boolean isIndividualAccount(){
|
||||
return this.value.equals(AccountType.INDIVIDUAL.getValue());
|
||||
}
|
||||
|
||||
public boolean isGroupAccount(){
|
||||
return this.value.equals(AccountType.GROUP.getValue());
|
||||
}
|
||||
|
||||
public boolean isJLGAccount(){
|
||||
return this.value.equals(AccountType.JLG.getValue());
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package org.mifosplatform.portfolio.accountdetails.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.portfolio.accountdetails.data.AccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.accountdetails.data.LoanAccountSummaryData;
|
||||
|
||||
|
||||
public interface AccountDetailsReadPlatformService {
|
||||
|
||||
public AccountSummaryCollectionData retrieveClientAccountDetails(final Long clientId);
|
||||
|
||||
public AccountSummaryCollectionData retrieveGroupAccountDetails(final Long groupId);
|
||||
|
||||
public Collection<LoanAccountSummaryData> retrieveClientLoanAccountsByLoanOfficerId(final Long clientId, final Long loanOfficerId);
|
||||
|
||||
public Collection<LoanAccountSummaryData> retrieveGroupLoanAccountsByLoanOfficerId(final Long groupId,final Long loanOfficerId);
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
package org.mifosplatform.portfolio.accountdetails.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.accountdetails.data.AccountSummaryCollectionData;
|
||||
import org.mifosplatform.portfolio.accountdetails.data.LoanAccountSummaryData;
|
||||
import org.mifosplatform.portfolio.accountdetails.data.SavingsAccountSummaryData;
|
||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.LoanStatusEnumData;
|
||||
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AccountDetailsReadPlatformServiceJpaRepositoryImpl implements AccountDetailsReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final ClientReadPlatformService clientReadPlatformService;
|
||||
private final GroupReadPlatformService groupReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public AccountDetailsReadPlatformServiceJpaRepositoryImpl(final ClientReadPlatformService clientReadPlatformService,
|
||||
final RoutingDataSource dataSource, final GroupReadPlatformService groupReadPlatformService) {
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.groupReadPlatformService = groupReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountSummaryCollectionData retrieveClientAccountDetails(Long clientId) {
|
||||
// Check if client exists
|
||||
clientReadPlatformService.retrieveOne(clientId);
|
||||
String loanwhereClause = " where l.client_id = ?";
|
||||
String savingswhereClause = " where sa.client_id = ? order by sa.status_enum ASC, sa.account_no ASC";
|
||||
List<LoanAccountSummaryData> loanAccounts = retrieveLoanAccountDetails(loanwhereClause, new Object[] { clientId });
|
||||
List<SavingsAccountSummaryData> savingsAccounts = retrieveAccountDetails(savingswhereClause, new Object[] { clientId });
|
||||
return new AccountSummaryCollectionData(loanAccounts, savingsAccounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountSummaryCollectionData retrieveGroupAccountDetails(Long groupId) {
|
||||
// Check if group exists
|
||||
groupReadPlatformService.retrieveOne(groupId);
|
||||
String loanWhereClauseForGroup = " where l.group_id = ? and l.client_id is null";
|
||||
String loanWhereClauseForMembers = " where l.group_id = ? and l.client_id is not null";
|
||||
String savingswhereClauseForGroup = " where sa.group_id = ? and sa.client_id is null order by sa.status_enum ASC, sa.account_no ASC";
|
||||
String savingswhereClauseForMembers = " where sa.group_id = ? and sa.client_id is not null order by sa.status_enum ASC, sa.account_no ASC";
|
||||
List<LoanAccountSummaryData> groupLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForGroup, new Object[] { groupId });
|
||||
List<SavingsAccountSummaryData> groupSavingsAccounts = retrieveAccountDetails(savingswhereClauseForGroup, new Object[] { groupId });
|
||||
List<LoanAccountSummaryData> memberLoanAccounts = retrieveLoanAccountDetails(loanWhereClauseForMembers, new Object[] { groupId });
|
||||
List<SavingsAccountSummaryData> memberSavingsAccounts = retrieveAccountDetails(savingswhereClauseForMembers,
|
||||
new Object[] { groupId });
|
||||
return new AccountSummaryCollectionData(groupLoanAccounts, groupSavingsAccounts, memberLoanAccounts, memberSavingsAccounts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LoanAccountSummaryData> retrieveClientLoanAccountsByLoanOfficerId(final Long clientId, final Long loanOfficerId) {
|
||||
// Check if client exists
|
||||
clientReadPlatformService.retrieveOne(clientId);
|
||||
String loanWhereClause = " where l.client_id = ? and l.loan_officer_id = ?";
|
||||
return retrieveLoanAccountDetails(loanWhereClause, new Object[] { clientId, loanOfficerId });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<LoanAccountSummaryData> retrieveGroupLoanAccountsByLoanOfficerId(final Long groupId, final Long loanOfficerId) {
|
||||
// Check if group exists
|
||||
groupReadPlatformService.retrieveOne(groupId);
|
||||
String loanWhereClause = " where l.group_id = ? and l.client_id is null and l.loan_officer_id = ?";
|
||||
return retrieveLoanAccountDetails(loanWhereClause, new Object[] { groupId, loanOfficerId });
|
||||
}
|
||||
|
||||
private List<LoanAccountSummaryData> retrieveLoanAccountDetails(String loanwhereClause, Object[] inputs) {
|
||||
LoanAccountSummaryDataMapper rm = new LoanAccountSummaryDataMapper();
|
||||
String sql = "select " + rm.loanAccountSummarySchema() + loanwhereClause;
|
||||
return this.jdbcTemplate.query(sql, rm, inputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityId
|
||||
* @return
|
||||
*/
|
||||
private List<SavingsAccountSummaryData> retrieveAccountDetails(String savingswhereClause, Object[] inputs) {
|
||||
SavingsAccountSummaryDataMapper savingsAccountSummaryDataMapper = new SavingsAccountSummaryDataMapper();
|
||||
final String savingsSql = "select " + savingsAccountSummaryDataMapper.schema() + savingswhereClause;
|
||||
return this.jdbcTemplate.query(savingsSql, savingsAccountSummaryDataMapper, inputs);
|
||||
}
|
||||
|
||||
private static final class SavingsAccountSummaryDataMapper implements RowMapper<SavingsAccountSummaryData> {
|
||||
|
||||
final String schemaSql;
|
||||
|
||||
public SavingsAccountSummaryDataMapper() {
|
||||
StringBuilder accountsSummary = new StringBuilder();
|
||||
accountsSummary.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, sa.status_enum as statusEnum, ");
|
||||
accountsSummary.append("sa.account_type_enum as accountType, ");
|
||||
accountsSummary.append("sa.account_balance_derived as accountBalance, ");
|
||||
accountsSummary
|
||||
.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, sa.currency_multiplesof as inMultiplesOf, ");
|
||||
accountsSummary.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
accountsSummary.append("curr.display_symbol as currencyDisplaySymbol, ");
|
||||
accountsSummary.append("sa.product_id as productId, p.name as productName ");
|
||||
accountsSummary.append("from m_savings_account sa ");
|
||||
accountsSummary.append("join m_savings_product as p on p.id = sa.product_id ");
|
||||
accountsSummary.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
|
||||
this.schemaSql = accountsSummary.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
final Long productId = JdbcSupport.getLong(rs, "productId");
|
||||
final String productName = rs.getString("productName");
|
||||
final Integer statusId = JdbcSupport.getInteger(rs, "statusEnum");
|
||||
final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "accountBalance");
|
||||
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusId);
|
||||
final Integer accountType = JdbcSupport.getInteger(rs, "accountType");
|
||||
final EnumOptionData accountTypeData = AccountEnumerations.loanType(accountType);
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
|
||||
currencyDisplaySymbol, currencyNameCode);
|
||||
|
||||
return new SavingsAccountSummaryData(id, accountNo, externalId, productId, productName, status, currency, accountBalance,
|
||||
accountTypeData);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LoanAccountSummaryDataMapper implements RowMapper<LoanAccountSummaryData> {
|
||||
|
||||
public String loanAccountSummarySchema() {
|
||||
|
||||
StringBuilder accountsSummary = new StringBuilder("l.id as id, l.account_no as accountNo, l.external_id as externalId,");
|
||||
accountsSummary.append("l.product_id as productId, lp.name as productName,")
|
||||
.append("l.loan_status_id as statusId, l.loan_type_enum as loanType, ").append("l.loan_product_counter as loanCycle ")
|
||||
.append(" from m_loan l ").append("LEFT JOIN m_product_loan AS lp ON lp.id = l.product_id");
|
||||
|
||||
return accountsSummary.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
final Long productId = JdbcSupport.getLong(rs, "productId");
|
||||
final String loanProductName = rs.getString("productName");
|
||||
final Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId");
|
||||
final LoanStatusEnumData loanStatus = LoanEnumerations.status(loanStatusId);
|
||||
final Integer loanTypeId = JdbcSupport.getInteger(rs, "loanType");
|
||||
final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeId);
|
||||
final Integer loanCycle = JdbcSupport.getInteger(rs, "loanCycle");
|
||||
|
||||
return new LoanAccountSummaryData(id, accountNo, externalId, productId, loanProductName, loanStatus, loanType, loanCycle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.mifosplatform.portfolio.accountdetails.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.portfolio.accountdetails.domain.AccountType;
|
||||
|
||||
|
||||
public class AccountEnumerations {
|
||||
|
||||
public static EnumOptionData loanType(final Integer loanTypeId) {
|
||||
return loanType(AccountType.fromInt(loanTypeId));
|
||||
}
|
||||
|
||||
public static EnumOptionData loanType(final String name) {
|
||||
return loanType(AccountType.fromName(name));
|
||||
}
|
||||
|
||||
public static EnumOptionData loanType(final AccountType type) {
|
||||
EnumOptionData optionData = new EnumOptionData(AccountType.INVALID.getValue().longValue(), AccountType.INVALID.getCode(), "Invalid");
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
optionData = new EnumOptionData(AccountType.INVALID.getValue().longValue(), AccountType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
case INDIVIDUAL:
|
||||
optionData = new EnumOptionData(AccountType.INDIVIDUAL.getValue().longValue(), AccountType.INDIVIDUAL.getCode(), "Individual");
|
||||
break;
|
||||
case GROUP:
|
||||
optionData = new EnumOptionData(AccountType.GROUP.getValue().longValue(), AccountType.GROUP.getCode(), "Group");
|
||||
break;
|
||||
case JLG:
|
||||
optionData = new EnumOptionData(AccountType.JLG.getValue().longValue(), AccountType.JLG.getCode(), "JLG");
|
||||
break;
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+2
-34
@@ -20,6 +20,7 @@ import org.mifosplatform.portfolio.calendar.domain.Calendar;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarDropdownReadPlatformService;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarReadPlatformService;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -105,7 +106,7 @@ public class CalendarsApiResource {
|
||||
|
||||
Collection<CalendarData> calendarsData = new ArrayList<CalendarData>();
|
||||
|
||||
List<Integer> calendarTypeOptions = createIntegerListFromQueryParameter(calendarType);
|
||||
List<Integer> calendarTypeOptions = CalendarUtils.createIntegerListFromQueryParameter(calendarType);
|
||||
|
||||
|
||||
if (!associationParameters.isEmpty()) {
|
||||
@@ -191,37 +192,4 @@ public class CalendarsApiResource {
|
||||
return new CalendarData(calendarData, entityTypeOptions, calendarTypeOptions, remindByOptions);
|
||||
}
|
||||
|
||||
|
||||
public List<Integer> createIntegerListFromQueryParameter(String calendarTypeQuery) {
|
||||
List<Integer> calendarTypeOptions = new ArrayList<Integer>();
|
||||
// adding all calendar Types if query parameter is "all"
|
||||
if(calendarTypeQuery.equalsIgnoreCase("all")){
|
||||
calendarTypeOptions.add(1);
|
||||
calendarTypeOptions.add(2);
|
||||
calendarTypeOptions.add(3);
|
||||
calendarTypeOptions.add(4);
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
// creating a list of calendar type options from the comma separated query parameter.
|
||||
List<String> calendarTypeOptionsInQuery = new ArrayList<String>();
|
||||
StringTokenizer st = new StringTokenizer(calendarTypeQuery, ",");
|
||||
while (st.hasMoreElements()) {
|
||||
calendarTypeOptionsInQuery.add(st.nextElement().toString());
|
||||
}
|
||||
|
||||
for(String calType : calendarTypeOptionsInQuery){
|
||||
if(calType.equalsIgnoreCase("collection")) {
|
||||
calendarTypeOptions.add(1);
|
||||
} else if(calType.equalsIgnoreCase("training")) {
|
||||
calendarTypeOptions.add(2);
|
||||
} else if(calType.equalsIgnoreCase("audit")) {
|
||||
calendarTypeOptions.add(3);
|
||||
} else if(calType.equalsIgnoreCase("general")) {
|
||||
calendarTypeOptions.add(4);
|
||||
}
|
||||
}
|
||||
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -23,7 +23,7 @@ import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.portfolio.calendar.CalendarConstants.CALENDAR_SUPPORTED_PARAMETERS;
|
||||
import org.mifosplatform.portfolio.calendar.exception.CalendarDateException;
|
||||
import org.mifosplatform.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarHelper;
|
||||
import org.mifosplatform.portfolio.calendar.service.CalendarUtils;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@@ -213,13 +213,13 @@ public class Calendar extends AbstractAuditableCustom<AppUser, Long> {
|
||||
//FIXME: AA - Is this restriction required only for collection type meetings or for all?.
|
||||
//Do not allow to change meeting frequency
|
||||
|
||||
if(!CalendarHelper.isFrequencySame(this.recurrence, newValue)){
|
||||
if(!CalendarUtils.isFrequencySame(this.recurrence, newValue)){
|
||||
final String defaultUserMessage = "Update of meeting frequency is not supported";
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.frequency", defaultUserMessage);
|
||||
}
|
||||
|
||||
//Do not allow to change meeting interval
|
||||
if(!CalendarHelper.isIntervalSame(this.recurrence, newValue)){
|
||||
if(!CalendarUtils.isIntervalSame(this.recurrence, newValue)){
|
||||
final String defaultUserMessage = "Update of meeting interval is not supported";
|
||||
throw new CalendarParameterUpdateNotSupportedException("meeting.interval", defaultUserMessage);
|
||||
}
|
||||
|
||||
+16
@@ -66,4 +66,20 @@ public enum CalendarEntityType {
|
||||
public String toString() {
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public static boolean isGroup(final Integer value) {
|
||||
return CalendarEntityType.GROUPS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isGroup(final String name) {
|
||||
return CalendarEntityType.GROUPS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isCenter(final Integer value) {
|
||||
return CalendarEntityType.CENTERS.value.equals(value) ? true : false;
|
||||
}
|
||||
|
||||
public static boolean isCenter(final String name) {
|
||||
return CalendarEntityType.CENTERS.name().equalsIgnoreCase(name) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-2
@@ -6,6 +6,7 @@
|
||||
package org.mifosplatform.portfolio.calendar.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
@@ -14,12 +15,19 @@ import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface CalendarInstanceRepository extends JpaRepository<CalendarInstance, Long>, JpaSpecificationExecutor<CalendarInstance> {
|
||||
|
||||
CalendarInstance findByCalendarAndEntityIdAndEntityTypeId(Long calendarId, Long entityId, Integer entityTypeId);
|
||||
CalendarInstance findByCalendarIdAndEntityIdAndEntityTypeId(Long calendarId, Long entityId, Integer entityTypeId);
|
||||
|
||||
Collection<CalendarInstance> findByEntityIdAndEntityTypeId(Long entityId, Integer entityTypeId);
|
||||
|
||||
CalendarInstance findByEntityIdAndEntityTypeIdAndCalendarTypeId(Long entityId, Integer entityTypeId, Integer calendarTypeId);
|
||||
|
||||
@Query("from CalendarInstance ci where ci.entityId = :loanId and ci.entityTypeId = :entityTypeId")
|
||||
CalendarInstance findCalendarInstaneByLoanId(@Param("loanId") Long loanId, @Param("entityTypeId") Integer entityTypeId);
|
||||
|
||||
|
||||
Collection<CalendarInstance> findByCalendarIdAndEntityTypeId(Long calendarId, Integer entityTypeId);
|
||||
|
||||
/**Should use in clause, can I do it without creating a new class?**/
|
||||
@Query("from CalendarInstance ci where ci.entityId in (select id from Loan loan where loan.client.id = :clientId and loan.group.id=:groupId and (loan.loanStatus = 100 or loan.loanStatus = 200 or loan.loanStatus = 300)) and ci.entityTypeId = 3")
|
||||
List<CalendarInstance> findCalendarInstancesForActiveLoansByGroupIdAndClientId(@Param("clientId") Long clientId,
|
||||
@Param("groupId") Long groupId);
|
||||
}
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.calendar.domain;
|
||||
|
||||
import org.mifosplatform.portfolio.calendar.exception.CalendarInstanceNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Wrapper for {@link CalendarInstanceRepository} that is responsible for checking
|
||||
* if {@link CalendarInstance} is returned when using <code>findOne</code>
|
||||
* repository method and throwing an appropriate not found exception.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This is to avoid need for checking and throwing in multiple areas of code
|
||||
* base where {@link CalendarInstanceRepository} is required.
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class CalendarInstanceRepositoryWrapper {
|
||||
|
||||
private final CalendarInstanceRepository repository;
|
||||
|
||||
@Autowired
|
||||
public CalendarInstanceRepositoryWrapper(final CalendarInstanceRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public CalendarInstance findOneWithNotFoundDetection(final Long CalendarInstanceId) {
|
||||
final CalendarInstance calendatInstance = this.repository.findOne(CalendarInstanceId);
|
||||
if (calendatInstance == null) { throw new CalendarInstanceNotFoundException(CalendarInstanceId); }
|
||||
return calendatInstance;
|
||||
}
|
||||
|
||||
public void save(final CalendarInstance calendatInstance) {
|
||||
this.repository.save(calendatInstance);
|
||||
}
|
||||
|
||||
public void delete(final CalendarInstance calendatInstance) {
|
||||
this.repository.delete(calendatInstance);
|
||||
}
|
||||
|
||||
public void saveAndFlush(final CalendarInstance calendatInstance) {
|
||||
this.repository.saveAndFlush(calendatInstance);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.calendar.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when CalendarInstance resources are not found.
|
||||
*/
|
||||
public class CalendarInstanceNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public CalendarInstanceNotFoundException(final Long id) {
|
||||
super("error.msg.calendar.instance.id.invalid", "Calendar Instance with identifier " + id + " does not exist", id);
|
||||
}
|
||||
|
||||
public CalendarInstanceNotFoundException(final String postFix, final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.calendar.instance." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+5
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.calendar.service;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.calendar.data.CalendarData;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -23,9 +24,13 @@ public interface CalendarReadPlatformService {
|
||||
CalendarData retrieveNewCalendarDetails();
|
||||
|
||||
CalendarData generateRecurringDate(final CalendarData calendarData);
|
||||
|
||||
CalendarData generateRecurringDate(final CalendarData calendarData, final LocalDate tillDate);
|
||||
|
||||
Collection<CalendarData> generateRecurringDates(final Collection<CalendarData> calendarsData);
|
||||
|
||||
CalendarData retrieveLoanCalendar(final Long loanId);
|
||||
|
||||
CalendarData retrieveCollctionCalendarByEntity(final Long entityId, final Integer entityTypeId);
|
||||
|
||||
}
|
||||
|
||||
+37
-24
@@ -18,6 +18,7 @@ import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||
import org.mifosplatform.portfolio.calendar.data.CalendarData;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarType;
|
||||
import org.mifosplatform.portfolio.calendar.exception.CalendarNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@@ -71,7 +72,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
if (remindById != null && remindById != 0) remindBy = CalendarEnumerations.calendarRemindBy(remindById);
|
||||
final Integer firstReminder = rs.getInt("firstReminder");
|
||||
final Integer secondReminder = rs.getInt("secondReminder");
|
||||
final String humanReadable = CalendarHelper.getRRuleReadable(startDate, recurrence);
|
||||
final String humanReadable = CalendarUtils.getRRuleReadable(startDate, recurrence);
|
||||
|
||||
final LocalDate createdDate = JdbcSupport.getLocalDate(rs, "createdDate");
|
||||
final LocalDate lastUpdatedDate = JdbcSupport.getLocalDate(rs, "updatedDate");
|
||||
@@ -113,13 +114,27 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
sql = rm.schema() + " and ci.entity_id = ? and ci.entity_type_enum = ? order by c.start_date ";
|
||||
result = this.jdbcTemplate.query(sql, rm, new Object[] { entityId, entityTypeId });
|
||||
} else if (!calendarTypeOptions.isEmpty()) {
|
||||
String sqlCalendarTypeOptions = getSqlCalendarTypeOptionsInString(calendarTypeOptions);
|
||||
String sqlCalendarTypeOptions = CalendarUtils.getSqlCalendarTypeOptionsInString(calendarTypeOptions);
|
||||
sql = rm.schema() + " and ci.entity_id = ? and ci.entity_type_enum = ? and c.calendar_type_enum in ( " + sqlCalendarTypeOptions
|
||||
+ " ) order by c.start_date ";
|
||||
result = this.jdbcTemplate.query(sql, rm, new Object[] { entityId, entityTypeId });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarData retrieveCollctionCalendarByEntity(final Long entityId, final Integer entityTypeId) {
|
||||
final CalendarDataMapper rm = new CalendarDataMapper();
|
||||
|
||||
String sql = rm.schema() + " and ci.entity_id = ? and ci.entity_type_enum = ? and calendar_type_enum = ? order by c.start_date ";
|
||||
List<CalendarData> result = this.jdbcTemplate.query(sql, rm, new Object[] { entityId, entityTypeId, CalendarType.COLLECTION.getValue() });
|
||||
|
||||
if(!result.isEmpty() && result.size() > 0){
|
||||
return result.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CalendarData> retrieveParentCalendarsByEntity(final Long entityId, final Integer entityTypeId,
|
||||
@@ -137,7 +152,7 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
sql = rm.schema() + " " + parentHeirarchyCondition + " and ci.entity_type_enum = ? order by c.start_date ";
|
||||
result = this.jdbcTemplate.query(sql, rm, new Object[] { entityId, CalendarEntityType.CENTERS.getValue() });
|
||||
} else {
|
||||
String sqlCalendarTypeOptions = getSqlCalendarTypeOptionsInString(calendarTypeOptions);
|
||||
String sqlCalendarTypeOptions = CalendarUtils.getSqlCalendarTypeOptionsInString(calendarTypeOptions);
|
||||
sql = rm.schema() + " " + parentHeirarchyCondition + " and ci.entity_type_enum = ? and c.calendar_type_enum in ("
|
||||
+ sqlCalendarTypeOptions + ") order by c.start_date ";
|
||||
result = this.jdbcTemplate.query(sql, rm, new Object[] { entityId, CalendarEntityType.CENTERS.getValue() });
|
||||
@@ -162,6 +177,11 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
|
||||
@Override
|
||||
public CalendarData generateRecurringDate(final CalendarData calendarData) {
|
||||
return generateRecurringDate(calendarData, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalendarData generateRecurringDate(CalendarData calendarData, LocalDate tillDate) {
|
||||
if (!calendarData.isRepeating()) return calendarData;
|
||||
final String rrule = calendarData.getRecurrence();
|
||||
final LocalDate currentDate = DateUtils.getLocalDateOfTenant();
|
||||
@@ -172,13 +192,22 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
startDate = currentDate.minusYears(1);
|
||||
}
|
||||
|
||||
if (endDate == null || endDate.isAfter(currentDate.plusYears(1))) {
|
||||
if(tillDate != null){
|
||||
if(endDate != null){
|
||||
if(endDate.isAfter(tillDate)){
|
||||
endDate = tillDate;//to retrieve meeting dates till specified date (tillDate)
|
||||
}
|
||||
}else{
|
||||
endDate = tillDate;//end date is null then fetch meeting dates tillDate
|
||||
}
|
||||
}else if (endDate == null || endDate.isAfter(currentDate.plusYears(1))) {
|
||||
endDate = currentDate.plusYears(1);
|
||||
}
|
||||
|
||||
final Collection<LocalDate> recurringDates = CalendarHelper.getRecurringDates(rrule, seedDate, startDate, endDate, -1);
|
||||
final Collection<LocalDate> nextTenRecurringDates = CalendarHelper.getRecurringDates(rrule, seedDate, endDate);
|
||||
|
||||
final Collection<LocalDate> recurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, startDate, endDate, -1);
|
||||
final Collection<LocalDate> nextTenRecurringDates = CalendarUtils.getRecurringDates(rrule, seedDate, endDate);
|
||||
return new CalendarData(calendarData, recurringDates, nextTenRecurringDates);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,21 +267,5 @@ public class CalendarReadPlatformServiceImpl implements CalendarReadPlatformServ
|
||||
|
||||
return conditionSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* function returns a comma separated list of calendar_type_enum values ex.
|
||||
* 1,2,3,4
|
||||
*
|
||||
* @param calendarTypeOptions
|
||||
* @return
|
||||
*/
|
||||
public String getSqlCalendarTypeOptionsInString(final List<Integer> calendarTypeOptions) {
|
||||
String sqlCalendarTypeOptions = "";
|
||||
int size = calendarTypeOptions.size();
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(i).toString() + ",";
|
||||
}
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
|
||||
return sqlCalendarTypeOptions;
|
||||
}
|
||||
|
||||
}
|
||||
+60
-9
@@ -11,6 +11,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.fortuna.ical4j.model.Date;
|
||||
import net.fortuna.ical4j.model.DateList;
|
||||
@@ -32,10 +34,10 @@ import org.mifosplatform.organisation.workingdays.service.WorkingDaysUtil;
|
||||
import org.mifosplatform.portfolio.calendar.domain.Calendar;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
|
||||
public class CalendarHelper {
|
||||
public class CalendarUtils {
|
||||
|
||||
public static LocalDate getNextRecurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate startDate) {
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) { return null; }
|
||||
return getNextRecurringDate(recur, seedDate, startDate);
|
||||
}
|
||||
@@ -82,7 +84,7 @@ public class CalendarHelper {
|
||||
public static Collection<LocalDate> getRecurringDates(final String recurringRule, final LocalDate seedDate,
|
||||
final LocalDate periodStartDate, final LocalDate periodEndDate, final int maxCount) {
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
|
||||
return getRecurringDates(recur, seedDate, periodStartDate,
|
||||
periodEndDate, maxCount);
|
||||
@@ -210,7 +212,7 @@ public class CalendarHelper {
|
||||
|
||||
public static boolean isValidRedurringDate(final String recurringRule, final LocalDate seedDate, final LocalDate date){
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) { return false; }
|
||||
|
||||
return isValidRecurringDate(recur, seedDate, date);
|
||||
@@ -248,7 +250,7 @@ public class CalendarHelper {
|
||||
}
|
||||
|
||||
public static PeriodFrequencyType getMeetingPeriodFrequencyType(final String recurringRule){
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
PeriodFrequencyType meetingFrequencyType = PeriodFrequencyType.INVALID;
|
||||
if(recur.getFrequency().equals(Recur.DAILY)){
|
||||
meetingFrequencyType = PeriodFrequencyType.DAYS;
|
||||
@@ -277,12 +279,12 @@ public class CalendarHelper {
|
||||
}
|
||||
|
||||
public static int getInterval(final String recurringRule){
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
return recur.getInterval();
|
||||
}
|
||||
|
||||
public static LocalDate getFirstRepaymentMeetingDate(final Calendar calendar, final LocalDate disbursementDate, final Integer loanRepaymentInterval, final String frequency){
|
||||
final Recur recur = CalendarHelper.getICalRecur(calendar.getRecurrence());
|
||||
final Recur recur = CalendarUtils.getICalRecur(calendar.getRecurrence());
|
||||
if (recur == null) { return null; }
|
||||
LocalDate startDate = disbursementDate;
|
||||
final LocalDate seedDate = calendar.getStartDateLocalDate();
|
||||
@@ -310,7 +312,7 @@ public class CalendarHelper {
|
||||
}
|
||||
|
||||
public static LocalDate getNewRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate oldRepaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) { return null; }
|
||||
if(isValidRecurringDate(recur, seedDate, oldRepaymentDate)){
|
||||
return oldRepaymentDate;
|
||||
@@ -320,7 +322,7 @@ public class CalendarHelper {
|
||||
|
||||
public static LocalDate getNextRepaymentMeetingDate(final String recurringRule, final LocalDate seedDate, final LocalDate repaymentDate, final Integer loanRepaymentInterval, final String frequency, final WorkingDays workingDays){
|
||||
|
||||
final Recur recur = CalendarHelper.getICalRecur(recurringRule);
|
||||
final Recur recur = CalendarUtils.getICalRecur(recurringRule);
|
||||
if (recur == null) { return null; }
|
||||
LocalDate tmpDate = repaymentDate;
|
||||
if(isValidRecurringDate(recur, seedDate, repaymentDate)){
|
||||
@@ -364,4 +366,53 @@ public class CalendarHelper {
|
||||
if (oldRecur == null || oldRecur.getFrequency() == null || newRecur == null || newRecur.getFrequency() == null) { return false; }
|
||||
return (oldRecur.getInterval() == newRecur.getInterval());
|
||||
}
|
||||
|
||||
public static List<Integer> createIntegerListFromQueryParameter(String calendarTypeQuery) {
|
||||
List<Integer> calendarTypeOptions = new ArrayList<Integer>();
|
||||
// adding all calendar Types if query parameter is "all"
|
||||
if(calendarTypeQuery.equalsIgnoreCase("all")){
|
||||
calendarTypeOptions.add(1);
|
||||
calendarTypeOptions.add(2);
|
||||
calendarTypeOptions.add(3);
|
||||
calendarTypeOptions.add(4);
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
// creating a list of calendar type options from the comma separated query parameter.
|
||||
List<String> calendarTypeOptionsInQuery = new ArrayList<String>();
|
||||
StringTokenizer st = new StringTokenizer(calendarTypeQuery, ",");
|
||||
while (st.hasMoreElements()) {
|
||||
calendarTypeOptionsInQuery.add(st.nextElement().toString());
|
||||
}
|
||||
|
||||
for(String calType : calendarTypeOptionsInQuery){
|
||||
if(calType.equalsIgnoreCase("collection")) {
|
||||
calendarTypeOptions.add(1);
|
||||
} else if(calType.equalsIgnoreCase("training")) {
|
||||
calendarTypeOptions.add(2);
|
||||
} else if(calType.equalsIgnoreCase("audit")) {
|
||||
calendarTypeOptions.add(3);
|
||||
} else if(calType.equalsIgnoreCase("general")) {
|
||||
calendarTypeOptions.add(4);
|
||||
}
|
||||
}
|
||||
|
||||
return calendarTypeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* function returns a comma separated list of calendar_type_enum values ex.
|
||||
* 1,2,3,4
|
||||
*
|
||||
* @param calendarTypeOptions
|
||||
* @return
|
||||
*/
|
||||
public static String getSqlCalendarTypeOptionsInString(final List<Integer> calendarTypeOptions) {
|
||||
String sqlCalendarTypeOptions = "";
|
||||
int size = calendarTypeOptions.size();
|
||||
for (int i = 0; i < size - 1; i++) {
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(i).toString() + ",";
|
||||
}
|
||||
sqlCalendarTypeOptions += calendarTypeOptions.get(size - 1).toString();
|
||||
return sqlCalendarTypeOptions;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -128,7 +128,7 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr
|
||||
final Calendar calendarForUpdate = this.calendarRepository.findOne(calendarId);
|
||||
if (calendarForUpdate == null) { throw new CalendarNotFoundException(calendarId); }
|
||||
|
||||
final CalendarInstance calendarInstanceForUpdate = this.calendarInstanceRepository.findByCalendarAndEntityIdAndEntityTypeId(calendarId, entityId, entityTypeId);
|
||||
final CalendarInstance calendarInstanceForUpdate = this.calendarInstanceRepository.findByCalendarIdAndEntityIdAndEntityTypeId(calendarId, entityId, entityTypeId);
|
||||
this.calendarInstanceRepository.saveAndFlush(calendarInstanceForUpdate);
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(null) //
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user