diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 6bacd8f0f..dac8e30e2 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -7118,6 +7118,12 @@ Content-Type: application/json
| externalId |
| A place to put an external reference for this savings account e.g. The ID another system uses. If provided, it must be unique. |
+ | active |
+ | Indicates whether this savings account should go into active state or not automatically |
+
+ | activationDate |
+ | If active is true the activationDate must be provided. If the savings account has an entry for minRequiredOpeningBalance then a deposit for that amount with activationDate as the date is automatically entered. |
+
| interestRate |
| The default interest rate set when creating savings accounts of this type of product. e.g. 5% Per year |
@@ -7257,7 +7263,7 @@ Content-Type: application/json
Mandatory Fields |
- | clientId or groupId, productId, accountNo, externalId |
+ | clientId or groupId, productId, accountNo, externalId, active, (activationDate if active is true) |
@@ -7273,27 +7279,29 @@ Content-Type: application/json
Minimal request: accountNo auto generated, remaining details inherited from savings product.
POST https://Domain Name/api/v1/savingsaccounts
-
POST savingaccount
-Content-Type: application/json
-Request Body:
-{
- "clientId": 1,
- "productId": 1
-}
-
-
Minimal request: accountNo provided (must be unique), remaining details inherited from savings product.
-
POST savingaccount
+ POST savingsaccount
Content-Type: application/json
Request Body:
{
"clientId": 1,
"productId": 1,
+ "active": false
+}
+
+ Minimal request: accountNo provided (must be unique), remaining details inherited from savings product.
+ POST savingsaccount
+Content-Type: application/json
+Request Body:
+{
+ "clientId": 1,
+ "productId": 1,
+ "active": false,
"accountNo": "SA000023",
"externalId": "SYS-23"
}
Full request: accountNo provided (must be unique), remaining details override details from savings product (except currency).
- POST savingaccount
+ POST savingsaccount
Content-Type: application/json
Request Body:
{
@@ -7301,7 +7309,10 @@ Request Body:
"productId": 1,
"accountNo": "SA000023",
"externalId": "SYS-23",
- "locale": "en",
+ "active": true,
+ "locale": "en",
+ "dateFormat": "dd MMMM yyyy",
+ "activationDate": "01 March 2011",
"interestRate": "5.65",
"interestRatePeriodFrequencyType": 2,
"minRequiredOpeningBalance": "1,000",
@@ -7313,6 +7324,35 @@ Request Body:
{
"officeId": 1,
"clientId": 1,
+ "savingsId": 1,
+ "resourceId": 1
+}
+
+
+
+
+
+
+
+
Activate a Savings Account
+
Activates a savings account.
+
+
+
POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=activate
+
POST savingsaccount/1?command=activate
+Content-Type: application/json
+Request Body:
+{
+ "locale": "en",
+ "dateFormat": "dd MMMM yyyy",
+ "activationDate": "01 March 2011"
+}
+
+
+{
+ "officeId": 1,
+ "clientId": 1,
+ "savingsId": 1,
"resourceId": 1
}
@@ -11436,6 +11476,14 @@ Content-Type: application/json
Delete a Savings Account |
+ |
+ savingsaccounts/{accountId}?command=activate |
+ Activate a Savings Account |
+ |
+ |
+ |
+
+
| Savings Transactions |
savingsaccounts/{accountId}/transactions?command=deposit |
Make a Deposit |
@@ -11443,7 +11491,7 @@ Content-Type: application/json
|
|
-
+
|
savingsaccounts/{accountId}/transactions?command=withdrawal |
Make a Withdrawal |
@@ -11467,7 +11515,6 @@ Content-Type: application/json
Update an Office |
|
-
| CURRENCY |
currencies |
diff --git a/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql b/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql
index 4a144c76a..da3731065 100644
--- a/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql
+++ b/mifosng-db/0001a-mifosplatform-core-ddl-latest.sql
@@ -729,6 +729,7 @@ CREATE TABLE `m_savings_product` (
UNIQUE KEY `sp_unq_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
CREATE TABLE `m_savings_account` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`account_no` varchar(20) NOT NULL,
@@ -736,6 +737,8 @@ CREATE TABLE `m_savings_account` (
`client_id` bigint(20) DEFAULT NULL,
`group_id` bigint(20) DEFAULT NULL,
`product_id` bigint(20) DEFAULT NULL,
+ `status_enum` SMALLINT(5) NOT NULL DEFAULT 300,
+ `activation_date` DATE DEFAULT NULL,
`currency_code` varchar(3) NOT NULL,
`currency_digits` smallint(5) NOT NULL,
`nominal_interest_rate_per_period` decimal(19,6) NOT NULL,
@@ -744,6 +747,7 @@ CREATE TABLE `m_savings_account` (
`min_required_opening_balance` decimal(19,6) DEFAULT NULL,
`lockin_period_frequency` decimal(19,6) DEFAULT NULL,
`lockin_period_frequency_enum` smallint(5) DEFAULT NULL,
+ `lockedin_until_date_derived` DATE DEFAULT NULL,
`total_deposits_derived` decimal(19,6) DEFAULT NULL,
`total_withdrawals_derived` decimal(19,6) DEFAULT NULL,
`total_interest_posted_derived` decimal(19,6) DEFAULT NULL,
diff --git a/mifosng-db/0002-mifosx-base-reference-data-utf8.sql b/mifosng-db/0002-mifosx-base-reference-data-utf8.sql
index f6e7d9b0b..23819b5d5 100644
--- a/mifosng-db/0002-mifosx-base-reference-data-utf8.sql
+++ b/mifosng-db/0002-mifosx-base-reference-data-utf8.sql
@@ -17,19 +17,36 @@ INSERT INTO `r_enum_value`
VALUES
('amortization_method_enum',0,'Equal principle payments','Equal principle payments'),
('amortization_method_enum',1,'Equal installments','Equal installments'),
-('interest_calculated_in_period_enum',0,'Daily','Daily'),('interest_calculated_in_period_enum',1,'Same as repayment period','Same as repayment period'),
-('interest_method_enum',0,'Declining Balance','Declining Balance'),('interest_method_enum',1,'Flat','Flat'),
-('interest_period_frequency_enum',2,'Per month','Per month'),('interest_period_frequency_enum',3,'Per year','Per year'),
-('loan_status_id',100,'Submitted and awaiting approval','Submitted and awaiting approval'),('loan_status_id',200,'Approved','Approved'),
-('loan_status_id',300,'Active','Active'),('loan_status_id',400,'Withdrawn by client','Withdrawn by client'),('loan_status_id',500,'Rejected','Rejected'),
-('loan_status_id',600,'Closed','Closed'),('loan_status_id',601,'Written-Off','Written-Off'),('loan_status_id',602,'Rescheduled','Rescheduled'),('loan_status_id',700,'Overpaid','Overpaid'),
-('loan_transaction_strategy_id',1,'mifos-standard-strategy','Mifos style'),('loan_transaction_strategy_id',2,'heavensfamily-strategy','Heavensfamily'),
-('loan_transaction_strategy_id',3,'creocore-strategy','Creocore'),('loan_transaction_strategy_id',4,'rbi-india-strategy','RBI (India)'),
-('processing_result_enum',0,'invalid','Invalid'),('processing_result_enum',1,'processed','Processed'),
-('processing_result_enum',2,'awaiting.approval','Awaiting Approval'),('processing_result_enum',3,'rejected','Rejected'),
-('repayment_period_frequency_enum',0,'Days','Days'),('repayment_period_frequency_enum',1,'Weeks','Weeks'),
-('repayment_period_frequency_enum',2,'Months','Months'),('term_period_frequency_enum',0,'Days','Days'),
-('term_period_frequency_enum',1,'Weeks','Weeks'),('term_period_frequency_enum',2,'Months','Months'),('term_period_frequency_enum',3,'Years','Years');
+('interest_calculated_in_period_enum',0,'Daily','Daily'),
+('interest_calculated_in_period_enum',1,'Same as repayment period','Same as repayment period'),
+('interest_method_enum',0,'Declining Balance','Declining Balance'),
+('interest_method_enum',1,'Flat','Flat'),
+('interest_period_frequency_enum',2,'Per month','Per month'),
+('interest_period_frequency_enum',3,'Per year','Per year'),
+('loan_status_id',100,'Submitted and awaiting approval','Submitted and awaiting approval'),
+('loan_status_id',200,'Approved','Approved'),
+('loan_status_id',300,'Active','Active'),
+('loan_status_id',400,'Withdrawn by client','Withdrawn by client'),
+('loan_status_id',500,'Rejected','Rejected'),
+('loan_status_id',600,'Closed','Closed'),
+('loan_status_id',601,'Written-Off','Written-Off'),
+('loan_status_id',602,'Rescheduled','Rescheduled'),
+('loan_status_id',700,'Overpaid','Overpaid'),
+('loan_transaction_strategy_id',1,'mifos-standard-strategy','Mifos style'),
+('loan_transaction_strategy_id',2,'heavensfamily-strategy','Heavensfamily'),
+('loan_transaction_strategy_id',3,'creocore-strategy','Creocore'),
+('loan_transaction_strategy_id',4,'rbi-india-strategy','RBI (India)'),
+('processing_result_enum',0,'invalid','Invalid'),
+('processing_result_enum',1,'processed','Processed'),
+('processing_result_enum',2,'awaiting.approval','Awaiting Approval'),
+('processing_result_enum',3,'rejected','Rejected'),
+('repayment_period_frequency_enum',0,'Days','Days'),
+('repayment_period_frequency_enum',1,'Weeks','Weeks'),
+('repayment_period_frequency_enum',2,'Months','Months'),
+('term_period_frequency_enum',0,'Days','Days'),
+('term_period_frequency_enum',1,'Weeks','Weeks'),
+('term_period_frequency_enum',2,'Months','Months'),
+('term_period_frequency_enum',3,'Years','Years');
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`)
VALUES ('transaction_type_enum', '1', 'Disbursement', 'Disbursement');
@@ -64,7 +81,6 @@ VALUES ('transaction_type_enum', '10', 'Apply Charges', 'Apply Charges');
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`)
VALUES ('transaction_type_enum', '11', 'Apply Interest', 'Apply Interest');
-
INSERT INTO `m_currency`
(`id`,`code`,`decimal_places`,`display_symbol`,`name`, `internationalized_name_code`)
VALUES
diff --git a/mifosng-db/0003-mifosx-permissions-and-authorisation-utf8.sql b/mifosng-db/0003-mifosx-permissions-and-authorisation-utf8.sql
index 652fa17d6..6836d79a6 100644
--- a/mifosng-db/0003-mifosx-permissions-and-authorisation-utf8.sql
+++ b/mifosng-db/0003-mifosx-permissions-and-authorisation-utf8.sql
@@ -263,7 +263,9 @@ INSERT INTO `m_permission`
('transaction_savings', 'DEPOSIT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'DEPOSIT', '1'),
('transaction_savings', 'DEPOSIT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'DEPOSIT', '0'),
('transaction_savings', 'WITHDRAWAL_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'WITHDRAWAL', '1'),
-('transaction_savings', 'WITHDRAWAL_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'WITHDRAWAL', '0');
+('transaction_savings', 'WITHDRAWAL_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'WITHDRAWAL', '0'),
+('transaction_savings', 'ACTIVATE_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'ACTIVATE', '1'),
+('transaction_savings', 'ACTIVATE_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'ACTIVATE', '0');
-- == accounting related permissions
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES
diff --git a/mifosng-db/patches/1-add-status-to-savings-account.sql b/mifosng-db/patches/1-add-status-to-savings-account.sql
new file mode 100644
index 000000000..282789e08
--- /dev/null
+++ b/mifosng-db/patches/1-add-status-to-savings-account.sql
@@ -0,0 +1,16 @@
+ALTER TABLE `m_savings_account`
+ADD COLUMN `status_enum` SMALLINT(5) NOT NULL DEFAULT 300 AFTER `product_id` ;
+
+ALTER TABLE `m_savings_account`
+ADD COLUMN `activation_date` DATE DEFAULT NULL AFTER `status_enum`;
+
+ALTER TABLE `m_savings_account`
+ADD COLUMN `lockedin_until_date_derived` DATE DEFAULT NULL AFTER `lockin_period_frequency_enum`;
+
+ALTER TABLE `m_portfolio_command_source`
+ADD COLUMN `savings_id` BIGINT(20) NULL DEFAULT NULL AFTER `loan_id` ;
+
+INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
+VALUES
+('transaction_savings', 'ACTIVATE_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'ACTIVATE', '1'),
+('transaction_savings', 'ACTIVATE_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'ACTIVATE', '0');
\ No newline at end of file
diff --git a/mifosng-provider/src/integrationTest/java/ClientLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/ClientLoanIntegrationTest.java
index 649873eb9..9709cd442 100644
--- a/mifosng-provider/src/integrationTest/java/ClientLoanIntegrationTest.java
+++ b/mifosng-provider/src/integrationTest/java/ClientLoanIntegrationTest.java
@@ -1,4 +1,17 @@
+import static com.jayway.restassured.RestAssured.given;
+import static com.jayway.restassured.RestAssured.post;
+import static com.jayway.restassured.path.json.JsonPath.from;
+import static junit.framework.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Random;
+
+import org.junit.Before;
+import org.junit.Test;
+
import com.google.gson.Gson;
import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.builder.ResponseSpecBuilder;
@@ -6,22 +19,11 @@ import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.specification.RequestSpecification;
import com.jayway.restassured.specification.ResponseSpecification;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Random;
-
-import static com.jayway.restassured.RestAssured.given;
-import static com.jayway.restassured.RestAssured.post;
-import static com.jayway.restassured.path.json.JsonPath.from;
-import static junit.framework.Assert.assertEquals;
/**
* Client Loan Integration Test for checking Loan Application Repayment Schedule.
*/
+@SuppressWarnings({ "rawtypes", "unchecked" })
public class ClientLoanIntegrationTest {
String basicAuthKey;
ResponseSpecification responseSpec;
@@ -70,7 +72,7 @@ public class ClientLoanIntegrationTest {
return from(json).get("clientId");
}
- private void checkClientCreatedOnServer(Integer generatedClientID) {
+ private void checkClientCreatedOnServer(final Integer generatedClientID) {
System.out.println("------------------------------CHECK CLIENT DETAILS------------------------------------\n");
given().spec(requestSpec)
.expect().spec(responseSpec)
@@ -86,14 +88,14 @@ public class ClientLoanIntegrationTest {
return from(json).get("resourceId");
}
- private void applyForLoanApplication(Integer clientID, Integer loanProductID) {
+ private void applyForLoanApplication(final Integer clientID, final Integer loanProductID) {
System.out.println("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
given().spec(requestSpec).body(getLoanApplicationBodyAsJSON(clientID.toString(), loanProductID.toString()))
.expect().spec(responseSpec)
.when().post("/mifosng-provider/api/v1/loans?tenantIdentifier=default");
}
- private ArrayList getLoanRepaymentSchedule(Integer productID)
+ private ArrayList getLoanRepaymentSchedule(final Integer productID)
{
System.out.println("---------------------------GETTING LOAN REPAYMENT SCHEDULE--------------------------------");
String json = given().spec(requestSpec).body(getLoanCalculationBodyAsJSON(productID.toString()))
@@ -102,7 +104,7 @@ public class ClientLoanIntegrationTest {
return from(json).get("periods");
}
- private void verifyLoanRepaymentSchedule(ArrayList loanSchedule) {
+ private void verifyLoanRepaymentSchedule(final ArrayList loanSchedule) {
System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
assertEquals("Checking for Due Date for 1st Month",new ArrayList(Arrays.asList(2011, 10, 20)),loanSchedule.get(1).get("dueDate"));
@@ -156,7 +158,7 @@ public class ClientLoanIntegrationTest {
return new Gson().toJson(map);
}
- private String getLoanApplicationBodyAsJSON(String clientID,String productID){
+ private String getLoanApplicationBodyAsJSON(final String clientID,final String productID){
HashMap map = new HashMap();
map.put("dateFormat", "dd MMMM yyyy");
map.put("locale", "en_GB");
@@ -179,7 +181,7 @@ public class ClientLoanIntegrationTest {
return new Gson().toJson(map);
}
- private String getLoanCalculationBodyAsJSON(String productID){
+ private String getLoanCalculationBodyAsJSON(final String productID){
HashMap map = new HashMap();
map.put("dateFormat", "dd MMMM yyyy");
map.put("locale", "en_GB");
@@ -200,15 +202,15 @@ public class ClientLoanIntegrationTest {
return new Gson().toJson(map);
}
- public String randomIDGenerator(String prefix, int lenOfRandomSuffix) {
+ public String randomIDGenerator(final String prefix, final int lenOfRandomSuffix) {
return randomStringGenerator(prefix,lenOfRandomSuffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
- public String randomNameGenerator(String prefix, int lenOfRandomSuffix) {
+ public String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) {
return randomStringGenerator(prefix,lenOfRandomSuffix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
- private String randomStringGenerator(String prefix,int len, String sourceSetString) {
+ private String randomStringGenerator(final String prefix,final int len, final String sourceSetString) {
int lengthOfSource = sourceSetString.length();
Random rnd = new Random();
StringBuilder sb = new StringBuilder(len);
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java
index 7261580fa..fe2c48cc6 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java
@@ -47,6 +47,10 @@ public class CommandSource extends AbstractPersistable {
@Column(name = "loan_id")
private Long loanId;
+ @SuppressWarnings("unused")
+ @Column(name = "savings_id")
+ private Long savingsId;
+
@Column(name = "api_get_url", length = 100)
private String resourceGetUrl;
@@ -165,11 +169,12 @@ public class CommandSource extends AbstractPersistable {
this.processingResult = CommandProcessingResultType.AWAITING_APPROVAL.getValue();
}
- public void updateForAudit(final Long officeId, final Long groupId, final Long clientId, final Long loanId) {
+ public void updateForAudit(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savignsId) {
this.officeId = officeId;
this.groupId = groupId;
this.clientId = clientId;
this.loanId = loanId;
+ this.savingsId = savignsId;
}
public String getResourceGetUrl() {
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
index 0c773fc24..da98c5f3d 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java
@@ -31,12 +31,12 @@ public class CommandWrapper {
}
public static CommandWrapper fromExistingCommand(final Long commandId, final String actionName, final String entityName,
- final Long resourceId, final Long subresourceId, final String resourceGetUrl) {
+ final Long resourceId, final Long subresourceId, final String resourceGetUrl) {
return new CommandWrapper(commandId, actionName, entityName, resourceId, subresourceId, resourceGetUrl);
}
- private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId, final Long subresourceId,
- final String resourceGetUrl) {
+ private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId,
+ final Long subresourceId, final String resourceGetUrl) {
this.commandId = commandId;
this.officeId = null;
this.groupId = null;
@@ -54,13 +54,12 @@ public class CommandWrapper {
this.href = resourceGetUrl;
this.json = null;
this.transactionId = null;
-
+
}
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
- final String actionName, final String entityName, final Long entityId, final Long subentityId,
- final Long codeId, final String supportedEntityType, final Long supportedEntityId, final String href, final String json,
- final String transactionId) {
+ final String actionName, final String entityName, final Long entityId, final Long subentityId, final Long codeId,
+ final String supportedEntityType, final Long supportedEntityId, final String href, final String json, final String transactionId) {
this.commandId = null;
this.officeId = officeId;
this.groupId = groupId;
@@ -95,7 +94,7 @@ public class CommandWrapper {
public Long resourceId() {
return this.entityId;
}
-
+
public Long subresourceId() {
return this.subentityId;
}
@@ -135,7 +134,7 @@ public class CommandWrapper {
public Long getEntityId() {
return this.entityId;
}
-
+
public Long getSubentityId() {
return this.subentityId;
}
@@ -354,12 +353,12 @@ public class CommandWrapper {
return this.actionName.equalsIgnoreCase("BULKREASSIGN") && this.entityName.equalsIgnoreCase("LOAN");
}
- public boolean isDatatableResource() {
+ public boolean isDatatableResource() {
return this.href.startsWith("/datatables/");
}
public boolean isDeleteOneToOne() {
- /* also covers case of deleting all of a one to many*/
+ /* also covers case of deleting all of a one to many */
return isDatatableResource() && isDeleteOperation() && this.subentityId == null;
}
@@ -431,6 +430,10 @@ public class CommandWrapper {
return this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
}
+ public boolean isSavingsAccountActivation() {
+ return this.actionName.equalsIgnoreCase("ACTIVATE") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
+ }
+
public boolean isSavingsAccountDeposit() {
return this.actionName.equalsIgnoreCase("DEPOSIT") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
}
@@ -446,8 +449,8 @@ public class CommandWrapper {
public boolean isNoteResource() {
boolean isnoteResource = false;
if (this.entityName.equalsIgnoreCase("CLIENTNOTE") || this.entityName.equalsIgnoreCase("LOANNOTE")
- || this.entityName.equalsIgnoreCase("LOANTRANSACTIONNOTE") || this.entityName.equalsIgnoreCase("DEPOSITNOTE")
- || this.entityName.equalsIgnoreCase("SAVINGNOTE") || this.entityName.equalsIgnoreCase("GROUPNOTE")) {
+ || this.entityName.equalsIgnoreCase("LOANTRANSACTIONNOTE") || this.entityName.equalsIgnoreCase("SAVINGNOTE")
+ || this.entityName.equalsIgnoreCase("GROUPNOTE")) {
isnoteResource = true;
}
return isnoteResource;
@@ -456,5 +459,4 @@ public class CommandWrapper {
public boolean isGroupResource() {
return this.entityName.equalsIgnoreCase("GROUP");
}
-
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
index 86890da1e..564a1ca53 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java
@@ -686,10 +686,19 @@ public class CommandWrapperBuilder {
return this;
}
+ public CommandWrapperBuilder savingsAccountActivation(final Long accountId) {
+ this.actionName = "ACTIVATE";
+ this.entityName = "SAVINGSACCOUNT";
+ this.savingsId = accountId;
+ this.entityId = null;
+ this.href = "/savingsaccounts/" + accountId + "?command=activate";
+ return this;
+ }
+
public CommandWrapperBuilder savingsAccountDeposit(final Long accountId) {
this.actionName = "DEPOSIT";
this.entityName = "SAVINGSACCOUNT";
- this.loanId = accountId;
+ this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "/transactions";
return this;
@@ -698,7 +707,7 @@ public class CommandWrapperBuilder {
public CommandWrapperBuilder savingsAccountWithdrawal(final Long accountId) {
this.actionName = "WITHDRAWAL";
this.entityName = "SAVINGSACCOUNT";
- this.loanId = accountId;
+ this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "/transactions";
return this;
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
index e3d4af282..1549942cc 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
@@ -69,7 +69,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker);
}
commandSourceResult.updateResourceId(result.resourceId());
- commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId());
+ commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId(),
+ result.getSavingsId());
String changesOnlyJson = null;
if (result.hasChanges()) {
@@ -360,6 +361,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = applicationContext.getBean("depositSavingsAccountCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isSavingsAccountWithdrawal()) {
handler = applicationContext.getBean("withdrawSavingsAccountCommandHandler", NewCommandSourceHandler.class);
+ } else if (wrapper.isSavingsAccountActivation()) {
+ handler = applicationContext.getBean("activateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
index 4c83e8d65..c5aa63a90 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java
@@ -8,6 +8,7 @@ package org.mifosplatform.infrastructure.core.api;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
+import java.util.Locale;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
@@ -377,4 +378,8 @@ public final class JsonCommand {
final PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(saltValue, "", passwordPlainText);
return platformPasswordEncoder.encode(dummyPlatformUser);
}
+
+ public Locale extractLocale() {
+ return this.fromApiJsonHelper.extractLocaleParameter(this.parsedCommand.getAsJsonObject());
+ }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/ApiGlobalErrorResponse.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/ApiGlobalErrorResponse.java
index 64e814cb5..c68648b46 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/ApiGlobalErrorResponse.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/ApiGlobalErrorResponse.java
@@ -22,12 +22,6 @@ public class ApiGlobalErrorResponse {
*/
private String developerMessage;
- /**
- * A link to a URL which provides more information on the details of this
- * type of error.
- */
- private String developerDocLink;
-
/**
* The HTTP status code of the response.
*/
@@ -57,7 +51,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("401");
globalErrorResponse.setDeveloperMessage("Invalid authentication details were passed in api request.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authenticated");
globalErrorResponse.setDefaultUserMessage("Unauthenticated. Please login.");
@@ -69,7 +62,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("401");
globalErrorResponse.setDeveloperMessage("Invalid tenant details were passed in api request.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.invalid.tenant.identifier");
globalErrorResponse.setDefaultUserMessage("Invalide tenant identifier provided with request.");
@@ -81,7 +73,6 @@ public class ApiGlobalErrorResponse {
globalErrorResponse.setHttpStatusCode("403");
globalErrorResponse
.setDeveloperMessage("The user associated with credentials passed on this request does not have sufficient privileges to perform this action.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.not.authorized");
globalErrorResponse.setDefaultUserMessage("Insufficient privileges to perform this action.");
@@ -97,7 +88,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("403");
globalErrorResponse.setDeveloperMessage("Request was understood but caused a domain rule violation.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("validation.msg.domain.rule.violation");
globalErrorResponse.setDefaultUserMessage("Errors contain reason for domain rule violation.");
@@ -114,7 +104,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("404");
globalErrorResponse.setDeveloperMessage("The requested resource is not available.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.resource.not.found");
globalErrorResponse.setDefaultUserMessage("The requested resource is not available.");
@@ -131,7 +120,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("403");
globalErrorResponse.setDeveloperMessage("The request caused a data integrity issue to be fired by the database.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
@@ -149,7 +137,6 @@ public class ApiGlobalErrorResponse {
globalErrorResponse.setHttpStatusCode("400");
globalErrorResponse
.setDeveloperMessage("The request was invalid. This typically will happen due to validation errors which are provided.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode);
globalErrorResponse.setDefaultUserMessage(defaultUserMessage);
@@ -164,7 +151,6 @@ public class ApiGlobalErrorResponse {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("500");
globalErrorResponse.setDeveloperMessage("An unexpected error occured on the platform server.");
- globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.platform.server.side.error");
globalErrorResponse.setDefaultUserMessage("An unexpected error occured on the platform server.");
@@ -224,12 +210,4 @@ public class ApiGlobalErrorResponse {
public void setUserMessageGlobalisationCode(final String userMessageGlobalisationCode) {
this.userMessageGlobalisationCode = userMessageGlobalisationCode;
}
-
- public String getDeveloperDocLink() {
- return developerDocLink;
- }
-
- public void setDeveloperDocLink(final String developerDocLink) {
- this.developerDocLink = developerDocLink;
- }
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exception/PlatformApiDataValidationException.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exception/PlatformApiDataValidationException.java
index b5d8ee6c5..7eecc0f81 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exception/PlatformApiDataValidationException.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exception/PlatformApiDataValidationException.java
@@ -9,14 +9,23 @@ import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
+/**
+ * Exception thrown when problem with an API request to the platform.
+ */
public class PlatformApiDataValidationException extends RuntimeException {
private final String globalisationMessageCode;
private final String defaultUserMessage;
private final List errors;
+ public PlatformApiDataValidationException(final List errors) {
+ this.globalisationMessageCode = "validation.msg.validation.errors.exist";
+ this.defaultUserMessage = "Validation errors exist.";
+ this.errors = errors;
+ }
+
public PlatformApiDataValidationException(final String globalisationMessageCode, final String defaultUserMessage,
- List errors) {
+ final List errors) {
this.globalisationMessageCode = globalisationMessageCode;
this.defaultUserMessage = defaultUserMessage;
this.errors = errors;
@@ -33,4 +42,4 @@ public class PlatformApiDataValidationException extends RuntimeException {
public List getErrors() {
return errors;
}
-}
+}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exceptionmapper/PlatformApiDataValidationExceptionMapper.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exceptionmapper/PlatformApiDataValidationExceptionMapper.java
index 6e274482c..17cf81e50 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exceptionmapper/PlatformApiDataValidationExceptionMapper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/exceptionmapper/PlatformApiDataValidationExceptionMapper.java
@@ -29,11 +29,11 @@ import org.springframework.stereotype.Component;
public class PlatformApiDataValidationExceptionMapper implements ExceptionMapper {
@Override
- public Response toResponse(PlatformApiDataValidationException exception) {
+ public Response toResponse(final PlatformApiDataValidationException exception) {
- ApiGlobalErrorResponse dataIntegrityError = ApiGlobalErrorResponse.badClientRequest(exception.getGlobalisationMessageCode(),
+ final ApiGlobalErrorResponse dataValidationErrorResponse = ApiGlobalErrorResponse.badClientRequest(exception.getGlobalisationMessageCode(),
exception.getDefaultUserMessage(), exception.getErrors());
- return Response.status(Status.BAD_REQUEST).entity(dataIntegrityError).type(MediaType.APPLICATION_JSON).build();
+ return Response.status(Status.BAD_REQUEST).entity(dataValidationErrorResponse).type(MediaType.APPLICATION_JSON).build();
}
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/CannotUpdateOfficeWithParentOfficeSameAsSelf.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/CannotUpdateOfficeWithParentOfficeSameAsSelf.java
index a6df4071a..bbc92273b 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/CannotUpdateOfficeWithParentOfficeSameAsSelf.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/CannotUpdateOfficeWithParentOfficeSameAsSelf.java
@@ -10,10 +10,9 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRul
/**
* Exception thrown when an attempt is made update the parent of a root office.
*/
-public class CannotUpdateOfficeWithParentOfficeSameAsSelf extends
- AbstractPlatformDomainRuleException {
+public class CannotUpdateOfficeWithParentOfficeSameAsSelf extends AbstractPlatformDomainRuleException {
- public CannotUpdateOfficeWithParentOfficeSameAsSelf(final Long officeId, final Long parentId) {
- super("error.msg.office.parentId.same.as.id", "Cannot update office with parent same as self.", officeId, parentId);
- }
+ public CannotUpdateOfficeWithParentOfficeSameAsSelf(final Long officeId, final Long parentId) {
+ super("error.msg.office.parentId.same.as.id", "Cannot update office with parent same as self.", officeId, parentId);
+ }
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/RootOfficeParentCannotBeUpdated.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/RootOfficeParentCannotBeUpdated.java
index 11d490c40..779eb3ba0 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/RootOfficeParentCannotBeUpdated.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/office/exception/RootOfficeParentCannotBeUpdated.java
@@ -10,10 +10,9 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRul
/**
* Exception thrown when an attempt is made update the parent of a root office.
*/
-public class RootOfficeParentCannotBeUpdated extends
- AbstractPlatformDomainRuleException {
+public class RootOfficeParentCannotBeUpdated extends AbstractPlatformDomainRuleException {
- public RootOfficeParentCannotBeUpdated() {
- super("error.msg.office.cannot.update.parent.office.of.root.office", "The root office must not be set with a parent office.");
- }
+ public RootOfficeParentCannotBeUpdated() {
+ super("error.msg.office.cannot.update.parent.office.of.root.office", "The root office must not be set with a parent office.");
+ }
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/PeriodFrequencyType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/PeriodFrequencyType.java
index c63507c67..83bb83ea1 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/PeriodFrequencyType.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/domain/PeriodFrequencyType.java
@@ -29,24 +29,22 @@ public enum PeriodFrequencyType {
}
public static PeriodFrequencyType fromInt(final Integer frequency) {
-
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.INVALID;
- switch (frequency) {
- case 0:
- repaymentFrequencyType = PeriodFrequencyType.DAYS;
- break;
- case 1:
- repaymentFrequencyType = PeriodFrequencyType.WEEKS;
- break;
- case 2:
- repaymentFrequencyType = PeriodFrequencyType.MONTHS;
- break;
- case 3:
- repaymentFrequencyType = PeriodFrequencyType.YEARS;
- break;
- default:
- repaymentFrequencyType = PeriodFrequencyType.INVALID;
- break;
+ if (frequency != null) {
+ switch (frequency) {
+ case 0:
+ repaymentFrequencyType = PeriodFrequencyType.DAYS;
+ break;
+ case 1:
+ repaymentFrequencyType = PeriodFrequencyType.WEEKS;
+ break;
+ case 2:
+ repaymentFrequencyType = PeriodFrequencyType.MONTHS;
+ break;
+ case 3:
+ repaymentFrequencyType = PeriodFrequencyType.YEARS;
+ break;
+ }
}
return repaymentFrequencyType;
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountTransactionsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountTransactionsApiResource.java
index 3c899d02a..bc682f004 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountTransactionsApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountTransactionsApiResource.java
@@ -96,7 +96,10 @@ public class SavingsAccountTransactionsApiResource {
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
- if (result == null) { throw new UnrecognizedQueryParamException("command", commandParam); }
+ if (result == null) {
+ // FIXME - KW - handle blank command param use case
+ throw new UnrecognizedQueryParamException("command", commandParam);
+ }
return this.toApiJsonSerializer.serialize(result);
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountsApiResource.java
index e08bc23f7..c6b225eeb 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountsApiResource.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsAccountsApiResource.java
@@ -23,6 +23,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
+import org.apache.commons.lang.StringUtils;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
@@ -30,6 +31,7 @@ import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
+import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
@@ -183,6 +185,33 @@ public class SavingsAccountsApiResource {
return this.toApiJsonSerializer.serialize(result);
}
+ @POST
+ @Path("{accountId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String activate(@PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam,
+ final String apiRequestBodyAsJson) {
+
+ final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
+
+ CommandProcessingResult result = null;
+ if (is(commandParam, "activate")) {
+ final CommandWrapper commandRequest = builder.savingsAccountActivation(accountId).build();
+ result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
+ }
+
+ if (result == null) {
+ // FIXME - KW - handle blank command param use case
+ throw new UnrecognizedQueryParamException("command", commandParam);
+ }
+
+ return this.toApiJsonSerializer.serialize(result);
+ }
+
+ private boolean is(final String commandParam, final String commandValue) {
+ return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
+ }
+
@DELETE
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsApiConstants.java
index 23ea132f1..92fa39d42 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsApiConstants.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/api/SavingsApiConstants.java
@@ -21,9 +21,12 @@ public class SavingsApiConstants {
public static final String idParamName = "id";
public static final String accountNoParamName = "accountNo";
public static final String externalIdParamName = "externalId";
+ public static final String statusParamName = "status";
public static final String clientIdParamName = "clientId";
public static final String groupIdParamName = "groupId";
public static final String productIdParamName = "productId";
+ public static final String activeParamName = "active";
+ public static final String activationDateParamName = "activationDate";
public static final String nameParamName = "name";
public static final String descriptionParamName = "description";
public static final String currencyCodeParamName = "currencyCode";
@@ -55,9 +58,9 @@ public class SavingsApiConstants {
"lockinPeriodFrequencyTypeOptions"));
public static final Set SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet(Arrays.asList(localeParamName,
- accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName, interestRateParamName,
- interestRatePeriodFrequencyTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
- lockinPeriodFrequencyTypeParamName));
+ dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName,
+ activeParamName, activationDateParamName, interestRateParamName, interestRatePeriodFrequencyTypeParamName,
+ minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
/**
* These parameters will match the class level parameters of
@@ -65,14 +68,18 @@ public class SavingsApiConstants {
* parameters to match those of request parameters.
*/
public static final Set SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList(idParamName,
- accountNoParamName, externalIdParamName, clientIdParamName, "clientName", groupIdParamName, "groupName", "savingsProductId",
- "savingsProductName", "currency", interestRateParamName, interestRatePeriodFrequencyTypeParamName, "annualInterestRate",
- minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, "summary",
- "transactions", "productOptions", "interestRatePeriodFrequencyTypeOptions", "lockinPeriodFrequencyTypeOptions"));
+ accountNoParamName, externalIdParamName, statusParamName, activationDateParamName, clientIdParamName, "clientName",
+ groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", interestRateParamName,
+ interestRatePeriodFrequencyTypeParamName, "annualInterestRate", minRequiredOpeningBalanceParamName,
+ lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, "summary", "transactions", "productOptions",
+ "interestRatePeriodFrequencyTypeOptions", "lockinPeriodFrequencyTypeOptions"));
public static final Set SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet(Arrays.asList(
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName));
public static final Set SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList(idParamName,
"accountId", accountNoParamName, "currency", "amount"));
+
+ public static final Set SAVINGS_ACCOUNT_ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet(Arrays.asList(localeParamName,
+ dateFormatParamName, activationDateParamName));
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java
index 9471cbaa7..97474ec20 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.savings.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;
@@ -20,6 +21,8 @@ public class SavingsAccountData {
private final Long id;
private final String accountNo;
private final String externalId;
+ private final SavingsAccountStatusEnumData status;
+ private final LocalDate activationDate;
private final Long groupId;
private final String groupName;
private final Long clientId;
@@ -43,10 +46,11 @@ public class SavingsAccountData {
private final Collection interestRatePeriodFrequencyTypeOptions;
private final Collection lockinPeriodFrequencyTypeOptions;
- public static SavingsAccountData instance(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 CurrencyData currency, final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType,
- final BigDecimal annualInterestRate, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
+ public static SavingsAccountData instance(final Long id, final String accountNo, final String externalId,
+ final SavingsAccountStatusEnumData status, final LocalDate activationDate, final Long groupId, final String groupName,
+ final Long clientId, final String clientName, final Long productId, final String productName, final CurrencyData currency,
+ final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
+ final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) {
final Collection productOptions = null;
@@ -54,21 +58,22 @@ public class SavingsAccountData {
final Collection lockinPeriodFrequencyTypeOptions = null;
final Collection transactions = null;
- return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
- currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, minRequiredOpeningBalance,
- lockinPeriodFrequency, lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions,
- lockinPeriodFrequencyTypeOptions, transactions);
+ return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
+ productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate,
+ minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary, productOptions,
+ interestRatePeriodFrequencyTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
}
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
final Collection productOptions, final Collection interestRatePeriodFrequencyTypeOptions,
final Collection lockinPeriodFrequencyTypeOptions, final Collection transactions) {
- return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
- account.clientId, account.clientName, account.savingsProductId, account.savingsProductName, account.currency,
- account.interestRate, account.interestRatePeriodFrequencyType, account.annualInterestRate,
- account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.summary,
- productOptions, interestRatePeriodFrequencyTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
+ return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate,
+ account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId,
+ account.savingsProductName, account.currency, account.interestRate, account.interestRatePeriodFrequencyType,
+ account.annualInterestRate, account.minRequiredOpeningBalance, account.lockinPeriodFrequency,
+ account.lockinPeriodFrequencyType, account.summary, productOptions, interestRatePeriodFrequencyTypeOptions,
+ lockinPeriodFrequencyTypeOptions, transactions);
}
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
@@ -77,6 +82,8 @@ public class SavingsAccountData {
final Long id = null;
final String accountNo = null;
final String externalId = null;
+ final SavingsAccountStatusEnumData status = null;
+ final LocalDate activationDate = null;
final Long productId = null;
final String productName = null;
final CurrencyData currency = null;
@@ -93,15 +100,16 @@ public class SavingsAccountData {
final Collection lockinPeriodFrequencyTypeOptions = null;
final Collection transactions = null;
- return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
- currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate, minRequiredOpeningBalance,
- lockinPeriodFrequency, lockinPeriodFrequencyType, summary, productOptions, interestRatePeriodFrequencyTypeOptions,
- lockinPeriodFrequencyTypeOptions, transactions);
+ return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
+ productId, productName, currency, interestRate, interestRatePeriodFrequencyType, annualInterestRate,
+ minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, summary, productOptions,
+ interestRatePeriodFrequencyTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
}
- private SavingsAccountData(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 CurrencyData currency,
- final BigDecimal interestRate, final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
+ private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
+ final LocalDate activationDate, final Long groupId, final String groupName, final Long clientId, final String clientName,
+ final Long productId, final String productName, final CurrencyData currency, final BigDecimal interestRate,
+ final EnumOptionData interestRatePeriodFrequencyType, final BigDecimal annualInterestRate,
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary,
final Collection productOptions, final Collection interestRatePeriodFrequencyTypeOptions,
@@ -109,6 +117,8 @@ public class SavingsAccountData {
this.id = id;
this.accountNo = accountNo;
this.externalId = externalId;
+ this.status = status;
+ this.activationDate = activationDate;
this.groupId = groupId;
this.groupName = groupName;
this.clientId = clientId;
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountDataValidator.java
index e6525ab33..6312cd5ba 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountDataValidator.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountDataValidator.java
@@ -1,6 +1,8 @@
package org.mifosplatform.portfolio.savings.data;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountNoParamName;
+import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
+import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.clientIdParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.externalIdParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.groupIdParamName;
@@ -18,6 +20,7 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
+import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
@@ -69,6 +72,15 @@ public class SavingsAccountDataValidator {
final Long productId = fromApiJsonHelper.extractLongNamed(productIdParamName, element);
baseDataValidator.reset().parameter(productIdParamName).value(productId).notNull().integerGreaterThanZero();
+ final Boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element);
+ baseDataValidator.reset().parameter(activeParamName).value(active).notNull();
+
+ LocalDate activationDate = null;
+ if (active != null && active.booleanValue()) {
+ activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
+ baseDataValidator.reset().parameter(activationDateParamName).value(activationDate).notNull();
+ }
+
if (fromApiJsonHelper.parameterExists(accountNoParamName, element)) {
final String accountNo = fromApiJsonHelper.extractStringNamed(accountNoParamName, element);
baseDataValidator.reset().parameter(accountNoParamName).value(accountNo).notBlank().notExceedingLengthOf(20);
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java
new file mode 100644
index 000000000..3a3479079
--- /dev/null
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java
@@ -0,0 +1,35 @@
+/**
+ * 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.savings.data;
+
+/**
+ * Immutable data object represent savings account status enumerations.
+ */
+public class SavingsAccountStatusEnumData {
+
+ @SuppressWarnings("unused")
+ private final Long id;
+ @SuppressWarnings("unused")
+ private final String code;
+ @SuppressWarnings("unused")
+ private final String value;
+ @SuppressWarnings("unused")
+ private final boolean unactivated;
+ @SuppressWarnings("unused")
+ private final boolean active;
+ @SuppressWarnings("unused")
+ private final boolean closed;
+
+ public SavingsAccountStatusEnumData(final Long id, final String code, final String value, final boolean unactivated,
+ final boolean active, final boolean closed) {
+ this.id = id;
+ this.code = code;
+ this.value = value;
+ this.unactivated = unactivated;
+ this.active = active;
+ this.closed = closed;
+ }
+}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
index d5c955f9f..aa53e092a 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
@@ -1,5 +1,6 @@
package org.mifosplatform.portfolio.savings.data;
+import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.transactionAmountParamName;
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.transactionDateParamName;
@@ -54,7 +55,28 @@ public class SavingsAccountTransactionDataValidator {
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDate).notNull();
final BigDecimal transactionAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transactionAmountParamName, element);
- baseDataValidator.reset().parameter(transactionAmountParamName).value(transactionAmount).notNull().zeroOrPositiveAmount();
+ baseDataValidator.reset().parameter(transactionAmountParamName).value(transactionAmount).notNull().positiveAmount();
+
+ throwExceptionIfValidationWarningsExist(dataValidationErrors);
+ }
+
+ public void validateActivation(final JsonCommand command) {
+ final String json = command.json();
+
+ if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
+
+ final Type typeOfMap = new TypeToken