MIFOSX-541: add application process around savings accounts.
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
ALTER TABLE `m_note`
|
||||||
|
ADD COLUMN `savings_account_id` BIGINT(20) NULL DEFAULT NULL AFTER `loan_transaction_id`,
|
||||||
|
ADD COLUMN `savings_account_transaction_id` BIGINT(20) NULL DEFAULT NULL AFTER `savings_account_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `m_note` ADD CONSTRAINT `FK_savings_account_id` FOREIGN KEY (`savings_account_id` ) REFERENCES `m_savings_account` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION, ADD INDEX `FK_savings_account_id` (`savings_account_id` ASC) ;
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account_transaction`
|
||||||
|
CHANGE COLUMN `is_reversed` `is_reversed` TINYINT(1) NOT NULL AFTER `transaction_type_enum`,
|
||||||
|
CHANGE COLUMN `balance_end_date_derived` `balance_end_date_derived` DATE NULL DEFAULT NULL AFTER `amount`,
|
||||||
|
CHANGE COLUMN `balance_number_of_days_derived` `balance_number_of_days_derived` INT(11) NULL DEFAULT NULL AFTER `balance_end_date_derived`;
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account`
|
||||||
|
ADD COLUMN `field_officer_id` bigint(20) DEFAULT NULL AFTER `product_id`,
|
||||||
|
ADD COLUMN `submittedon_date` DATE NOT NULL AFTER `status_enum`,
|
||||||
|
ADD COLUMN `submittedon_userid` bigint(20) DEFAULT NULL AFTER `submittedon_date`,
|
||||||
|
ADD COLUMN `approvedon_date` DATE DEFAULT NULL AFTER `submittedon_userid`,
|
||||||
|
ADD COLUMN `approvedon_userid` bigint(20) DEFAULT NULL AFTER `approvedon_date`,
|
||||||
|
ADD COLUMN `rejectedon_date` DATE DEFAULT NULL AFTER `approvedon_userid`,
|
||||||
|
ADD COLUMN `rejectedon_userid` bigint(20) DEFAULT NULL AFTER `rejectedon_date`,
|
||||||
|
ADD COLUMN `withdrawnon_date` DATE DEFAULT NULL AFTER `rejectedon_userid`,
|
||||||
|
ADD COLUMN `withdrawnon_userid` bigint(20) DEFAULT NULL AFTER `withdrawnon_date`;
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account`
|
||||||
|
CHANGE COLUMN `activation_date` `activatedon_date` DATE NULL DEFAULT NULL AFTER `withdrawnon_userid`;
|
||||||
|
|
||||||
|
ALTER TABLE `m_savings_account`
|
||||||
|
ADD COLUMN `activatedon_userid` bigint(20) DEFAULT NULL AFTER `activatedon_date`,
|
||||||
|
ADD COLUMN `closedon_date` DATE DEFAULT NULL AFTER `activatedon_userid`,
|
||||||
|
ADD COLUMN `closedon_userid` bigint(20) DEFAULT NULL AFTER `closedon_date`;
|
||||||
|
|
||||||
|
UPDATE `m_savings_account`
|
||||||
|
SET
|
||||||
|
`submittedon_date`=`activatedon_date`,
|
||||||
|
`approvedon_date`=`activatedon_date`;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO `mifostenant-default`.`m_permission`
|
||||||
|
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`)
|
||||||
|
VALUES
|
||||||
|
('transaction_savings', 'APPROVE_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'APPROVE', 1),
|
||||||
|
('transaction_savings', 'REJECT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'REJECT', 1),
|
||||||
|
('transaction_savings', 'WITHDRAW_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'WITHDRAW', 1),
|
||||||
|
('transaction_savings', 'APPROVALUNDO_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'APPROVALUNDO', 1),
|
||||||
|
('transaction_savings', 'CLOSE_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'CLOSE', 1);
|
||||||
|
|
||||||
|
INSERT INTO `mifostenant-default`.`m_permission`
|
||||||
|
(`grouping`,`code`,`entity_name`,`action_name`,`can_maker_checker`)
|
||||||
|
VALUES
|
||||||
|
('transaction_savings', 'APPROVE_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'APPROVE', 0),
|
||||||
|
('transaction_savings', 'REJECT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'REJECT', 0),
|
||||||
|
('transaction_savings', 'WITHDRAW_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'WITHDRAW', 0),
|
||||||
|
('transaction_savings', 'APPROVALUNDO_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'APPROVALUNDO', 0),
|
||||||
|
('transaction_savings', 'CLOSE_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'CLOSE', 0);
|
||||||
|
|
||||||
|
|
||||||
|
-- Remove permissions with 'in the past' permissions
|
||||||
|
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='210';
|
||||||
|
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='212';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='214';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='217';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='220';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='233';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='235';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='237';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='240';
|
||||||
|
DELETE FROM `m_permission` WHERE `id`='243';
|
||||||
@@ -53,7 +53,7 @@ project.ext.springVersion = '3.2.3.RELEASE'
|
|||||||
project.ext.springSecurityVersion = '3.1.4.RELEASE'
|
project.ext.springSecurityVersion = '3.1.4.RELEASE'
|
||||||
project.ext.hibernateCoreVersion = '4.1.9.Final'
|
project.ext.hibernateCoreVersion = '4.1.9.Final'
|
||||||
project.ext.jerseyVersion = '1.17'
|
project.ext.jerseyVersion = '1.17'
|
||||||
project.ext.springDataJpaVersion = '1.3.0.RELEASE'
|
project.ext.springDataJpaVersion = '1.3.2.RELEASE'
|
||||||
|
|
||||||
project.ext.mysqlUser='root'
|
project.ext.mysqlUser='root'
|
||||||
project.ext.mysqlPassword='mysql'
|
project.ext.mysqlPassword='mysql'
|
||||||
@@ -123,8 +123,8 @@ dependencies {
|
|||||||
|
|
||||||
[group: 'joda-time', name: 'joda-time', version: '2.1'],
|
[group: 'joda-time', name: 'joda-time', version: '2.1'],
|
||||||
[group: 'net.sourceforge.javacsv', name: 'javacsv', version: '2.0'],
|
[group: 'net.sourceforge.javacsv', name: 'javacsv', version: '2.0'],
|
||||||
[group: 'org.apache.commons', name: 'commons-email', version: '1.2'],
|
[group: 'org.apache.commons', name: 'commons-email', version: '1.3.1'],
|
||||||
[group: 'commons-lang', name: 'commons-lang', version: '2.4'],
|
[group: 'org.apache.commons', name: 'commons-lang3', version: '3.1'],
|
||||||
|
|
||||||
[group: 'org.slf4j', name: 'slf4j-api', version: '1.7.5'],
|
[group: 'org.slf4j', name: 'slf4j-api', version: '1.7.5'],
|
||||||
[group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.5'],
|
[group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.5'],
|
||||||
@@ -164,7 +164,8 @@ dependencies {
|
|||||||
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1']
|
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1']
|
||||||
)
|
)
|
||||||
|
|
||||||
testCompile 'junit:junit:4.11',
|
testCompile 'junit:junit:4.10',
|
||||||
|
'junit:junit-dep:4.10',
|
||||||
'org.mockito:mockito-all:1.9.5',
|
'org.mockito:mockito-all:1.9.5',
|
||||||
'com.jayway.restassured:rest-assured:1.7.2'
|
'com.jayway.restassured:rest-assured:1.7.2'
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -23,7 +23,8 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
|||||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.*;
|
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.*;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -21,7 +21,8 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.*;
|
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.*;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
|||||||
+16
-36
@@ -415,42 +415,6 @@ public class CommandWrapper {
|
|||||||
return isUserResource() && isUpdate() && loggedInUserId.equals(this.entityId);
|
return isUserResource() && isUpdate() && loggedInUserId.equals(this.entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDepositProductResource() {
|
|
||||||
return this.entityName.equalsIgnoreCase("DEPOSITPRODUCT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDepositAccountResource() {
|
|
||||||
return this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isApprovalOfDeposit() {
|
|
||||||
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWithdrawDepositAmount() {
|
|
||||||
return this.actionName.equalsIgnoreCase("WITHDRAWAL") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWithdrawInterest() {
|
|
||||||
return this.actionName.equalsIgnoreCase("INTEREST") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRenewOfDepositApplicaion() {
|
|
||||||
return this.actionName.equalsIgnoreCase("RENEW") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRejectionOfDepositApplicaion() {
|
|
||||||
return this.actionName.equalsIgnoreCase("REJECT") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWithdrawByApplicant() {
|
|
||||||
return this.actionName.equalsIgnoreCase("WITHDRAW") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isUndoApprovalOfDepositApplication() {
|
|
||||||
return this.actionName.equalsIgnoreCase("APPROVALUNDO") && this.entityName.equalsIgnoreCase("DEPOSITACCOUNT");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSavingsProductResource() {
|
public boolean isSavingsProductResource() {
|
||||||
return this.entityName.equalsIgnoreCase("SAVINGSPRODUCT");
|
return this.entityName.equalsIgnoreCase("SAVINGSPRODUCT");
|
||||||
}
|
}
|
||||||
@@ -459,6 +423,22 @@ public class CommandWrapper {
|
|||||||
return this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
return this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRejectionOfSavingsAccountApplication() {
|
||||||
|
return this.actionName.equalsIgnoreCase("REJECT") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWithdrawFromSavingsAccountApplicationByApplicant() {
|
||||||
|
return this.actionName.equalsIgnoreCase("WITHDRAW") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApprovalOfSavingsAccountApplication() {
|
||||||
|
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUndoApprovalOfSavingsAccountApplication() {
|
||||||
|
return this.actionName.equalsIgnoreCase("APPROVALUNDO") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSavingsAccountActivation() {
|
public boolean isSavingsAccountActivation() {
|
||||||
return this.actionName.equalsIgnoreCase("ACTIVATE") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
return this.actionName.equalsIgnoreCase("ACTIVATE") && this.entityName.equalsIgnoreCase("SAVINGSACCOUNT");
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-5
@@ -757,6 +757,42 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder rejectSavingsAccountApplication(final Long accountId) {
|
||||||
|
this.actionName = "REJECT";
|
||||||
|
this.entityName = "SAVINGSACCOUNT";
|
||||||
|
this.entityId = accountId;
|
||||||
|
this.savingsId = accountId;
|
||||||
|
this.href = "/savingsaccounts/" + accountId + "?command=reject";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder withdrawSavingsAccountApplication(final Long accountId) {
|
||||||
|
this.actionName = "WITHDRAW";
|
||||||
|
this.entityName = "SAVINGSACCOUNT";
|
||||||
|
this.entityId = accountId;
|
||||||
|
this.savingsId = accountId;
|
||||||
|
this.href = "/savingsaccounts/" + accountId + "?command=withdrawnByApplicant";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder approveSavingsAccountApplication(final Long accountId) {
|
||||||
|
this.actionName = "APPROVE";
|
||||||
|
this.entityName = "SAVINGSACCOUNT";
|
||||||
|
this.entityId = accountId;
|
||||||
|
this.savingsId = accountId;
|
||||||
|
this.href = "/savingsaccounts/" + accountId + "?command=approve";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder undoSavingsAccountApplication(final Long accountId) {
|
||||||
|
this.actionName = "APPROVALUNDO";
|
||||||
|
this.entityName = "SAVINGSACCOUNT";
|
||||||
|
this.entityId = accountId;
|
||||||
|
this.savingsId = accountId;
|
||||||
|
this.href = "/savingsaccounts/" + accountId + "?command=undoapproval";
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder savingsAccountActivation(final Long accountId) {
|
public CommandWrapperBuilder savingsAccountActivation(final Long accountId) {
|
||||||
this.actionName = "ACTIVATE";
|
this.actionName = "ACTIVATE";
|
||||||
this.entityName = "SAVINGSACCOUNT";
|
this.entityName = "SAVINGSACCOUNT";
|
||||||
@@ -1036,7 +1072,7 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder assignRole(Long groupId) {
|
public CommandWrapperBuilder assignRole(final Long groupId) {
|
||||||
this.actionName = "ASSIGNROLE";
|
this.actionName = "ASSIGNROLE";
|
||||||
this.entityName = "GROUP";
|
this.entityName = "GROUP";
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
@@ -1045,7 +1081,7 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder unassignRole(Long groupId, Long roleId) {
|
public CommandWrapperBuilder unassignRole(final Long groupId, final Long roleId) {
|
||||||
this.actionName = "UNASSIGNROLE";
|
this.actionName = "UNASSIGNROLE";
|
||||||
this.entityName = "GROUP";
|
this.entityName = "GROUP";
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
@@ -1054,7 +1090,7 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder updateRole(Long groupId, Long roleId) {
|
public CommandWrapperBuilder updateRole(final Long groupId, final Long roleId) {
|
||||||
this.actionName = "UPDATEROLE";
|
this.actionName = "UPDATEROLE";
|
||||||
this.entityName = "GROUP";
|
this.entityName = "GROUP";
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
@@ -1063,7 +1099,7 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder unassignClientStaff(Long clientId) {
|
public CommandWrapperBuilder unassignClientStaff(final Long clientId) {
|
||||||
this.actionName = "UNASSIGNSTAFF";
|
this.actionName = "UNASSIGNSTAFF";
|
||||||
this.entityName = "CLIENT";
|
this.entityName = "CLIENT";
|
||||||
this.entityId = clientId;
|
this.entityId = clientId;
|
||||||
@@ -1072,7 +1108,7 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandWrapperBuilder assignClientStaff(Long clientId) {
|
public CommandWrapperBuilder assignClientStaff(final Long clientId) {
|
||||||
this.actionName = "ASSIGNSTAFF";
|
this.actionName = "ASSIGNSTAFF";
|
||||||
this.entityName = "CLIENT";
|
this.entityName = "CLIENT";
|
||||||
this.entityId = clientId;
|
this.entityId = clientId;
|
||||||
|
|||||||
+15
-3
@@ -374,11 +374,23 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
}
|
}
|
||||||
} else if (wrapper.isSavingsAccountResource()) {
|
} else if (wrapper.isSavingsAccountResource()) {
|
||||||
if (wrapper.isCreate()) {
|
if (wrapper.isCreate()) {
|
||||||
handler = this.applicationContext.getBean("createSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext
|
||||||
|
.getBean("savingsAccountApplicationSubmittalCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isUpdate()) {
|
} else if (wrapper.isUpdate()) {
|
||||||
handler = this.applicationContext.getBean("updateSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("savingsAccountApplicationModificationCommandHandler",
|
||||||
|
NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isDelete()) {
|
} else if (wrapper.isDelete()) {
|
||||||
handler = this.applicationContext.getBean("deleteSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("savingsAccountApplicationDeletionCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isRejectionOfSavingsAccountApplication()) {
|
||||||
|
handler = this.applicationContext.getBean("savingsAccountApplicationRejectedCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isWithdrawFromSavingsAccountApplicationByApplicant()) {
|
||||||
|
handler = this.applicationContext.getBean("savingsAccountApplicationWithdrawnByApplicantCommandHandler",
|
||||||
|
NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isApprovalOfSavingsAccountApplication()) {
|
||||||
|
handler = this.applicationContext.getBean("savingsAccountApplicationApprovalCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
} else if (wrapper.isUndoApprovalOfSavingsAccountApplication()) {
|
||||||
|
handler = this.applicationContext.getBean("savingsAccountApplicationApprovalUndoCommandHandler",
|
||||||
|
NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isSavingsAccountDeposit()) {
|
} else if (wrapper.isSavingsAccountDeposit()) {
|
||||||
handler = this.applicationContext.getBean("depositSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("depositSavingsAccountCommandHandler", NewCommandSourceHandler.class);
|
||||||
} else if (wrapper.isSavingsAccountWithdrawal()) {
|
} else if (wrapper.isSavingsAccountWithdrawal()) {
|
||||||
|
|||||||
+60
-18
@@ -46,6 +46,7 @@ public final class JsonCommand {
|
|||||||
private final Long supportedEntityId;
|
private final Long supportedEntityId;
|
||||||
private final String transactionId;
|
private final String transactionId;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
|
||||||
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
|
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
|
||||||
final String entityName, final Long resourceId, final Long subresourceId, final Long groupId, final Long clientId,
|
final String entityName, final Long resourceId, final Long subresourceId, final Long groupId, final Long clientId,
|
||||||
final Long loanId, final Long savingsId, final Long codeId, final String supportedEntityType, final Long supportedEntityId,
|
final Long loanId, final Long savingsId, final Long codeId, final String supportedEntityType, final Long supportedEntityId,
|
||||||
@@ -64,8 +65,7 @@ public final class JsonCommand {
|
|||||||
public JsonCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
|
public JsonCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
|
||||||
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId,
|
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId,
|
||||||
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final Long codeId,
|
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final Long codeId,
|
||||||
final String supportedEntityType, final Long supportedEntityId, final String transactionId,
|
final String supportedEntityType, final Long supportedEntityId, final String transactionId, final String url) {
|
||||||
final String url) {
|
|
||||||
this.commandId = commandId;
|
this.commandId = commandId;
|
||||||
this.jsonCommand = jsonCommand;
|
this.jsonCommand = jsonCommand;
|
||||||
this.parsedCommand = parsedCommand;
|
this.parsedCommand = parsedCommand;
|
||||||
@@ -148,9 +148,9 @@ public final class JsonCommand {
|
|||||||
public String getTransactionId() {
|
public String getTransactionId() {
|
||||||
return this.transactionId;
|
return this.transactionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return this.url;
|
return this.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean differenceExists(final LocalDate baseValue, final LocalDate workingCopyValue) {
|
private boolean differenceExists(final LocalDate baseValue, final LocalDate workingCopyValue) {
|
||||||
@@ -187,10 +187,10 @@ public final class JsonCommand {
|
|||||||
boolean differenceExists = false;
|
boolean differenceExists = false;
|
||||||
|
|
||||||
if (baseValue != null) {
|
if (baseValue != null) {
|
||||||
if(workingCopyValue != null) {
|
if (workingCopyValue != null) {
|
||||||
differenceExists = !baseValue.equals(workingCopyValue);
|
differenceExists = !baseValue.equals(workingCopyValue);
|
||||||
} else {
|
} else {
|
||||||
differenceExists = true;
|
differenceExists = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
differenceExists = workingCopyValue != null;
|
differenceExists = workingCopyValue != null;
|
||||||
@@ -203,11 +203,11 @@ public final class JsonCommand {
|
|||||||
boolean differenceExists = false;
|
boolean differenceExists = false;
|
||||||
|
|
||||||
if (baseValue != null) {
|
if (baseValue != null) {
|
||||||
if(workingCopyValue != null) {
|
if (workingCopyValue != null) {
|
||||||
differenceExists = baseValue.compareTo(workingCopyValue) != 0;
|
differenceExists = baseValue.compareTo(workingCopyValue) != 0;
|
||||||
}else {
|
} else {
|
||||||
differenceExists = true;
|
differenceExists = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
differenceExists = workingCopyValue != null;
|
differenceExists = workingCopyValue != null;
|
||||||
}
|
}
|
||||||
@@ -301,6 +301,15 @@ public final class JsonCommand {
|
|||||||
return StringUtils.defaultIfEmpty(value, "");
|
return StringUtils.defaultIfEmpty(value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isChangeInBigDecimalParameterNamedDefaultingZeroToNull(final String parameterName, final BigDecimal existingValue) {
|
||||||
|
boolean isChanged = false;
|
||||||
|
if (parameterExists(parameterName)) {
|
||||||
|
final BigDecimal workingValue = bigDecimalValueOfParameterNamedDefaultToNullIfZero(parameterName);
|
||||||
|
isChanged = differenceExists(existingValue, workingValue);
|
||||||
|
}
|
||||||
|
return isChanged;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChangeInBigDecimalParameterNamed(final String parameterName, final BigDecimal existingValue) {
|
public boolean isChangeInBigDecimalParameterNamed(final String parameterName, final BigDecimal existingValue) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
@@ -309,24 +318,53 @@ public final class JsonCommand {
|
|||||||
}
|
}
|
||||||
return isChanged;
|
return isChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChangeInBigDecimalParameterNamedWithNullCheck(final String parameterName, final BigDecimal existingValue) {
|
public boolean isChangeInBigDecimalParameterNamedWithNullCheck(final String parameterName, final BigDecimal existingValue) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
final BigDecimal workingValue = bigDecimalValueOfParameterNamed(parameterName);
|
final BigDecimal workingValue = bigDecimalValueOfParameterNamed(parameterName);
|
||||||
if(workingValue == null && existingValue != null){
|
if (workingValue == null && existingValue != null) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
}else{
|
} else {
|
||||||
isChanged = differenceExists(existingValue, workingValue);
|
isChanged = differenceExists(existingValue, workingValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isChanged;
|
return isChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static BigDecimal defaultToNullIfZero(final BigDecimal value) {
|
||||||
|
BigDecimal result = value;
|
||||||
|
if (value != null && BigDecimal.ZERO.compareTo(value) == 0) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer defaultToNullIfZero(final Integer value) {
|
||||||
|
Integer result = value;
|
||||||
|
if (value != null && value == 0) {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public BigDecimal bigDecimalValueOfParameterNamed(final String parameterName) {
|
public BigDecimal bigDecimalValueOfParameterNamed(final String parameterName) {
|
||||||
return this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(parameterName, parsedCommand);
|
return this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(parameterName, parsedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal bigDecimalValueOfParameterNamedDefaultToNullIfZero(final String parameterName) {
|
||||||
|
return defaultToNullIfZero(bigDecimalValueOfParameterNamed(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChangeInIntegerParameterNamedDefaultingZeroToNull(final String parameterName, final Integer existingValue) {
|
||||||
|
boolean isChanged = false;
|
||||||
|
if (parameterExists(parameterName)) {
|
||||||
|
final Integer workingValue = integerValueOfParameterNamedDefaultToNullIfZero(parameterName);
|
||||||
|
isChanged = differenceExists(existingValue, workingValue);
|
||||||
|
}
|
||||||
|
return isChanged;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChangeInIntegerParameterNamed(final String parameterName, final Integer existingValue) {
|
public boolean isChangeInIntegerParameterNamed(final String parameterName, final Integer existingValue) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
@@ -340,19 +378,23 @@ public final class JsonCommand {
|
|||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
final Integer workingValue = integerValueOfParameterNamed(parameterName);
|
final Integer workingValue = integerValueOfParameterNamed(parameterName);
|
||||||
if(workingValue == null && existingValue != null){
|
if (workingValue == null && existingValue != null) {
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
}else{
|
} else {
|
||||||
isChanged = differenceExists(existingValue, workingValue);
|
isChanged = differenceExists(existingValue, workingValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isChanged;
|
return isChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer integerValueOfParameterNamed(final String parameterName) {
|
public Integer integerValueOfParameterNamed(final String parameterName) {
|
||||||
return this.fromApiJsonHelper.extractIntegerWithLocaleNamed(parameterName, parsedCommand);
|
return this.fromApiJsonHelper.extractIntegerWithLocaleNamed(parameterName, parsedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer integerValueOfParameterNamedDefaultToNullIfZero(final String parameterName) {
|
||||||
|
return defaultToNullIfZero(integerValueOfParameterNamed(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isChangeInIntegerSansLocaleParameterNamed(final String parameterName, final Integer existingValue) {
|
public boolean isChangeInIntegerSansLocaleParameterNamed(final String parameterName, final Integer existingValue) {
|
||||||
boolean isChanged = false;
|
boolean isChanged = false;
|
||||||
if (parameterExists(parameterName)) {
|
if (parameterExists(parameterName)) {
|
||||||
|
|||||||
+73
-45
@@ -209,25 +209,24 @@ public class DataValidatorBuilder {
|
|||||||
public DataValidatorBuilder isOneOfTheseValues(final Object... values) {
|
public DataValidatorBuilder isOneOfTheseValues(final Object... values) {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
if (value != null) {
|
List<Object> valuesList = Arrays.asList(values);
|
||||||
List<Object> valuesList = Arrays.asList(values);
|
String valuesListStr = StringUtils.join(valuesList, ", ");
|
||||||
String valuesListStr = StringUtils.join(valuesList, ", ");
|
|
||||||
|
|
||||||
if (!valuesList.contains(this.value)) {
|
if (this.value == null || !valuesList.contains(this.value)) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".is.not.one.of.expected.enumerations");
|
.append(".is.not.one.of.expected.enumerations");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must be one of [ ")
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must be one of [ ")
|
||||||
.append(valuesListStr).append(" ] ").append(".");
|
.append(valuesListStr).append(" ] ").append(".");
|
||||||
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, this.value, values);
|
parameter, this.value, values);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder isNotOneOfTheseValues(final Object... values) {
|
public DataValidatorBuilder isNotOneOfTheseValues(final Object... values) {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -238,8 +237,8 @@ public class DataValidatorBuilder {
|
|||||||
if (valuesList.contains(this.value)) {
|
if (valuesList.contains(this.value)) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".is.one.of.unwanted.enumerations");
|
.append(".is.one.of.unwanted.enumerations");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must not be any of [ ")
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter)
|
||||||
.append(valuesListStr).append(" ] ").append(".");
|
.append(" must not be any of [ ").append(valuesListStr).append(" ] ").append(".");
|
||||||
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, this.value, values);
|
defaultEnglishMessage.toString(), parameter, this.value, values);
|
||||||
@@ -268,6 +267,9 @@ public class DataValidatorBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* should be used with .notNull() before it
|
||||||
|
*/
|
||||||
public DataValidatorBuilder zeroOrPositiveAmount() {
|
public DataValidatorBuilder zeroOrPositiveAmount() {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -286,6 +288,30 @@ public class DataValidatorBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* should be used with .notNull() before it
|
||||||
|
*/
|
||||||
|
public DataValidatorBuilder integerZeroOrGreater() {
|
||||||
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
|
if (value != null) {
|
||||||
|
Integer number = Integer.valueOf(value.toString());
|
||||||
|
if (number < 0) {
|
||||||
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
|
.append(".not.zero.or.greater");
|
||||||
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(
|
||||||
|
" must be zero or greater.");
|
||||||
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
|
defaultEnglishMessage.toString(), parameter, number, 0);
|
||||||
|
dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* should be used with .notNull() before it
|
||||||
|
*/
|
||||||
public DataValidatorBuilder integerGreaterThanZero() {
|
public DataValidatorBuilder integerGreaterThanZero() {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -304,6 +330,9 @@ public class DataValidatorBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* should be used with .notNull() before it
|
||||||
|
*/
|
||||||
public DataValidatorBuilder longGreaterThanZero() {
|
public DataValidatorBuilder longGreaterThanZero() {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -337,11 +366,11 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder jsonArrayNotEmpty() {
|
public DataValidatorBuilder jsonArrayNotEmpty() {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
JsonArray array = (JsonArray)value;
|
JsonArray array = (JsonArray) value;
|
||||||
if (value != null && !array.iterator().hasNext()) {
|
if (value != null && !array.iterator().hasNext()) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".cannot.be.empty");
|
.append(".cannot.be.empty");
|
||||||
@@ -427,14 +456,14 @@ public class DataValidatorBuilder {
|
|||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder cantBeBlankWhenParameterProvidedIs(final String parameterName, final Object parameterValue) {
|
public DataValidatorBuilder cantBeBlankWhenParameterProvidedIs(final String parameterName, final Object parameterValue) {
|
||||||
if (value != null && StringUtils.isNotBlank(value.toString())) { return this; }
|
if (value != null && StringUtils.isNotBlank(value.toString())) { return this; }
|
||||||
|
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".must.be.provided.when.").append(parameterName).append(".is.").append(parameterValue);
|
.append(".must.be.provided.when.").append(parameterName).append(".is.").append(parameterValue);
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter)
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter).append(" must be provided when ")
|
||||||
.append(" must be provided when ").append(parameterName).append(" is ").append(parameterValue);
|
.append(parameterName).append(" is ").append(parameterValue);
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||||
parameter, value, parameterName, parameterValue);
|
parameter, value, parameterName, parameterValue);
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
@@ -457,12 +486,12 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder inMinAndMaxAmountRange(final BigDecimal minimumAmount, final BigDecimal maximumAmount) {
|
public DataValidatorBuilder inMinAndMaxAmountRange(final BigDecimal minimumAmount, final BigDecimal maximumAmount) {
|
||||||
if (minimumAmount != null && maximumAmount != null && value != null){
|
if (minimumAmount != null && maximumAmount != null && value != null) {
|
||||||
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
||||||
if (amount.compareTo(minimumAmount) == -1 || amount.compareTo(maximumAmount) == 1) {
|
if (amount.compareTo(minimumAmount) == -1 || amount.compareTo(maximumAmount) == 1) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".amount.is.not.within.min.max.range");
|
.append(".amount.is.not.within.min.max.range");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter) .append(" amount ").append(amount)
|
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter).append(" amount ").append(amount)
|
||||||
.append(" must be between ").append(minimumAmount).append(" and ").append(maximumAmount).append(" .");
|
.append(" must be between ").append(minimumAmount).append(" and ").append(maximumAmount).append(" .");
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, amount, minimumAmount, maximumAmount);
|
defaultEnglishMessage.toString(), parameter, amount, minimumAmount, maximumAmount);
|
||||||
@@ -472,14 +501,14 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder notLessThanMin(final BigDecimal min) {
|
public DataValidatorBuilder notLessThanMin(final BigDecimal min) {
|
||||||
if (min != null && value != null){
|
if (min != null && value != null) {
|
||||||
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
||||||
if (amount.compareTo(min) == -1) {
|
if (amount.compareTo(min) == -1) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".is.less.than.min");
|
.append(".is.less.than.min");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter) .append(" value ").append(amount)
|
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter).append(" value ").append(amount)
|
||||||
.append(" must not be less than minimum value ").append(min);
|
.append(" must not be less than minimum value ").append(min);
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, amount, min);
|
defaultEnglishMessage.toString(), parameter, amount, min);
|
||||||
@@ -489,14 +518,14 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder notGreaterThanMax(final BigDecimal max) {
|
public DataValidatorBuilder notGreaterThanMax(final BigDecimal max) {
|
||||||
if (max != null && value != null){
|
if (max != null && value != null) {
|
||||||
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
||||||
if (amount.compareTo(max) == 1) {
|
if (amount.compareTo(max) == 1) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".is.greater.than.max");
|
.append(".is.greater.than.max");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter) .append(" value ").append(amount)
|
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter).append(" value ").append(amount)
|
||||||
.append(" must not be more than maximum value ").append(max);
|
.append(" must not be more than maximum value ").append(max);
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, amount, max);
|
defaultEnglishMessage.toString(), parameter, amount, max);
|
||||||
@@ -541,7 +570,7 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder notLessThanMin(final Integer min) {
|
public DataValidatorBuilder notLessThanMin(final Integer min) {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -559,7 +588,7 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder notGreaterThanMax(final Integer max) {
|
public DataValidatorBuilder notGreaterThanMax(final Integer max) {
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
@@ -577,26 +606,25 @@ public class DataValidatorBuilder {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder matchesRegularExpression(final String expression) {
|
|
||||||
if (value == null && ignoreNullValue) { return this; }
|
|
||||||
|
|
||||||
if (value != null && !value.toString().matches(expression)) {
|
public DataValidatorBuilder matchesRegularExpression(final String expression) {
|
||||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
if (value == null && ignoreNullValue) { return this; }
|
||||||
|
|
||||||
|
if (value != null && !value.toString().matches(expression)) {
|
||||||
|
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||||
.append(".does.not.match.regexp");
|
.append(".does.not.match.regexp");
|
||||||
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter)
|
StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(parameter)
|
||||||
.append(" must match the provided regular expression [ ")
|
.append(" must match the provided regular expression [ ").append(expression).append(" ] ").append(".");
|
||||||
.append(expression).append(" ] ").append(".");
|
|
||||||
|
|
||||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||||
defaultEnglishMessage.toString(), parameter, this.value, expression);
|
parameter, this.value, expression);
|
||||||
|
|
||||||
dataValidationErrors.add(error);
|
dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataValidatorBuilder validateStringFor(final String validInputs) {
|
private DataValidatorBuilder validateStringFor(final String validInputs) {
|
||||||
if (this.value == null && this.ignoreNullValue) { return this; }
|
if (this.value == null && this.ignoreNullValue) { return this; }
|
||||||
final String[] inputs = validInputs.split(VALID_INPUT_SEPERATOR);
|
final String[] inputs = validInputs.split(VALID_INPUT_SEPERATOR);
|
||||||
@@ -610,15 +638,15 @@ public class DataValidatorBuilder {
|
|||||||
if (validationErr) {
|
if (validationErr) {
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
.append(this.parameter).append(".value.should.true.or.false");
|
.append(this.parameter).append(".value.should.true.or.false");
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(this.parameter)
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The parameter ").append(this.parameter).append(
|
||||||
.append(" value should true or false ");
|
" value should true or false ");
|
||||||
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
defaultEnglishMessage.toString(), this.parameter, this.value);
|
defaultEnglishMessage.toString(), this.parameter, this.value);
|
||||||
this.dataValidationErrors.add(error);
|
this.dataValidationErrors.add(error);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataValidatorBuilder validateForBooleanValue() {
|
public DataValidatorBuilder validateForBooleanValue() {
|
||||||
return validateStringFor("TRUE" + VALID_INPUT_SEPERATOR + "FALSE");
|
return validateStringFor("TRUE" + VALID_INPUT_SEPERATOR + "FALSE");
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -5,6 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.core.domain;
|
package org.mifosplatform.infrastructure.core.domain;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
@@ -38,6 +40,14 @@ public class LocalDateInterval {
|
|||||||
return Days.daysBetween(this.startDate, this.endDate).getDays();
|
return Days.daysBetween(this.startDate, this.endDate).getDays();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean containsPortionOf(final LocalDateInterval interval) {
|
||||||
|
return contains(interval.startDate) || contains(interval.endDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(final LocalDateInterval interval) {
|
||||||
|
return contains(interval.startDate) && contains(interval.endDate);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean contains(final LocalDate target) {
|
public boolean contains(final LocalDate target) {
|
||||||
return isBetweenInclusive(this.startDate, this.endDate, target);
|
return isBetweenInclusive(this.startDate, this.endDate, target);
|
||||||
}
|
}
|
||||||
@@ -49,4 +59,9 @@ public class LocalDateInterval {
|
|||||||
public boolean fallsBefore(final LocalDate dateToCheck) {
|
public boolean fallsBefore(final LocalDate dateToCheck) {
|
||||||
return this.endDate.isBefore(dateToCheck);
|
return this.endDate.isBefore(dateToCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.client.data;
|
package org.mifosplatform.portfolio.client.data;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.activationDateParamName;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|||||||
+5
-1
@@ -452,7 +452,7 @@ public final class Client extends AbstractPersistable<Long> {
|
|||||||
this.staff = null;
|
this.staff = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assignStaff(Staff staff) {
|
public void assignStaff(final Staff staff) {
|
||||||
this.staff = staff;
|
this.staff = staff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,4 +466,8 @@ public final class Client extends AbstractPersistable<Long> {
|
|||||||
public Integer getStatus() {
|
public Integer getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
||||||
|
return getActivationLocalDate().isAfter(submittedOn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -179,6 +179,10 @@ public final class Group extends AbstractPersistable<Long> {
|
|||||||
this.status = GroupingTypeStatus.ACTIVE.getValue();
|
this.status = GroupingTypeStatus.ACTIVE.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActivatedAfter(final LocalDate submittedOn) {
|
||||||
|
return getActivationLocalDate().isAfter(submittedOn);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isNotActive() {
|
public boolean isNotActive() {
|
||||||
return !isActive();
|
return !isActive();
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-49
@@ -137,9 +137,9 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "loan_status_id", nullable = false)
|
@Column(name = "loan_status_id", nullable = false)
|
||||||
private Integer loanStatus;
|
private Integer loanStatus;
|
||||||
|
|
||||||
@Column(name = "sync_disbursement_with_meeting", nullable = true)
|
@Column(name = "sync_disbursement_with_meeting", nullable = true)
|
||||||
private Boolean syncDisbursementWithMeeting;
|
private Boolean syncDisbursementWithMeeting;
|
||||||
|
|
||||||
// loan application states
|
// loan application states
|
||||||
@Temporal(TemporalType.DATE)
|
@Temporal(TemporalType.DATE)
|
||||||
@Column(name = "submittedon_date")
|
@Column(name = "submittedon_date")
|
||||||
@@ -231,10 +231,10 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Column(name = "total_overpaid_derived", scale = 6, precision = 19)
|
@Column(name = "total_overpaid_derived", scale = 6, precision = 19)
|
||||||
private BigDecimal totalOverpaid;
|
private BigDecimal totalOverpaid;
|
||||||
|
|
||||||
@Column(name = "loan_counter")
|
@Column(name = "loan_counter")
|
||||||
private Integer loanCounter;
|
private Integer loanCounter;
|
||||||
|
|
||||||
@Column(name = "loan_product_counter")
|
@Column(name = "loan_product_counter")
|
||||||
private Integer loanProductCounter;
|
private Integer loanProductCounter;
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final Integer loanType,
|
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final Integer loanType,
|
||||||
final LoanProduct loanProduct, final Fund fund, final Staff officer,
|
final LoanProduct loanProduct, final Fund fund, final Staff officer,
|
||||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
||||||
final Boolean syncDisbursementWithMeeting) {
|
final Boolean syncDisbursementWithMeeting) {
|
||||||
final LoanStatus status = null;
|
final LoanStatus status = null;
|
||||||
final CodeValue loanPurpose = null;
|
final CodeValue loanPurpose = null;
|
||||||
@@ -307,7 +307,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
||||||
final Integer loanType, final LoanProduct loanProduct, final Fund fund, final Staff officer,
|
final Integer loanType, final LoanProduct loanProduct, final Fund fund, final Staff officer,
|
||||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||||
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
|
||||||
final Boolean syncDisbursementWithMeeting) {
|
final Boolean syncDisbursementWithMeeting) {
|
||||||
final LoanStatus status = null;
|
final LoanStatus status = null;
|
||||||
final CodeValue loanPurpose = null;
|
final CodeValue loanPurpose = null;
|
||||||
@@ -361,7 +361,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
this.collateral = null;
|
this.collateral = null;
|
||||||
}
|
}
|
||||||
this.loanOfficerHistory = null;
|
this.loanOfficerHistory = null;
|
||||||
|
|
||||||
this.syncDisbursementWithMeeting = syncDisbursementWithMeeting;
|
this.syncDisbursementWithMeeting = syncDisbursementWithMeeting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,7 +830,7 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add clientId, groupId and loanType changes to actual changes
|
// add clientId, groupId and loanType changes to actual changes
|
||||||
|
|
||||||
final String clientIdParamName = "clientId";
|
final String clientIdParamName = "clientId";
|
||||||
final Long clientId = this.client == null ? null : this.client.getId();
|
final Long clientId = this.client == null ? null : this.client.getId();
|
||||||
if (command.isChangeInLongParameterNamed(clientIdParamName, clientId)) {
|
if (command.isChangeInLongParameterNamed(clientIdParamName, clientId)) {
|
||||||
@@ -932,11 +932,11 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
final String syncDisbursementParameterName = "syncDisbursementWithMeeting";
|
final String syncDisbursementParameterName = "syncDisbursementWithMeeting";
|
||||||
if (command.isChangeInBooleanParameterNamed(syncDisbursementParameterName, isSyncDisbursementWithMeeting())) {
|
if (command.isChangeInBooleanParameterNamed(syncDisbursementParameterName, isSyncDisbursementWithMeeting())) {
|
||||||
final Boolean valueAsInput = command.booleanObjectValueOfParameterNamed(syncDisbursementParameterName);
|
final Boolean valueAsInput = command.booleanObjectValueOfParameterNamed(syncDisbursementParameterName);
|
||||||
actualChanges.put(syncDisbursementParameterName, valueAsInput);
|
actualChanges.put(syncDisbursementParameterName, valueAsInput);
|
||||||
this.syncDisbursementWithMeeting = valueAsInput;
|
this.syncDisbursementWithMeeting = valueAsInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String interestChargedFromDateParamName = "interestChargedFromDate";
|
final String interestChargedFromDateParamName = "interestChargedFromDate";
|
||||||
if (command.isChangeInLocalDateParameterNamed(interestChargedFromDateParamName, getInterestChargedFromDate())) {
|
if (command.isChangeInLocalDateParameterNamed(interestChargedFromDateParamName, getInterestChargedFromDate())) {
|
||||||
final String valueAsInput = command.stringValueOfParameterNamed(interestChargedFromDateParamName);
|
final String valueAsInput = command.stringValueOfParameterNamed(interestChargedFromDateParamName);
|
||||||
@@ -1003,14 +1003,14 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems));
|
actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final String loanTermFrequencyParamName = "loanTermFrequency";
|
final String loanTermFrequencyParamName = "loanTermFrequency";
|
||||||
if (command.isChangeInIntegerParameterNamed(loanTermFrequencyParamName, this.termFrequency)) {
|
if (command.isChangeInIntegerParameterNamed(loanTermFrequencyParamName, this.termFrequency)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(loanTermFrequencyParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(loanTermFrequencyParamName);
|
||||||
actualChanges.put(externalIdParamName, newValue);
|
actualChanges.put(externalIdParamName, newValue);
|
||||||
this.termFrequency = newValue;
|
this.termFrequency = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String loanTermFrequencyTypeParamName = "loanTermFrequencyType";
|
final String loanTermFrequencyTypeParamName = "loanTermFrequencyType";
|
||||||
if (command.isChangeInIntegerParameterNamed(loanTermFrequencyTypeParamName, this.termPeriodFrequencyType)) {
|
if (command.isChangeInIntegerParameterNamed(loanTermFrequencyTypeParamName, this.termPeriodFrequencyType)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(loanTermFrequencyTypeParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(loanTermFrequencyTypeParamName);
|
||||||
@@ -1100,18 +1100,12 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.a.future.date", errorMessage, submittedOn);
|
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.a.future.date", errorMessage, submittedOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(client == null)) {
|
if (client != null && client.isActivatedAfter(submittedOn)) {
|
||||||
if (submittedOn.isBefore(client.getActivationLocalDate())) {
|
final String errorMessage = "The date on which a loan is submitted cannot be earlier than client's activation date.";
|
||||||
final String errorMessage = "The date on which a loan is submitted cannot be earlier than client's activation date.";
|
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.client.activation.date", errorMessage, submittedOn);
|
||||||
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.client.activation.date", errorMessage,
|
} else if (group != null && group.isActivatedAfter(submittedOn)) {
|
||||||
submittedOn);
|
final String errorMessage = "The date on which a loan is submitted cannot be earlier than groups's activation date.";
|
||||||
}
|
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.group.activation.date", errorMessage, submittedOn);
|
||||||
} else if (!(group == null)) {
|
|
||||||
if (submittedOn.isBefore(group.getActivationLocalDate())) {
|
|
||||||
final String errorMessage = "The date on which a loan is submitted cannot be earlier than groups's activation date.";
|
|
||||||
throw new InvalidLoanStateTransitionException("submittal", "cannot.be.before.group.activation.date", errorMessage,
|
|
||||||
submittedOn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submittedOn.isAfter(getExpectedDisbursedOnLocalDate())) {
|
if (submittedOn.isAfter(getExpectedDisbursedOnLocalDate())) {
|
||||||
@@ -1379,14 +1373,17 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
final Integer loanTermFrequency = this.termFrequency;
|
final Integer loanTermFrequency = this.termFrequency;
|
||||||
final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType);
|
final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType);
|
||||||
//If ExpectedFirstRepaymentOnDate is null and repayment is synced with meeting then use firstRepaymentMeetingDate
|
// If ExpectedFirstRepaymentOnDate is null and repayment is synced with
|
||||||
//to generate repayment schedule dates
|
// meeting then use firstRepaymentMeetingDate
|
||||||
final LocalDate firstRepaymentOnDate = (getExpectedFirstRepaymentOnDate() == null) ? firstRepaymentMeetingDate : getExpectedFirstRepaymentOnDate();
|
// to generate repayment schedule dates
|
||||||
|
final LocalDate firstRepaymentOnDate = (getExpectedFirstRepaymentOnDate() == null) ? firstRepaymentMeetingDate
|
||||||
|
: getExpectedFirstRepaymentOnDate();
|
||||||
LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency,
|
LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency,
|
||||||
loanTermPeriodFrequencyType, getDisbursementDate(), firstRepaymentOnDate, getInArrearsTolerance(),
|
loanTermPeriodFrequencyType, getDisbursementDate(), firstRepaymentOnDate, getInArrearsTolerance(),
|
||||||
this.loanRepaymentScheduleDetail);
|
this.loanRepaymentScheduleDetail);
|
||||||
|
|
||||||
LoanScheduleModel loanSchedule = loanScheduleGenerator.generate(mc, applicationCurrency, loanApplicationTerms, this.charges, isHolidayEnabled, holidays);
|
LoanScheduleModel loanSchedule = loanScheduleGenerator.generate(mc, applicationCurrency, loanApplicationTerms, this.charges,
|
||||||
|
isHolidayEnabled, holidays);
|
||||||
|
|
||||||
updateLoanSchedule(loanSchedule);
|
updateLoanSchedule(loanSchedule);
|
||||||
}
|
}
|
||||||
@@ -2348,34 +2345,37 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return this.closedOnDate;
|
return this.closedOnDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule, final boolean isHolidayEnabled, final List<Holiday> holidays) {
|
public void updateLoanRepaymentScheduleDates(final LocalDate meetingStartDate, final String recuringRule,
|
||||||
//update repayment dates of repayment schedule installaments
|
final boolean isHolidayEnabled, final List<Holiday> holidays) {
|
||||||
LocalDate tmpFromDate = this.getDisbursementDate();//first repayment's from date is same as disbursement date.
|
// update repayment dates of repayment schedule installaments
|
||||||
|
LocalDate tmpFromDate = this.getDisbursementDate();// first repayment's
|
||||||
|
// from date is same
|
||||||
|
// as disbursement
|
||||||
|
// date.
|
||||||
LocalDate newRepaymentDate = null;
|
LocalDate newRepaymentDate = null;
|
||||||
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
|
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
|
||||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
//FIXME: AA this won't update repayment dates before current date.
|
// FIXME: AA this won't update repayment dates before current date.
|
||||||
if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) {
|
if (oldDueDate.isAfter(meetingStartDate) && oldDueDate.isAfter(DateUtils.getLocalDateOfTenant())) {
|
||||||
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
|
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
|
||||||
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
|
final String frequency = CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
|
||||||
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
|
final Integer loanRepaymentInterval = this.loanRepaymentScheduleDetail.getRepayEvery();
|
||||||
// reset repayment date with new meeting date
|
// reset repayment date with new meeting date
|
||||||
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate, loanRepaymentInterval, frequency);
|
newRepaymentDate = CalendarHelper.getNewRepaymentMeetingDate(recuringRule, meetingStartDate, oldDueDate,
|
||||||
if(isHolidayEnabled){
|
loanRepaymentInterval, frequency);
|
||||||
|
if (isHolidayEnabled) {
|
||||||
newRepaymentDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(newRepaymentDate, holidays);
|
newRepaymentDate = HolidayUtil.getRepaymentRescheduleDateToIfHoliday(newRepaymentDate, holidays);
|
||||||
}
|
}
|
||||||
loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate);
|
loanRepaymentScheduleInstallment.updateDueDate(newRepaymentDate);
|
||||||
//reset from date to get actual daysInPeriod
|
// reset from date to get actual daysInPeriod
|
||||||
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
||||||
tmpFromDate = newRepaymentDate;//update with new repayment date
|
tmpFromDate = newRepaymentDate;// update with new repayment date
|
||||||
}else{
|
} else {
|
||||||
tmpFromDate = oldDueDate;
|
tmpFromDate = oldDueDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) {
|
public void applyHolidayToRepaymentScheduleDates(final Holiday holiday) {
|
||||||
// first repayment's from date is same as disbursement date.
|
// first repayment's from date is same as disbursement date.
|
||||||
@@ -2383,9 +2383,10 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
// Loop through all loanRepayments
|
// Loop through all loanRepayments
|
||||||
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
|
for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : this.repaymentScheduleInstallments) {
|
||||||
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
final LocalDate oldDueDate = loanRepaymentScheduleInstallment.getDueDate();
|
||||||
|
|
||||||
//update from date if it's not same as previous installament's due date.
|
// update from date if it's not same as previous installament's due
|
||||||
if(!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)){
|
// date.
|
||||||
|
if (!loanRepaymentScheduleInstallment.getFromDate().isEqual(tmpFromDate)) {
|
||||||
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
loanRepaymentScheduleInstallment.updateFromDate(tmpFromDate);
|
||||||
}
|
}
|
||||||
if (oldDueDate.isAfter(holiday.getToDateLocalDate())) break;
|
if (oldDueDate.isAfter(holiday.getToDateLocalDate())) break;
|
||||||
@@ -2412,11 +2413,11 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return this.loanProductCounter;
|
return this.loanProductCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateClientLoanCounter(Integer newLoanCounter) {
|
public void updateClientLoanCounter(final Integer newLoanCounter) {
|
||||||
this.loanCounter = newLoanCounter;
|
this.loanCounter = newLoanCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanProductLoanCounter(Integer newLoanProductLoanCounter) {
|
public void updateLoanProductLoanCounter(final Integer newLoanProductLoanCounter) {
|
||||||
this.loanProductCounter = newLoanProductLoanCounter;
|
this.loanProductCounter = newLoanProductLoanCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2432,7 +2433,6 @@ public class Loan extends AbstractPersistable<Long> {
|
|||||||
return this.termFrequency;
|
return this.termFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Integer getTermPeriodFrequencyType() {
|
public Integer getTermPeriodFrequencyType() {
|
||||||
return this.termPeriodFrequencyType;
|
return this.termPeriodFrequencyType;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationApprovalCommandHandler implements NewCommandSourceHa
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.approveLoanApplication(command.entityId(), command);
|
return this.writePlatformService.approveApplication(command.entityId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationApprovalUndoCommandHandler implements NewCommandSour
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.undoLoanApplicationApproval(command.entityId(), command);
|
return this.writePlatformService.undoApplicationApproval(command.entityId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationDeletionCommandHandler implements NewCommandSourceHa
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.deleteLoanApplication(command.entityId());
|
return this.writePlatformService.deleteApplication(command.entityId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationModificationCommandHandler implements NewCommandSour
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.modifyLoanApplication(command.getLoanId(), command);
|
return this.writePlatformService.modifyApplication(command.getLoanId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationRejectedCommandHandler implements NewCommandSourceHa
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.rejectLoanApplication(command.entityId(), command);
|
return this.writePlatformService.rejectApplication(command.entityId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationSubmittalCommandHandler implements NewCommandSourceH
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.submitLoanApplication(command);
|
return this.writePlatformService.submitApplication(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -27,6 +27,6 @@ public class LoanApplicationWithdrawnByApplicantCommandHandler implements NewCom
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
return this.writePlatformService.applicantWithdrawsFromLoanApplication(command.entityId(), command);
|
return this.writePlatformService.applicantWithdrawsFromApplication(command.entityId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-2
@@ -647,8 +647,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
|||||||
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
|
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
"Validation errors exist.", dataValidationErrors); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateMinMaxConstraintValues(final JsonElement element, final LoanProduct loanProduct) {
|
public void validateMinMaxConstraintValues(final JsonElement element, final LoanProduct loanProduct) {
|
||||||
|
|||||||
+7
-7
@@ -10,17 +10,17 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
|||||||
|
|
||||||
public interface LoanApplicationWritePlatformService {
|
public interface LoanApplicationWritePlatformService {
|
||||||
|
|
||||||
CommandProcessingResult submitLoanApplication(JsonCommand command);
|
CommandProcessingResult submitApplication(JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult modifyLoanApplication(Long loanId, JsonCommand command);
|
CommandProcessingResult modifyApplication(Long loanId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult deleteLoanApplication(Long loanId);
|
CommandProcessingResult deleteApplication(Long loanId);
|
||||||
|
|
||||||
CommandProcessingResult approveLoanApplication(Long loanId, JsonCommand command);
|
CommandProcessingResult approveApplication(Long loanId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult undoLoanApplicationApproval(Long loanId, JsonCommand command);
|
CommandProcessingResult undoApplicationApproval(Long loanId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult rejectLoanApplication(Long loanId, JsonCommand command);
|
CommandProcessingResult rejectApplication(Long loanId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult applicantWithdrawsFromLoanApplication(Long loanId, JsonCommand command);
|
CommandProcessingResult applicantWithdrawsFromApplication(Long loanId, JsonCommand command);
|
||||||
}
|
}
|
||||||
+7
-7
@@ -138,7 +138,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult submitLoanApplication(final JsonCommand command) {
|
public CommandProcessingResult submitApplication(final JsonCommand command) {
|
||||||
|
|
||||||
final AppUser currentUser = context.authenticatedUser();
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult modifyLoanApplication(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult modifyApplication(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
@@ -384,7 +384,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult deleteLoanApplication(final Long loanId) {
|
public CommandProcessingResult deleteApplication(final Long loanId) {
|
||||||
|
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
@@ -408,7 +408,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult approveLoanApplication(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult approveApplication(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
final AppUser currentUser = context.authenticatedUser();
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
@@ -441,7 +441,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult undoLoanApplicationApproval(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult undoApplicationApproval(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
context.authenticatedUser();
|
context.authenticatedUser();
|
||||||
|
|
||||||
@@ -473,7 +473,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult rejectLoanApplication(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult rejectApplication(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
final AppUser currentUser = context.authenticatedUser();
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
@@ -505,7 +505,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult applicantWithdrawsFromLoanApplication(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult applicantWithdrawsFromApplication(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
final AppUser currentUser = context.authenticatedUser();
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.mifosplatform.portfolio.client.domain.Client;
|
|||||||
import org.mifosplatform.portfolio.group.domain.Group;
|
import org.mifosplatform.portfolio.group.domain.Group;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||||
import org.mifosplatform.useradministration.domain.AppUser;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -53,10 +54,10 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@Column(name = "note_type_enum")
|
@Column(name = "note_type_enum")
|
||||||
private final Integer noteTypeId;
|
private final Integer noteTypeId;
|
||||||
|
|
||||||
// @SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
// @ManyToOne
|
@ManyToOne
|
||||||
// @JoinColumn(name = "saving_account_id", nullable = true)
|
@JoinColumn(name = "savings_account_id", nullable = true)
|
||||||
// private SavingAccount savingAccount;
|
private SavingsAccount savingsAccount;
|
||||||
|
|
||||||
public static Note clientNoteFromJson(final Client client, final JsonCommand command) {
|
public static Note clientNoteFromJson(final Client client, final JsonCommand command) {
|
||||||
final String note = command.stringValueOfParameterNamed("note");
|
final String note = command.stringValueOfParameterNamed("note");
|
||||||
@@ -76,10 +77,9 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
return new Note(loan, loanTransaction, note);
|
return new Note(loan, loanTransaction, note);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public static Note savingNote(final SavingAccount account, final String
|
public static Note savingNote(final SavingsAccount account, final String note) {
|
||||||
// note) {
|
return new Note(account, note);
|
||||||
// return new Note(account, note);
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
private Note(final Client client, final String note) {
|
private Note(final Client client, final String note) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
@@ -118,12 +118,12 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.noteTypeId = null;
|
this.noteTypeId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Note(final SavingAccount account, final String note) {
|
public Note(final SavingsAccount account, final String note) {
|
||||||
// this.savingAccount = account;
|
this.savingsAccount = account;
|
||||||
// this.client = account.getClient();
|
this.client = account.getClient();
|
||||||
// this.note = note;
|
this.note = note;
|
||||||
// this.noteTypeId = NoteType.SAVING_ACCOUNT.getValue();
|
this.noteTypeId = NoteType.SAVING_ACCOUNT.getValue();
|
||||||
// }
|
}
|
||||||
|
|
||||||
public Map<String, Object> update(final JsonCommand command) {
|
public Map<String, Object> update(final JsonCommand command) {
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
|
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
|
||||||
|
|||||||
+2
-2
@@ -26,7 +26,7 @@ public interface NoteRepository extends JpaRepository<Note, Long>, JpaSpecificat
|
|||||||
|
|
||||||
Note findByLoanTransactionIdAndId(Long loanTransactionId, Long id);
|
Note findByLoanTransactionIdAndId(Long loanTransactionId, Long id);
|
||||||
|
|
||||||
// Note findByDepositAccountIdAndId(Long depositAccountId, Long id);
|
List<Note> findBySavingsAccountId(Long savingAccountId);
|
||||||
|
|
||||||
// Note findBySavingAccountIdAndId(Long savingAccountId, Long id);
|
// Note findBySavingsAccountIdAndId(Long savingAccountId, Long id);
|
||||||
}
|
}
|
||||||
+3
-1
@@ -3,7 +3,9 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enumeration of different transactions that can occur on a
|
* An enumeration of different transactions that can occur on a
|
||||||
+7
-5
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.api;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -32,8 +32,10 @@ public class SavingsApiConstants {
|
|||||||
public static final String clientIdParamName = "clientId";
|
public static final String clientIdParamName = "clientId";
|
||||||
public static final String groupIdParamName = "groupId";
|
public static final String groupIdParamName = "groupId";
|
||||||
public static final String productIdParamName = "productId";
|
public static final String productIdParamName = "productId";
|
||||||
|
public static final String fieldOfficerIdParamName = "fieldOfficerId";
|
||||||
|
public static final String submittedOnDateParamName = "submittedOnDate";
|
||||||
public static final String activeParamName = "active";
|
public static final String activeParamName = "active";
|
||||||
public static final String activationDateParamName = "activationDate";
|
public static final String activationDateParamName = "activatedOnDate";
|
||||||
public static final String nameParamName = "name";
|
public static final String nameParamName = "name";
|
||||||
public static final String descriptionParamName = "description";
|
public static final String descriptionParamName = "description";
|
||||||
public static final String currencyCodeParamName = "currencyCode";
|
public static final String currencyCodeParamName = "currencyCode";
|
||||||
@@ -52,7 +54,7 @@ public class SavingsApiConstants {
|
|||||||
public static final String annualFeeOnMonthDayParamName = "annualFeeOnMonthDay";
|
public static final String annualFeeOnMonthDayParamName = "annualFeeOnMonthDay";
|
||||||
public static final String accountingRuleParamName = "accountingRule";
|
public static final String accountingRuleParamName = "accountingRule";
|
||||||
public static final String paymentTypeIdParamName = "paymentTypeId";
|
public static final String paymentTypeIdParamName = "paymentTypeId";
|
||||||
public static final String accountNumberParamName = "accountNumber";
|
public static final String transactionAccountNumberParamName = "accountNumber";
|
||||||
public static final String checkNumberParamName = "checkNumber";
|
public static final String checkNumberParamName = "checkNumber";
|
||||||
public static final String routingCodeParamName = "routingCode";
|
public static final String routingCodeParamName = "routingCode";
|
||||||
public static final String receiptNumberParamName = "receiptNumber";
|
public static final String receiptNumberParamName = "receiptNumber";
|
||||||
@@ -89,7 +91,7 @@ public class SavingsApiConstants {
|
|||||||
|
|
||||||
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||||
dateFormatParamName, monthDayFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName,
|
dateFormatParamName, monthDayFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName,
|
||||||
productIdParamName, activeParamName, activationDateParamName, nominalAnnualInterestRateParamName,
|
productIdParamName, fieldOfficerIdParamName, submittedOnDateParamName, nominalAnnualInterestRateParamName,
|
||||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
||||||
@@ -112,7 +114,7 @@ public class SavingsApiConstants {
|
|||||||
|
|
||||||
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||||
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
||||||
accountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName));
|
transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName));
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
|
public static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName,
|
||||||
"accountId", accountNoParamName, "currency", "amount"));
|
"accountId", accountNoParamName, "currency", "amount"));
|
||||||
+34
-15
@@ -3,7 +3,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -15,13 +19,13 @@ public enum SavingsCompoundingInterestPeriodType {
|
|||||||
|
|
||||||
INVALID(0, "savingsCompoundingInterestPeriodType.invalid"), //
|
INVALID(0, "savingsCompoundingInterestPeriodType.invalid"), //
|
||||||
DAILY(1, "savingsCompoundingInterestPeriodType.daily"), //
|
DAILY(1, "savingsCompoundingInterestPeriodType.daily"), //
|
||||||
WEEKLY(2, "savingsCompoundingInterestPeriodType.weekly"), //
|
// WEEKLY(2, "savingsCompoundingInterestPeriodType.weekly"), //
|
||||||
BIWEEKLY(3, "savingsCompoundingInterestPeriodType.biweekly"), //
|
// BIWEEKLY(3, "savingsCompoundingInterestPeriodType.biweekly"), //
|
||||||
MONTHLY(4, "savingsCompoundingInterestPeriodType.monthly"), //
|
MONTHLY(4, "savingsCompoundingInterestPeriodType.monthly");
|
||||||
QUATERLY(5, "savingsCompoundingInterestPeriodType.quarterly"), //
|
// QUATERLY(5, "savingsCompoundingInterestPeriodType.quarterly"), //
|
||||||
BI_ANNUAL(6, "savingsCompoundingInterestPeriodType.biannual"), //
|
// BI_ANNUAL(6, "savingsCompoundingInterestPeriodType.biannual"), //
|
||||||
ANNUAL(7, "savingsCompoundingInterestPeriodType.annual"), //
|
// ANNUAL(7, "savingsCompoundingInterestPeriodType.annual"), //
|
||||||
NO_COMPOUNDING_SIMPLE_INTEREST(8, "savingsCompoundingInterestPeriodType.nocompounding");
|
// NO_COMPOUNDING_SIMPLE_INTEREST(8, "savingsCompoundingInterestPeriodType.nocompounding");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -39,6 +43,15 @@ public enum SavingsCompoundingInterestPeriodType {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Object[] integerValues() {
|
||||||
|
List<Integer> values = new ArrayList<Integer>();
|
||||||
|
for (SavingsCompoundingInterestPeriodType enumType : values()) {
|
||||||
|
values.add(enumType.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return values.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public static SavingsCompoundingInterestPeriodType fromInt(final Integer type) {
|
public static SavingsCompoundingInterestPeriodType fromInt(final Integer type) {
|
||||||
SavingsCompoundingInterestPeriodType repaymentFrequencyType = SavingsCompoundingInterestPeriodType.INVALID;
|
SavingsCompoundingInterestPeriodType repaymentFrequencyType = SavingsCompoundingInterestPeriodType.INVALID;
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
@@ -47,28 +60,34 @@ public enum SavingsCompoundingInterestPeriodType {
|
|||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.DAILY;
|
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.DAILY;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.WEEKLY;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.WEEKLY;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.BIWEEKLY;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.BIWEEKLY;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.MONTHLY;
|
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.MONTHLY;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.QUATERLY;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.QUATERLY;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.BI_ANNUAL;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.BI_ANNUAL;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.ANNUAL;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.ANNUAL;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
repaymentFrequencyType = SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST;
|
// repaymentFrequencyType =
|
||||||
|
// SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return repaymentFrequencyType;
|
return repaymentFrequencyType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <ul>
|
* <ul>
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <ul>
|
* <ul>
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enumeration of supported calendar periods used in savings.
|
* An enumeration of supported calendar periods used in savings.
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interest posting period is the span of time at the end of which savings
|
||||||
|
* earned but not yet credited/posted in a client's account is credited/posted.
|
||||||
|
*/
|
||||||
|
public enum SavingsPostingInterestPeriodType {
|
||||||
|
|
||||||
|
INVALID(0, "savingsPostingInterestPeriodType.invalid"), //
|
||||||
|
MONTHLY(4, "savingsPostingInterestPeriodType.monthly"), //
|
||||||
|
QUATERLY(5, "savingsPostingInterestPeriodType.quarterly"), //
|
||||||
|
ANNUAL(7, "savingsPostingInterestPeriodType.annual");
|
||||||
|
|
||||||
|
private final Integer value;
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
private SavingsPostingInterestPeriodType(final Integer value, final String code) {
|
||||||
|
this.value = value;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SavingsPostingInterestPeriodType fromInt(final Integer type) {
|
||||||
|
SavingsPostingInterestPeriodType repaymentFrequencyType = SavingsPostingInterestPeriodType.INVALID;
|
||||||
|
if (type != null) {
|
||||||
|
switch (type) {
|
||||||
|
case 4:
|
||||||
|
repaymentFrequencyType = SavingsPostingInterestPeriodType.MONTHLY;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
repaymentFrequencyType = SavingsPostingInterestPeriodType.QUATERLY;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
repaymentFrequencyType = SavingsPostingInterestPeriodType.ANNUAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return repaymentFrequencyType;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings;
|
||||||
|
|
||||||
public enum SavingsWithdrawalFeesType {
|
public enum SavingsWithdrawalFeesType {
|
||||||
|
|
||||||
+3
-1
@@ -31,6 +31,7 @@ import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSeriali
|
|||||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
|
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountReadPlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsAccountReadPlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -72,7 +73,8 @@ public class SavingsAccountTransactionsApiResource {
|
|||||||
@Path("template")
|
@Path("template")
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public String retrieveTemplate(@PathParam("savingsId") final Long savingsId, @QueryParam("command") final String commandParam,
|
public String retrieveTemplate(@PathParam("savingsId") final Long savingsId,
|
||||||
|
// @QueryParam("command") final String commandParam,
|
||||||
@Context final UriInfo uriInfo) {
|
@Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|||||||
+62
-10
@@ -12,6 +12,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
@@ -36,7 +37,9 @@ import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSeriali
|
|||||||
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
import org.mifosplatform.infrastructure.core.service.Page;
|
import org.mifosplatform.infrastructure.core.service.Page;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||||
@@ -81,12 +84,15 @@ public class SavingsAccountsApiResource {
|
|||||||
@Path("template")
|
@Path("template")
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public String retrieveTemplate(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId,
|
public String template(@QueryParam("clientId") final Long clientId, @QueryParam("groupId") final Long groupId,
|
||||||
@QueryParam("productId") final Long productId, @Context final UriInfo uriInfo) {
|
@QueryParam("productId") final Long productId,
|
||||||
|
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
|
||||||
|
@Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
final SavingsAccountData savingsAccount = this.savingsAccountReadPlatformService.retrieveTemplate(clientId, groupId, productId);
|
final SavingsAccountData savingsAccount = this.savingsAccountReadPlatformService.retrieveTemplate(clientId, groupId, productId,
|
||||||
|
staffInSelectedOfficeOnly);
|
||||||
|
|
||||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
return this.toApiJsonSerializer.serialize(settings, savingsAccount, SavingsApiConstants.SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
return this.toApiJsonSerializer.serialize(settings, savingsAccount, SavingsApiConstants.SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
||||||
@@ -113,7 +119,7 @@ public class SavingsAccountsApiResource {
|
|||||||
@POST
|
@POST
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public String create(final String apiRequestBodyAsJson) {
|
public String submitApplication(final String apiRequestBodyAsJson) {
|
||||||
|
|
||||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSavingsAccount().withJson(apiRequestBodyAsJson).build();
|
final CommandWrapper commandRequest = new CommandWrapperBuilder().createSavingsAccount().withJson(apiRequestBodyAsJson).build();
|
||||||
|
|
||||||
@@ -147,6 +153,7 @@ public class SavingsAccountsApiResource {
|
|||||||
|
|
||||||
Collection<SavingsAccountTransactionData> transactions = null;
|
Collection<SavingsAccountTransactionData> transactions = null;
|
||||||
Collection<SavingsProductData> productOptions = null;
|
Collection<SavingsProductData> productOptions = null;
|
||||||
|
Collection<StaffData> fieldOfficerOptions = null;
|
||||||
Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
Collection<EnumOptionData> interestCompoundingPostingTypeOptions = null;
|
Collection<EnumOptionData> interestCompoundingPostingTypeOptions = null;
|
||||||
Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||||
@@ -174,16 +181,49 @@ public class SavingsAccountsApiResource {
|
|||||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
if (settings.isTemplate()) {
|
if (settings.isTemplate()) {
|
||||||
productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
|
productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
|
||||||
|
|
||||||
|
// FIXME - FOR CHANGE SAVINGS ACCOUNT APPLICATION need to determine
|
||||||
|
// office id of savings account
|
||||||
|
// if (savingsAccount.officeId() != null) {
|
||||||
|
//
|
||||||
|
// if (staffInSelectedOfficeOnly) {
|
||||||
|
// // only bring back loan officers in selected branch/office
|
||||||
|
// Collection<StaffData> fieldOfficersInBranch =
|
||||||
|
// this.staffReadPlatformService
|
||||||
|
// .retrieveAllLoanOfficersInOfficeById(officeId);
|
||||||
|
//
|
||||||
|
// if (!CollectionUtils.isEmpty(fieldOfficersInBranch)) {
|
||||||
|
// fieldOfficerOptions = new
|
||||||
|
// ArrayList<StaffData>(fieldOfficersInBranch);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // by default bring back all officers in selected
|
||||||
|
// // branch/office as well as officers in office above
|
||||||
|
// // this office
|
||||||
|
// final boolean restrictToLoanOfficersOnly = true;
|
||||||
|
// Collection<StaffData> loanOfficersInHierarchy =
|
||||||
|
// this.staffReadPlatformService
|
||||||
|
// .retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId,
|
||||||
|
// restrictToLoanOfficersOnly);
|
||||||
|
//
|
||||||
|
// if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
|
||||||
|
// fieldOfficerOptions = new
|
||||||
|
// ArrayList<StaffData>(loanOfficersInHierarchy);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService.retrieveCompoundingInterestPeriodTypeOptions();
|
interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService.retrieveCompoundingInterestPeriodTypeOptions();
|
||||||
interestCompoundingPostingTypeOptions = this.dropdownReadPlatformService.retrieveInterestPostingPeriodTypeOptions();
|
interestCompoundingPostingTypeOptions = this.dropdownReadPlatformService.retrieveInterestPostingPeriodTypeOptions();
|
||||||
interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions();
|
interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions();
|
||||||
|
interestCalculationDaysInYearTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationDaysInYearTypeOptions();
|
||||||
lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions();
|
lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions();
|
||||||
withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestCompoundingPeriodTypeOptions,
|
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, fieldOfficerOptions,
|
||||||
interestCompoundingPostingTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
interestCompoundingPeriodTypeOptions, interestCompoundingPostingTypeOptions, interestCalculationTypeOptions,
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@@ -210,7 +250,19 @@ public class SavingsAccountsApiResource {
|
|||||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||||
|
|
||||||
CommandProcessingResult result = null;
|
CommandProcessingResult result = null;
|
||||||
if (is(commandParam, "activate")) {
|
if (is(commandParam, "reject")) {
|
||||||
|
final CommandWrapper commandRequest = builder.rejectSavingsAccountApplication(accountId).build();
|
||||||
|
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
} else if (is(commandParam, "withdrawnByApplicant")) {
|
||||||
|
final CommandWrapper commandRequest = builder.withdrawSavingsAccountApplication(accountId).build();
|
||||||
|
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
} else if (is(commandParam, "approve")) {
|
||||||
|
final CommandWrapper commandRequest = builder.approveSavingsAccountApplication(accountId).build();
|
||||||
|
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
} else if (is(commandParam, "undoapproval")) {
|
||||||
|
final CommandWrapper commandRequest = builder.undoSavingsAccountApplication(accountId).build();
|
||||||
|
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
} else if (is(commandParam, "activate")) {
|
||||||
final CommandWrapper commandRequest = builder.savingsAccountActivation(accountId).build();
|
final CommandWrapper commandRequest = builder.savingsAccountActivation(accountId).build();
|
||||||
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
} else if (is(commandParam, "calculateInterest")) {
|
} else if (is(commandParam, "calculateInterest")) {
|
||||||
@@ -223,8 +275,8 @@ public class SavingsAccountsApiResource {
|
|||||||
|
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
//
|
//
|
||||||
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "activate", "calculateInterest",
|
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "reject", "withdrawnByApplicant", "approve",
|
||||||
"postInterest" });
|
"undoapproval", "activate", "calculateInterest", "postInterest" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.toApiJsonSerializer.serialize(result);
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
|
|||||||
+6
-5
@@ -42,11 +42,12 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext
|
|||||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||||
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
|
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
|
import org.mifosplatform.portfolio.paymentdetail.PaymentDetailConstants;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsDropdownReadPlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsDropdownReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsProductReadPlatformService;
|
||||||
@@ -180,7 +181,7 @@ public class SavingsProductsApiResource {
|
|||||||
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY);
|
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY);
|
||||||
|
|
||||||
final EnumOptionData interestPostingPeriodType = SavingsEnumerations
|
final EnumOptionData interestPostingPeriodType = SavingsEnumerations
|
||||||
.interestPostingPeriodType(SavingsInterestPostingPeriodType.MONTHLY);
|
.interestPostingPeriodType(SavingsPostingInterestPeriodType.MONTHLY);
|
||||||
|
|
||||||
final EnumOptionData interestCalculationType = SavingsEnumerations
|
final EnumOptionData interestCalculationType = SavingsEnumerations
|
||||||
.interestCalculationType(SavingsInterestCalculationType.DAILY_BALANCE);
|
.interestCalculationType(SavingsInterestCalculationType.DAILY_BALANCE);
|
||||||
|
|||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable data object represent the important time-line events of a savings
|
||||||
|
* account application.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class SavingsAccountApplicationTimelineData {
|
||||||
|
|
||||||
|
private final LocalDate submittedOnDate;
|
||||||
|
private final String submittedByUsername;
|
||||||
|
private final String submittedByFirstname;
|
||||||
|
private final String submittedByLastname;
|
||||||
|
private final LocalDate rejectedOnDate;
|
||||||
|
private final String rejectedByUsername;
|
||||||
|
private final String rejectedByFirstname;
|
||||||
|
private final String rejectedByLastname;
|
||||||
|
private final LocalDate withdrawnOnDate;
|
||||||
|
private final String withdrawnByUsername;
|
||||||
|
private final String withdrawnByFirstname;
|
||||||
|
private final String withdrawnByLastname;
|
||||||
|
private final LocalDate approvedOnDate;
|
||||||
|
private final String approvedByUsername;
|
||||||
|
private final String approvedByFirstname;
|
||||||
|
private final String approvedByLastname;
|
||||||
|
private final LocalDate activatedOnDate;
|
||||||
|
private final String activatedByUsername;
|
||||||
|
private final String activatedByFirstname;
|
||||||
|
private final String activatedByLastname;
|
||||||
|
private final LocalDate closedOnDate;
|
||||||
|
private final String closedByUsername;
|
||||||
|
private final String closedByFirstname;
|
||||||
|
private final String closedByLastname;
|
||||||
|
|
||||||
|
public static SavingsAccountApplicationTimelineData templateDefault() {
|
||||||
|
|
||||||
|
final LocalDate submittedOnDate = null;
|
||||||
|
final String submittedByUsername = null;
|
||||||
|
final String submittedByFirstname = null;
|
||||||
|
final String submittedByLastname = null;
|
||||||
|
final LocalDate rejectedOnDate = null;
|
||||||
|
final String rejectedByUsername = null;
|
||||||
|
final String rejectedByFirstname = null;
|
||||||
|
final String rejectedByLastname = null;
|
||||||
|
final LocalDate withdrawnOnDate = null;
|
||||||
|
final String withdrawnByUsername = null;
|
||||||
|
final String withdrawnByFirstname = null;
|
||||||
|
final String withdrawnByLastname = null;
|
||||||
|
final LocalDate approvedOnDate = null;
|
||||||
|
final String approvedByUsername = null;
|
||||||
|
final String approvedByFirstname = null;
|
||||||
|
final String approvedByLastname = null;
|
||||||
|
final LocalDate activatedOnDate = null;
|
||||||
|
final String activatedByUsername = null;
|
||||||
|
final String activatedByFirstname = null;
|
||||||
|
final String activatedByLastname = null;
|
||||||
|
final LocalDate closedOnDate = null;
|
||||||
|
final String closedByUsername = null;
|
||||||
|
final String closedByFirstname = null;
|
||||||
|
final String closedByLastname = null;
|
||||||
|
|
||||||
|
return new SavingsAccountApplicationTimelineData(submittedOnDate, submittedByUsername, submittedByFirstname, submittedByLastname,
|
||||||
|
rejectedOnDate, rejectedByUsername, rejectedByFirstname, rejectedByLastname, withdrawnOnDate, withdrawnByUsername,
|
||||||
|
withdrawnByFirstname, withdrawnByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname,
|
||||||
|
activatedOnDate, activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, closedByUsername,
|
||||||
|
closedByFirstname, closedByLastname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SavingsAccountApplicationTimelineData(final LocalDate submittedOnDate, final String submittedByUsername,
|
||||||
|
final String submittedByFirstname, final String submittedByLastname, final LocalDate rejectedOnDate,
|
||||||
|
final String rejectedByUsername, final String rejectedByFirstname, final String rejectedByLastname,
|
||||||
|
final LocalDate withdrawnOnDate, final String withdrawnByUsername, final String withdrawnByFirstname,
|
||||||
|
final String withdrawnByLastname, final LocalDate approvedOnDate, final String approvedByUsername,
|
||||||
|
final String approvedByFirstname, final String approvedByLastname, final LocalDate activatedOnDate,
|
||||||
|
final String activatedByUsername, final String activatedByFirstname, final String activatedByLastname,
|
||||||
|
final LocalDate closedOnDate, final String closedByUsername, final String closedByFirstname, final String closedByLastname) {
|
||||||
|
this.submittedOnDate = submittedOnDate;
|
||||||
|
this.submittedByUsername = submittedByUsername;
|
||||||
|
this.submittedByFirstname = submittedByFirstname;
|
||||||
|
this.submittedByLastname = submittedByLastname;
|
||||||
|
this.rejectedOnDate = rejectedOnDate;
|
||||||
|
this.rejectedByUsername = rejectedByUsername;
|
||||||
|
this.rejectedByFirstname = rejectedByFirstname;
|
||||||
|
this.rejectedByLastname = rejectedByLastname;
|
||||||
|
this.withdrawnOnDate = withdrawnOnDate;
|
||||||
|
this.withdrawnByUsername = withdrawnByUsername;
|
||||||
|
this.withdrawnByFirstname = withdrawnByFirstname;
|
||||||
|
this.withdrawnByLastname = withdrawnByLastname;
|
||||||
|
this.approvedOnDate = approvedOnDate;
|
||||||
|
this.approvedByUsername = approvedByUsername;
|
||||||
|
this.approvedByFirstname = approvedByFirstname;
|
||||||
|
this.approvedByLastname = approvedByLastname;
|
||||||
|
this.activatedOnDate = activatedOnDate;
|
||||||
|
this.activatedByUsername = activatedByUsername;
|
||||||
|
this.activatedByFirstname = activatedByFirstname;
|
||||||
|
this.activatedByLastname = activatedByLastname;
|
||||||
|
this.closedOnDate = closedOnDate;
|
||||||
|
this.closedByUsername = closedByUsername;
|
||||||
|
this.closedByFirstname = closedByFirstname;
|
||||||
|
this.closedByLastname = closedByLastname;
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
-49
@@ -12,6 +12,7 @@ import org.joda.time.LocalDate;
|
|||||||
import org.joda.time.MonthDay;
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||||
|
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object representing a savings account.
|
* Immutable data object representing a savings account.
|
||||||
@@ -21,14 +22,16 @@ public class SavingsAccountData {
|
|||||||
private final Long id;
|
private final Long id;
|
||||||
private final String accountNo;
|
private final String accountNo;
|
||||||
private final String externalId;
|
private final String externalId;
|
||||||
private final SavingsAccountStatusEnumData status;
|
|
||||||
private final LocalDate activationDate;
|
|
||||||
private final Long groupId;
|
private final Long groupId;
|
||||||
private final String groupName;
|
private final String groupName;
|
||||||
private final Long clientId;
|
private final Long clientId;
|
||||||
private final String clientName;
|
private final String clientName;
|
||||||
private final Long savingsProductId;
|
private final Long savingsProductId;
|
||||||
private final String savingsProductName;
|
private final String savingsProductName;
|
||||||
|
private final Long fieldofficerId;
|
||||||
|
private final String fieldofficerName;
|
||||||
|
private final SavingsAccountStatusEnumData status;
|
||||||
|
private final SavingsAccountApplicationTimelineData timeline;
|
||||||
private final CurrencyData currency;
|
private final CurrencyData currency;
|
||||||
private final BigDecimal nominalAnnualInterestRate;
|
private final BigDecimal nominalAnnualInterestRate;
|
||||||
private final EnumOptionData interestCompoundingPeriodType;
|
private final EnumOptionData interestCompoundingPeriodType;
|
||||||
@@ -53,6 +56,8 @@ public class SavingsAccountData {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final Collection<SavingsProductData> productOptions;
|
private final Collection<SavingsProductData> productOptions;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
private final Collection<StaffData> fieldOfficerOptions;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
|
private final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final Collection<EnumOptionData> interestPostingPeriodTypeOptions;
|
private final Collection<EnumOptionData> interestPostingPeriodTypeOptions;
|
||||||
@@ -65,17 +70,19 @@ public class SavingsAccountData {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final Collection<EnumOptionData> withdrawalFeeTypeOptions;
|
private final Collection<EnumOptionData> withdrawalFeeTypeOptions;
|
||||||
|
|
||||||
public static SavingsAccountData instance(final Long id, final String accountNo, final String externalId,
|
public static SavingsAccountData instance(final Long id, final String accountNo, final String externalId, final Long groupId,
|
||||||
final SavingsAccountStatusEnumData status, final LocalDate activationDate, final Long groupId, final String groupName,
|
final String groupName, final Long clientId, final String clientName, final Long productId, final String productName,
|
||||||
final Long clientId, final String clientName, final Long productId, final String productName, final CurrencyData currency,
|
final Long fieldOfficerId, final String fieldOfficerName, final SavingsAccountStatusEnumData status,
|
||||||
final BigDecimal interestRate, final EnumOptionData interestCompoundingPeriodType,
|
final SavingsAccountApplicationTimelineData timeline, final CurrencyData currency, final BigDecimal interestRate,
|
||||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
final EnumOptionData interestCompoundingPeriodType, final EnumOptionData interestPostingPeriodType,
|
||||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||||
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||||
final LocalDate annualFeeNextDueDate, final SavingsAccountSummaryData summary) {
|
final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay, final LocalDate annualFeeNextDueDate,
|
||||||
|
final SavingsAccountSummaryData summary) {
|
||||||
|
|
||||||
final Collection<SavingsProductData> productOptions = null;
|
final Collection<SavingsProductData> productOptions = null;
|
||||||
|
final Collection<StaffData> fieldOfficerOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||||
@@ -85,32 +92,34 @@ public class SavingsAccountData {
|
|||||||
|
|
||||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||||
|
|
||||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||||
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
fieldOfficerId, fieldOfficerName, status, timeline, currency, interestRate, interestCompoundingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
annualFeeOnMonthDay, annualFeeNextDueDate, summary, transactions, productOptions, fieldOfficerOptions,
|
||||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||||
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
final Collection<SavingsProductData> productOptions, final Collection<StaffData> fieldOfficerOptions,
|
||||||
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||||
final Collection<SavingsAccountTransactionData> transactions) {
|
final Collection<SavingsAccountTransactionData> transactions) {
|
||||||
|
|
||||||
return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate,
|
return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||||
account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId,
|
account.clientId, account.clientName, account.savingsProductId, account.savingsProductName, account.fieldofficerId,
|
||||||
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
account.fieldofficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||||
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||||
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
|
account.interestCalculationDaysInYearType, account.minRequiredOpeningBalance, account.lockinPeriodFrequency,
|
||||||
account.withdrawalFeeAmount, account.withdrawalFeeType, account.annualFeeAmount, account.annualFeeOnMonthDay,
|
account.lockinPeriodFrequencyType, account.withdrawalFeeAmount, account.withdrawalFeeType, account.annualFeeAmount,
|
||||||
account.annualFeeNextDueDate, account.summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
account.annualFeeOnMonthDay, account.annualFeeNextDueDate, account.summary, transactions, productOptions,
|
||||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||||
|
withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||||
@@ -119,10 +128,12 @@ public class SavingsAccountData {
|
|||||||
final Long id = null;
|
final Long id = null;
|
||||||
final String accountNo = null;
|
final String accountNo = null;
|
||||||
final String externalId = null;
|
final String externalId = null;
|
||||||
final SavingsAccountStatusEnumData status = null;
|
|
||||||
final LocalDate activationDate = null;
|
|
||||||
final Long productId = null;
|
final Long productId = null;
|
||||||
final String productName = null;
|
final String productName = null;
|
||||||
|
final Long fieldOfficerId = null;
|
||||||
|
final String fieldOfficerName = null;
|
||||||
|
final SavingsAccountStatusEnumData status = null;
|
||||||
|
final SavingsAccountApplicationTimelineData timeline = null;
|
||||||
final CurrencyData currency = null;
|
final CurrencyData currency = null;
|
||||||
final BigDecimal nominalAnnualInterestRate = null;
|
final BigDecimal nominalAnnualInterestRate = null;
|
||||||
final EnumOptionData interestPeriodType = null;
|
final EnumOptionData interestPeriodType = null;
|
||||||
@@ -142,6 +153,7 @@ public class SavingsAccountData {
|
|||||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||||
|
|
||||||
final Collection<SavingsProductData> productOptions = null;
|
final Collection<SavingsProductData> productOptions = null;
|
||||||
|
final Collection<StaffData> fieldOfficerOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||||
@@ -149,25 +161,26 @@ public class SavingsAccountData {
|
|||||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||||
|
|
||||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
return new SavingsAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||||
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
|
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
annualFeeOnMonthDay, annualFeeNextDueDate, summary, transactions, productOptions, fieldOfficerOptions,
|
||||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
|
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName,
|
||||||
final LocalDate activationDate, final Long groupId, final String groupName, final Long clientId, final String clientName,
|
final Long clientId, final String clientName, final Long productId, final String productName, final Long fieldofficerId,
|
||||||
final Long productId, final String productName, final CurrencyData currency, final BigDecimal nominalAnnualInterestRate,
|
final String fieldofficerName, final SavingsAccountStatusEnumData status, final SavingsAccountApplicationTimelineData timeline,
|
||||||
final EnumOptionData interestPeriodType, final EnumOptionData interestPostingPeriodType,
|
final CurrencyData currency, final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestPeriodType,
|
||||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||||
final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay, final LocalDate annualFeeNextDueDate,
|
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||||
final SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
final LocalDate annualFeeNextDueDate, final SavingsAccountSummaryData summary,
|
||||||
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsProductData> productOptions,
|
||||||
|
final Collection<StaffData> fieldOfficerOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||||
@@ -175,14 +188,16 @@ public class SavingsAccountData {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.accountNo = accountNo;
|
this.accountNo = accountNo;
|
||||||
this.externalId = externalId;
|
this.externalId = externalId;
|
||||||
this.status = status;
|
|
||||||
this.activationDate = activationDate;
|
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.groupName = groupName;
|
this.groupName = groupName;
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
this.clientName = clientName;
|
this.clientName = clientName;
|
||||||
this.savingsProductId = productId;
|
this.savingsProductId = productId;
|
||||||
this.savingsProductName = productName;
|
this.savingsProductName = productName;
|
||||||
|
this.fieldofficerId = fieldofficerId;
|
||||||
|
this.fieldofficerName = fieldofficerName;
|
||||||
|
this.status = status;
|
||||||
|
this.timeline = timeline;
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
|
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
|
||||||
this.interestCompoundingPeriodType = interestPeriodType;
|
this.interestCompoundingPeriodType = interestPeriodType;
|
||||||
@@ -202,6 +217,7 @@ public class SavingsAccountData {
|
|||||||
this.transactions = transactions;
|
this.transactions = transactions;
|
||||||
|
|
||||||
this.productOptions = productOptions;
|
this.productOptions = productOptions;
|
||||||
|
this.fieldOfficerOptions = fieldOfficerOptions;
|
||||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
||||||
this.interestPostingPeriodTypeOptions = interestPostingPeriodTypeOptions;
|
this.interestPostingPeriodTypeOptions = interestPostingPeriodTypeOptions;
|
||||||
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
|
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
|
||||||
|
|||||||
+63
-58
@@ -5,25 +5,24 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.data;
|
package org.mifosplatform.portfolio.savings.data;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountNoParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.externalIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.clientIdParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.groupIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.externalIdParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.groupIdParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.productIdParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -39,7 +38,7 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.mifosplatform.portfolio.savings.api.SavingsApiConstants;
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -56,7 +55,7 @@ public class SavingsAccountDataValidator {
|
|||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateForCreate(final String json) {
|
public void validateForSubmit(final String json) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
@@ -85,13 +84,9 @@ public class SavingsAccountDataValidator {
|
|||||||
final Long productId = fromApiJsonHelper.extractLongNamed(productIdParamName, element);
|
final Long productId = fromApiJsonHelper.extractLongNamed(productIdParamName, element);
|
||||||
baseDataValidator.reset().parameter(productIdParamName).value(productId).notNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(productIdParamName).value(productId).notNull().integerGreaterThanZero();
|
||||||
|
|
||||||
final Boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element);
|
final LocalDate submittedOnDate = fromApiJsonHelper.extractLocalDateNamed(submittedOnDateParamName, element);
|
||||||
baseDataValidator.reset().parameter(activeParamName).value(active).notNull();
|
if (submittedOnDate == null) {
|
||||||
|
baseDataValidator.reset().parameter(submittedOnDateParamName).value(submittedOnDate).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)) {
|
if (fromApiJsonHelper.parameterExists(accountNoParamName, element)) {
|
||||||
@@ -140,32 +135,32 @@ public class SavingsAccountDataValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||||
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).positiveAmount();
|
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||||
|
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).integerZeroOrGreater();
|
||||||
.positiveAmount();
|
|
||||||
|
|
||||||
if (lockinPeriodFrequency != null) {
|
if (lockinPeriodFrequency != null) {
|
||||||
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||||
lockinPeriodFrequencyTypeParamName, element);
|
lockinPeriodFrequencyTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull()
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull()
|
||||||
.inMinMaxRange(1, 3);
|
.inMinMaxRange(0, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
||||||
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName,
|
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(1, 3);
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||||
|
|
||||||
if (lockinPeriodFrequencyType != null) {
|
if (lockinPeriodFrequencyType != null) {
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName,
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull().positiveAmount();
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull()
|
||||||
|
.integerZeroOrGreater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,17 +168,30 @@ public class SavingsAccountDataValidator {
|
|||||||
|
|
||||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).positiveAmount();
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).zeroOrPositiveAmount();
|
||||||
|
|
||||||
|
if (withdrawalFeeAmount != null) {
|
||||||
|
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||||
|
.isOneOfTheseValues(1, 2);
|
||||||
|
|
||||||
|
if (withdrawalFeeType != null) {
|
||||||
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||||
|
element);
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).positiveAmount();
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).zeroOrPositiveAmount();
|
||||||
|
|
||||||
if (annualFeeAmount != null) {
|
if (annualFeeAmount != null) {
|
||||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||||
@@ -191,6 +199,15 @@ public class SavingsAccountDataValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||||
|
|
||||||
|
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||||
|
if (monthDayOfAnnualFee != null) {
|
||||||
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().zeroOrPositiveAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,50 +310,38 @@ public class SavingsAccountDataValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||||
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).positiveAmount();
|
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).ignoreIfNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||||
|
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
||||||
.positiveAmount();
|
.integerZeroOrGreater();
|
||||||
|
|
||||||
if (lockinPeriodFrequency != null) {
|
|
||||||
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
|
||||||
lockinPeriodFrequencyTypeParamName, element);
|
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull()
|
|
||||||
.inMinMaxRange(1, 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
||||||
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName,
|
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(1, 3);
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||||
|
|
||||||
if (lockinPeriodFrequencyType != null) {
|
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName,
|
|
||||||
element);
|
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull().positiveAmount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||||
|
|
||||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull().positiveAmount();
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||||
|
.isOneOfTheseValues(1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().positiveAmount();
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||||
|
|||||||
+14
-5
@@ -16,22 +16,31 @@ public class SavingsAccountStatusEnumData {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final String value;
|
private final String value;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final boolean unactivated;
|
private final boolean submittedAndPendingApproval;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean approved;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean rejected;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final boolean withdrawnByApplicant;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final boolean active;
|
private final boolean active;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final boolean closed;
|
private final boolean closed;
|
||||||
|
|
||||||
public SavingsAccountStatusEnumData(final Long id, final String code, final String value, final boolean unactivated,
|
public SavingsAccountStatusEnumData(final Long id, final String code, final String value, final boolean submittedAndPendingApproval,
|
||||||
final boolean active, final boolean closed) {
|
final boolean approved, final boolean rejected, final boolean withdrawnByApplicant, final boolean active, final boolean closed) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.unactivated = unactivated;
|
this.submittedAndPendingApproval = submittedAndPendingApproval;
|
||||||
|
this.approved = approved;
|
||||||
|
this.rejected = rejected;
|
||||||
|
this.withdrawnByApplicant = withdrawnByApplicant;
|
||||||
this.active = active;
|
this.active = active;
|
||||||
this.closed = closed;
|
this.closed = closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long id() {
|
public Long id() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -5,15 +5,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.data;
|
package org.mifosplatform.portfolio.savings.data;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountNumberParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.activationDateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.bankNumberParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.bankNumberParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.checkNumberParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.checkNumberParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.paymentTypeIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.paymentTypeIdParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.receiptNumberParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.receiptNumberParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.routingCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.routingCodeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.transactionAccountNumberParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.transactionAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.transactionAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.transactionDateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.transactionDateParamName;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -32,7 +32,7 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.mifosplatform.portfolio.savings.api.SavingsApiConstants;
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class SavingsAccountTransactionDataValidator {
|
|||||||
// Validate all string payment detail fields for max length
|
// Validate all string payment detail fields for max length
|
||||||
final Integer paymentTypeId = fromApiJsonHelper.extractIntegerWithLocaleNamed(paymentTypeIdParamName, element);
|
final Integer paymentTypeId = fromApiJsonHelper.extractIntegerWithLocaleNamed(paymentTypeIdParamName, element);
|
||||||
baseDataValidator.reset().parameter(paymentTypeIdParamName).value(paymentTypeId).ignoreIfNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter(paymentTypeIdParamName).value(paymentTypeId).ignoreIfNull().integerGreaterThanZero();
|
||||||
final Set<String> paymentDetailParameters = new HashSet<String>(Arrays.asList(accountNumberParamName, checkNumberParamName,
|
final Set<String> paymentDetailParameters = new HashSet<String>(Arrays.asList(transactionAccountNumberParamName, checkNumberParamName,
|
||||||
routingCodeParamName, receiptNumberParamName, bankNumberParamName));
|
routingCodeParamName, receiptNumberParamName, bankNumberParamName));
|
||||||
for (String paymentDetailParameterName : paymentDetailParameters) {
|
for (String paymentDetailParameterName : paymentDetailParameters) {
|
||||||
final String paymentDetailParameterValue = fromApiJsonHelper.extractStringNamed(paymentDetailParameterName, element);
|
final String paymentDetailParameterValue = fromApiJsonHelper.extractStringNamed(paymentDetailParameterName, element);
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.data;
|
package org.mifosplatform.portfolio.savings.data;
|
||||||
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionType;
|
import org.mifosplatform.portfolio.savings.SavingsAccountTransactionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object represent savings account transaction type
|
* Immutable data object represent savings account transaction type
|
||||||
|
|||||||
+62
-34
@@ -5,24 +5,24 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.data;
|
package org.mifosplatform.portfolio.savings.data;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -40,6 +40,7 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ public class SavingsProductDataValidator {
|
|||||||
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||||
interestCompoundingPeriodTypeParamName, element);
|
interestCompoundingPeriodTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
|
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
|
||||||
.isOneOfTheseValues(new Object[] { 1, 2, 3, 4, 5, 6, 7, 8 });
|
.isOneOfTheseValues(SavingsCompoundingInterestPeriodType.integerValues());
|
||||||
|
|
||||||
final Integer interestPostingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPostingPeriodTypeParamName,
|
final Integer interestPostingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPostingPeriodTypeParamName,
|
||||||
element);
|
element);
|
||||||
@@ -109,14 +110,13 @@ public class SavingsProductDataValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||||
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).positiveAmount();
|
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||||
|
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).integerZeroOrGreater();
|
||||||
.positiveAmount();
|
|
||||||
|
|
||||||
if (lockinPeriodFrequency != null) {
|
if (lockinPeriodFrequency != null) {
|
||||||
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
final Integer lockinPeriodFrequencyType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||||
@@ -134,24 +134,39 @@ public class SavingsProductDataValidator {
|
|||||||
if (lockinPeriodFrequencyType != null) {
|
if (lockinPeriodFrequencyType != null) {
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName,
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull().positiveAmount();
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull()
|
||||||
|
.integerZeroOrGreater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||||
|
|
||||||
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||||
|
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).zeroOrPositiveAmount();
|
||||||
|
|
||||||
|
if (withdrawalFeeAmount != null) {
|
||||||
|
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||||
|
.isOneOfTheseValues(1, 2);
|
||||||
|
|
||||||
if (withdrawalFeeType != null) {
|
if (withdrawalFeeType != null) {
|
||||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||||
element);
|
element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull().positiveAmount();
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().positiveAmount();
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).zeroOrPositiveAmount();
|
||||||
|
|
||||||
if (annualFeeAmount != null) {
|
if (annualFeeAmount != null) {
|
||||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||||
@@ -159,6 +174,15 @@ public class SavingsProductDataValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||||
|
|
||||||
|
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||||
|
if (monthDayOfAnnualFee != null) {
|
||||||
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().zeroOrPositiveAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// accounting related data validation
|
// accounting related data validation
|
||||||
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||||
@@ -232,7 +256,7 @@ public class SavingsProductDataValidator {
|
|||||||
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||||
interestCompoundingPeriodTypeParamName, element);
|
interestCompoundingPeriodTypeParamName, element);
|
||||||
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
|
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
|
||||||
.inMinMaxRange(1, 8);
|
.isOneOfTheseValues(SavingsCompoundingInterestPeriodType.integerValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
|
||||||
@@ -249,11 +273,17 @@ public class SavingsProductDataValidator {
|
|||||||
.notNull().isOneOfTheseValues(360, 365);
|
.notNull().isOneOfTheseValues(360, 365);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||||
|
final BigDecimal minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName,
|
||||||
|
element);
|
||||||
|
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).ignoreIfNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull()
|
||||||
.positiveAmount();
|
.integerZeroOrGreater();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
||||||
@@ -265,7 +295,8 @@ public class SavingsProductDataValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull().positiveAmount();
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull()
|
||||||
|
.zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||||
@@ -276,7 +307,7 @@ public class SavingsProductDataValidator {
|
|||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().positiveAmount();
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().zeroOrPositiveAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||||
@@ -319,9 +350,6 @@ public class SavingsProductDataValidator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validation for advanced accounting options
|
* Validation for advanced accounting options
|
||||||
*
|
|
||||||
* @param baseDataValidator
|
|
||||||
* @param element
|
|
||||||
*/
|
*/
|
||||||
private void validatePaymentChannelFundSourceMappings(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
private void validatePaymentChannelFundSourceMappings(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||||
if (fromApiJsonHelper.parameterExists(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), element)) {
|
if (fromApiJsonHelper.parameterExists(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), element)) {
|
||||||
|
|||||||
-63
@@ -1,63 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.MathContext;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
|
||||||
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
|
||||||
|
|
||||||
public class InterestCompoundingPeriodSummary {
|
|
||||||
|
|
||||||
private final LocalDateInterval periodInterval;
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private final BigDecimal openingBalance;
|
|
||||||
private final BigDecimal closingBalance;
|
|
||||||
private final BigDecimal interestEarnedUnrounded;
|
|
||||||
private final BigDecimal cumulativeCompoundedInterestToDate;
|
|
||||||
|
|
||||||
public static InterestCompoundingPeriodSummary create(final LocalDateInterval periodInterval, final BigDecimal openingBalance,
|
|
||||||
final BigDecimal closingBalance, final BigDecimal interestEarnedUnrounded, final BigDecimal cumulativeCompoundedInterestToDate) {
|
|
||||||
return new InterestCompoundingPeriodSummary(periodInterval, openingBalance, closingBalance, interestEarnedUnrounded,
|
|
||||||
cumulativeCompoundedInterestToDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InterestCompoundingPeriodSummary(final LocalDateInterval periodInterval, final BigDecimal openingBalance,
|
|
||||||
final BigDecimal closingBalance, final BigDecimal interestEarnedUnrounded, final BigDecimal cumulativeCompoundedInterestToDate) {
|
|
||||||
this.periodInterval = periodInterval;
|
|
||||||
this.openingBalance = openingBalance;
|
|
||||||
this.closingBalance = closingBalance;
|
|
||||||
this.interestEarnedUnrounded = interestEarnedUnrounded;
|
|
||||||
this.cumulativeCompoundedInterestToDate = cumulativeCompoundedInterestToDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Money closingBalance(final MonetaryCurrency currency) {
|
|
||||||
return Money.of(currency, this.closingBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal closingBalance() {
|
|
||||||
return this.closingBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal closingBalanceWithUnroundedInterest(final MathContext mc) {
|
|
||||||
return this.closingBalance.add(interestEarnedUnrounded, mc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal compoundedInterest() {
|
|
||||||
return cumulativeCompoundedInterestToDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal interestUnrounded() {
|
|
||||||
return this.interestEarnedUnrounded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean fallsBefore(final LocalDate dateToCheck) {
|
|
||||||
return this.periodInterval.fallsBefore(dateToCheck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+629
-432
File diff suppressed because it is too large
Load Diff
+68
-50
@@ -5,36 +5,45 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings.domain;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountNoParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.externalIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.fieldOfficerIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.groupIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.joda.time.MonthDay;
|
import org.joda.time.MonthDay;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||||
|
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
|
||||||
import org.mifosplatform.portfolio.client.domain.Client;
|
import org.mifosplatform.portfolio.client.domain.Client;
|
||||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||||
import org.mifosplatform.portfolio.group.domain.Group;
|
import org.mifosplatform.portfolio.group.domain.Group;
|
||||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
import org.mifosplatform.portfolio.group.domain.GroupRepositoryWrapper;
|
||||||
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -46,18 +55,24 @@ public class SavingsAccountAssembler {
|
|||||||
|
|
||||||
private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper;
|
private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper;
|
||||||
private final ClientRepositoryWrapper clientRepository;
|
private final ClientRepositoryWrapper clientRepository;
|
||||||
private final GroupRepository groupRepository;
|
private final GroupRepositoryWrapper groupRepository;
|
||||||
|
private final StaffRepositoryWrapper staffRepository;
|
||||||
private final SavingsProductRepository savingProductRepository;
|
private final SavingsProductRepository savingProductRepository;
|
||||||
|
private final SavingsAccountRepositoryWrapper savingsAccountRepository;
|
||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
|
public SavingsAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
|
||||||
final ClientRepositoryWrapper clientRepository, final GroupRepository groupRepository,
|
final ClientRepositoryWrapper clientRepository, final GroupRepositoryWrapper groupRepository,
|
||||||
final SavingsProductRepository savingProductRepository, final FromJsonHelper fromApiJsonHelper) {
|
final StaffRepositoryWrapper staffRepository, final SavingsProductRepository savingProductRepository,
|
||||||
|
final SavingsAccountRepositoryWrapper savingsAccountRepository,
|
||||||
|
final FromJsonHelper fromApiJsonHelper) {
|
||||||
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
|
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
|
||||||
this.clientRepository = clientRepository;
|
this.clientRepository = clientRepository;
|
||||||
this.groupRepository = groupRepository;
|
this.groupRepository = groupRepository;
|
||||||
|
this.staffRepository = staffRepository;
|
||||||
this.savingProductRepository = savingProductRepository;
|
this.savingProductRepository = savingProductRepository;
|
||||||
|
this.savingsAccountRepository = savingsAccountRepository;
|
||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,36 +80,39 @@ public class SavingsAccountAssembler {
|
|||||||
* Assembles a new {@link SavingsAccount} from JSON details passed in
|
* Assembles a new {@link SavingsAccount} from JSON details passed in
|
||||||
* request inheriting details where relevant from chosen
|
* request inheriting details where relevant from chosen
|
||||||
* {@link SavingsProduct}.
|
* {@link SavingsProduct}.
|
||||||
*
|
|
||||||
* @param existingReversedTransactionIds
|
|
||||||
* @param existingTransactionIds
|
|
||||||
*/
|
*/
|
||||||
public SavingsAccount assembleFrom(final JsonCommand command, List<Long> existingTransactionIds,
|
public SavingsAccount assembleFrom(final JsonCommand command) {
|
||||||
List<Long> existingReversedTransactionIds) {
|
|
||||||
|
|
||||||
final JsonElement element = command.parsedJson();
|
final JsonElement element = command.parsedJson();
|
||||||
|
|
||||||
final String accountNo = fromApiJsonHelper.extractStringNamed("accountNo", element);
|
final String accountNo = fromApiJsonHelper.extractStringNamed(accountNoParamName, element);
|
||||||
final String externalId = fromApiJsonHelper.extractStringNamed("externalId", element);
|
final String externalId = fromApiJsonHelper.extractStringNamed(externalIdParamName, element);
|
||||||
final Long productId = fromApiJsonHelper.extractLongNamed("productId", element);
|
final Long productId = fromApiJsonHelper.extractLongNamed(productIdParamName, element);
|
||||||
|
|
||||||
final SavingsProduct product = this.savingProductRepository.findOne(productId);
|
final SavingsProduct product = this.savingProductRepository.findOne(productId);
|
||||||
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
||||||
|
|
||||||
final Long clientId = fromApiJsonHelper.extractLongNamed("clientId", element);
|
|
||||||
final Long groupId = fromApiJsonHelper.extractLongNamed("groupId", element);
|
|
||||||
|
|
||||||
Client client = null;
|
Client client = null;
|
||||||
Group group = null;
|
Group group = null;
|
||||||
|
Staff fieldOfficer = null;
|
||||||
|
|
||||||
|
final Long clientId = fromApiJsonHelper.extractLongNamed(clientIdParamName, element);
|
||||||
if (clientId != null) {
|
if (clientId != null) {
|
||||||
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Long groupId = fromApiJsonHelper.extractLongNamed(groupIdParamName, element);
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
group = this.groupRepository.findOne(groupId);
|
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
|
||||||
if (group == null) { throw new GroupNotFoundException(groupId); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Long fieldOfficerId = fromApiJsonHelper.extractLongNamed(fieldOfficerIdParamName, element);
|
||||||
|
if (fieldOfficerId != null) {
|
||||||
|
fieldOfficer = this.staffRepository.findOneWithNotFoundDetection(fieldOfficerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final LocalDate submittedOnDate = fromApiJsonHelper.extractLocalDateNamed(submittedOnDateParamName, element);
|
||||||
|
|
||||||
BigDecimal interestRate = null;
|
BigDecimal interestRate = null;
|
||||||
if (command.parameterExists(nominalAnnualInterestRateParamName)) {
|
if (command.parameterExists(nominalAnnualInterestRateParamName)) {
|
||||||
interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
|
interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
|
||||||
@@ -102,9 +120,6 @@ public class SavingsAccountAssembler {
|
|||||||
interestRate = product.nominalAnnualInterestRate();
|
interestRate = product.nominalAnnualInterestRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean active = fromApiJsonHelper.extractBooleanNamed(activeParamName, element);
|
|
||||||
final LocalDate activationDate = fromApiJsonHelper.extractLocalDateNamed(activationDateParamName, element);
|
|
||||||
|
|
||||||
SavingsCompoundingInterestPeriodType interestCompoundingPeriodType = null;
|
SavingsCompoundingInterestPeriodType interestCompoundingPeriodType = null;
|
||||||
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
||||||
if (interestPeriodTypeValue != null) {
|
if (interestPeriodTypeValue != null) {
|
||||||
@@ -113,10 +128,10 @@ public class SavingsAccountAssembler {
|
|||||||
interestCompoundingPeriodType = product.interestCompoundingPeriodType();
|
interestCompoundingPeriodType = product.interestCompoundingPeriodType();
|
||||||
}
|
}
|
||||||
|
|
||||||
SavingsInterestPostingPeriodType interestPostingPeriodType = null;
|
SavingsPostingInterestPeriodType interestPostingPeriodType = null;
|
||||||
final Integer interestPostingPeriodTypeValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
final Integer interestPostingPeriodTypeValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
||||||
if (interestPostingPeriodTypeValue != null) {
|
if (interestPostingPeriodTypeValue != null) {
|
||||||
interestPostingPeriodType = SavingsInterestPostingPeriodType.fromInt(interestPostingPeriodTypeValue);
|
interestPostingPeriodType = SavingsPostingInterestPeriodType.fromInt(interestPostingPeriodTypeValue);
|
||||||
} else {
|
} else {
|
||||||
interestPostingPeriodType = product.interestPostingPeriodType();
|
interestPostingPeriodType = product.interestPostingPeriodType();
|
||||||
}
|
}
|
||||||
@@ -194,17 +209,20 @@ public class SavingsAccountAssembler {
|
|||||||
monthDayOfAnnualFee = product.monthDayOfAnnualFee();
|
monthDayOfAnnualFee = product.monthDayOfAnnualFee();
|
||||||
}
|
}
|
||||||
|
|
||||||
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
|
final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo, externalId,
|
||||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
submittedOnDate, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
|
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||||
annualFeeAmount, monthDayOfAnnualFee);
|
withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, monthDayOfAnnualFee);
|
||||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
||||||
|
|
||||||
if (active) {
|
account.validateNewApplicationState(DateUtils.getLocalDateOfTenant());
|
||||||
final Locale locale = command.extractLocale();
|
|
||||||
final DateTimeFormatter formatter = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
return account;
|
||||||
account.activate(formatter, activationDate, existingTransactionIds, existingReversedTransactionIds);
|
}
|
||||||
}
|
|
||||||
|
public SavingsAccount assembleFrom(final Long savingsId) {
|
||||||
|
SavingsAccount account = this.savingsAccountRepository.findOneWithNotFoundDetection(savingsId);
|
||||||
|
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|||||||
-65
@@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.MathContext;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
|
||||||
|
|
||||||
public class SavingsAccountDailyBalance {
|
|
||||||
|
|
||||||
private final LocalDateInterval interestPeriodInterval;
|
|
||||||
private final BigDecimal endOfDayBalance;
|
|
||||||
private final BigDecimal cumulativeBalance;
|
|
||||||
private final BigDecimal compoundedInterestToDate;
|
|
||||||
|
|
||||||
public static SavingsAccountDailyBalance createFrom(final LocalDateInterval interestPeriodInterval, final BigDecimal endOfDayBalance,
|
|
||||||
final BigDecimal compoundedInterestToDate) {
|
|
||||||
return new SavingsAccountDailyBalance(interestPeriodInterval, endOfDayBalance, compoundedInterestToDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SavingsAccountDailyBalance(final LocalDateInterval interestPeriodInterval, final BigDecimal endOfDayBalance,
|
|
||||||
final BigDecimal compoundedInterestToDate) {
|
|
||||||
this.interestPeriodInterval = interestPeriodInterval;
|
|
||||||
this.endOfDayBalance = endOfDayBalance;
|
|
||||||
this.compoundedInterestToDate = compoundedInterestToDate;
|
|
||||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
|
||||||
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(interestPeriodInterval.daysInPeriodInclusiveOfEndDate());
|
|
||||||
this.cumulativeBalance = endOfDayBalance.multiply(numberOfDaysBigDecimal, mc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Money dailyRunningBalance(final MonetaryCurrency currency) {
|
|
||||||
return Money.of(currency, endOfDayBalance);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal endOfDayBalance() {
|
|
||||||
return this.endOfDayBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal cumulativeBalance() {
|
|
||||||
return this.cumulativeBalance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer numberOfDays() {
|
|
||||||
return interestPeriodInterval.daysInPeriodInclusiveOfEndDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGreaterThanZero() {
|
|
||||||
return this.endOfDayBalance.compareTo(BigDecimal.ZERO) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal interestUsingDailyBalanceMethod(final BigDecimal dailyInterestRate, final Integer numberOfDays) {
|
|
||||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
|
||||||
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(numberOfDays.longValue());
|
|
||||||
|
|
||||||
final BigDecimal compoundedEndOfDayBalance = this.endOfDayBalance.add(this.compoundedInterestToDate, mc);
|
|
||||||
return compoundedEndOfDayBalance.multiply(dailyInterestRate, mc).multiply(numberOfDaysBigDecimal, mc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+28
-4
@@ -11,8 +11,11 @@ package org.mifosplatform.portfolio.savings.domain;
|
|||||||
public enum SavingsAccountStatusType {
|
public enum SavingsAccountStatusType {
|
||||||
|
|
||||||
INVALID(0, "savingsAccountStatusType.invalid"), //
|
INVALID(0, "savingsAccountStatusType.invalid"), //
|
||||||
UNACTIVATED(100, "savingsAccountStatusType.unactivated"), //
|
SUBMITTED_AND_PENDING_APPROVAL(100, "savingsAccountStatusType.submitted.and.pending.approval"), //
|
||||||
|
APPROVED(200, "savingsAccountStatusType.approved"), //
|
||||||
ACTIVE(300, "savingsAccountStatusType.active"), //
|
ACTIVE(300, "savingsAccountStatusType.active"), //
|
||||||
|
WITHDRAWN_BY_APPLICANT(400, "savingsAccountStatusType.withdrawn.by.applicant"), //
|
||||||
|
REJECTED(500, "savingsAccountStatusType.rejected"), //
|
||||||
CLOSED(600, "savingsAccountStatusType.closed");
|
CLOSED(600, "savingsAccountStatusType.closed");
|
||||||
|
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
@@ -23,11 +26,20 @@ public enum SavingsAccountStatusType {
|
|||||||
SavingsAccountStatusType enumeration = SavingsAccountStatusType.INVALID;
|
SavingsAccountStatusType enumeration = SavingsAccountStatusType.INVALID;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 100:
|
case 100:
|
||||||
enumeration = SavingsAccountStatusType.UNACTIVATED;
|
enumeration = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL;
|
||||||
|
break;
|
||||||
|
case 200:
|
||||||
|
enumeration = SavingsAccountStatusType.APPROVED;
|
||||||
break;
|
break;
|
||||||
case 300:
|
case 300:
|
||||||
enumeration = SavingsAccountStatusType.ACTIVE;
|
enumeration = SavingsAccountStatusType.ACTIVE;
|
||||||
break;
|
break;
|
||||||
|
case 400:
|
||||||
|
enumeration = SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT;
|
||||||
|
break;
|
||||||
|
case 500:
|
||||||
|
enumeration = SavingsAccountStatusType.REJECTED;
|
||||||
|
break;
|
||||||
case 600:
|
case 600:
|
||||||
enumeration = SavingsAccountStatusType.CLOSED;
|
enumeration = SavingsAccountStatusType.CLOSED;
|
||||||
break;
|
break;
|
||||||
@@ -52,8 +64,20 @@ public enum SavingsAccountStatusType {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnactivated() {
|
public boolean isSubmittedAndPendingApproval() {
|
||||||
return this.value.equals(SavingsAccountStatusType.UNACTIVATED.getValue());
|
return this.value.equals(SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApproved() {
|
||||||
|
return this.value.equals(SavingsAccountStatusType.APPROVED.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRejected() {
|
||||||
|
return this.value.equals(SavingsAccountStatusType.REJECTED.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isApplicationWithdrawnByApplicant() {
|
||||||
|
return this.value.equals(SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
|
|||||||
+6
-9
@@ -13,6 +13,7 @@ import javax.persistence.Embeddable;
|
|||||||
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link SavingsAccountSummary} encapsulates all the summary details of a
|
* {@link SavingsAccountSummary} encapsulates all the summary details of a
|
||||||
@@ -60,19 +61,15 @@ public final class SavingsAccountSummary {
|
|||||||
.minus(this.totalWithdrawalFees).minus(this.totalAnnualFees).getAmount();
|
.minus(this.totalWithdrawalFees).minus(this.totalAnnualFees).getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
|
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency, final List<PostingPeriod> allPostingPeriods) {
|
||||||
final List<InterestCompoundingPeriodSummary> compoundingPeriods) {
|
|
||||||
|
|
||||||
// get the max compounded interest
|
Money totalEarned = Money.zero(currency);
|
||||||
final BigDecimal compoundedInterestToDate = compoundingPeriods.get(compoundingPeriods.size() - 1).compoundedInterest();
|
|
||||||
final Money maxIntrestCompoundedToDate = Money.of(currency, compoundedInterestToDate);
|
|
||||||
|
|
||||||
BigDecimal totalInterestUnrounded = BigDecimal.ZERO;
|
for (PostingPeriod period : allPostingPeriods) {
|
||||||
for (InterestCompoundingPeriodSummary interestPeriodSummary : compoundingPeriods) {
|
totalEarned = totalEarned.plus(period.interest());
|
||||||
totalInterestUnrounded = totalInterestUnrounded.add(interestPeriodSummary.interestUnrounded());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.totalInterestEarned = maxIntrestCompoundedToDate.getAmountDefaultedToNullIfZero();
|
this.totalInterestEarned = totalEarned.getAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLessThanOrEqualToAccountBalance(final Money amount) {
|
public boolean isLessThanOrEqualToAccountBalance(final Money amount) {
|
||||||
|
|||||||
+97
-21
@@ -24,7 +24,9 @@ import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
|||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsAccountTransactionType;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.interest.EndOfDayBalance;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
@@ -205,27 +207,6 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
return this.balanceNumberOfDays != null && this.balanceNumberOfDays > 0;
|
return this.balanceNumberOfDays != null && this.balanceNumberOfDays > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavingsAccountDailyBalance toDailyBalance(final LocalDate periodEnd) {
|
|
||||||
|
|
||||||
LocalDate balanceValidTo = getEndOfBalanceLocalDate();
|
|
||||||
if (periodEnd.isBefore(getEndOfBalanceLocalDate())) {
|
|
||||||
balanceValidTo = periodEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalDateInterval interestPeriodInterval = LocalDateInterval.create(getTransactionLocalDate(), balanceValidTo);
|
|
||||||
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance, BigDecimal.ZERO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SavingsAccountDailyBalance toCompoundedDailyBalance(final LocalDate periodEnd, final BigDecimal compoundedInterestToDate) {
|
|
||||||
LocalDate balanceValidTo = getEndOfBalanceLocalDate();
|
|
||||||
if (periodEnd.isBefore(getEndOfBalanceLocalDate())) {
|
|
||||||
balanceValidTo = periodEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
final LocalDateInterval interestPeriodInterval = LocalDateInterval.create(getTransactionLocalDate(), balanceValidTo);
|
|
||||||
return SavingsAccountDailyBalance.createFrom(interestPeriodInterval, this.runningBalance, compoundedInterestToDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNotAmount(final Money amountToCheck) {
|
public boolean hasNotAmount(final Money amountToCheck) {
|
||||||
final Money transactionAmount = getAmount(amountToCheck.getCurrency());
|
final Money transactionAmount = getAmount(amountToCheck.getCurrency());
|
||||||
return transactionAmount.isNotEqualTo(amountToCheck);
|
return transactionAmount.isNotEqualTo(amountToCheck);
|
||||||
@@ -249,4 +230,99 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
return thisTransactionData;
|
return thisTransactionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAfter(final LocalDate transactionDate) {
|
||||||
|
return this.getTransactionLocalDate().isAfter(transactionDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance toEndOfDayBalance(final LocalDateInterval periodInterval, final MonetaryCurrency currency) {
|
||||||
|
|
||||||
|
Money endOfDayBalance = Money.of(currency, this.runningBalance);
|
||||||
|
Money openingBalance = endOfDayBalance;
|
||||||
|
|
||||||
|
LocalDate balanceDate = periodInterval.startDate();
|
||||||
|
|
||||||
|
int numberOfDays = periodInterval.daysInPeriodInclusiveOfEndDate();
|
||||||
|
if (periodInterval.contains(getTransactionLocalDate())) {
|
||||||
|
balanceDate = getTransactionLocalDate();
|
||||||
|
LocalDateInterval newInterval = LocalDateInterval.create(getTransactionLocalDate(), periodInterval.endDate());
|
||||||
|
numberOfDays = newInterval.daysInPeriodInclusiveOfEndDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EndOfDayBalance.from(balanceDate, openingBalance, endOfDayBalance, numberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance toEndOfDayBalance(final Money openingBalance, final LocalDate nextTransactionDate) {
|
||||||
|
|
||||||
|
MonetaryCurrency currency = openingBalance.getCurrency();
|
||||||
|
Money endOfDayBalance = openingBalance.copy();
|
||||||
|
if (isDeposit()) {
|
||||||
|
endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||||
|
} else if (isWithdrawal() || isWithdrawalFee()) {
|
||||||
|
endOfDayBalance = openingBalance.minus(getAmount(currency));
|
||||||
|
}
|
||||||
|
|
||||||
|
int numberOfDays = LocalDateInterval.create(getTransactionLocalDate(), nextTransactionDate).daysInPeriodInclusiveOfEndDate();
|
||||||
|
if (!openingBalance.isEqualTo(endOfDayBalance) && numberOfDays > 1) {
|
||||||
|
numberOfDays = numberOfDays - 1;
|
||||||
|
}
|
||||||
|
return EndOfDayBalance.from(getTransactionLocalDate(), openingBalance, endOfDayBalance, numberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance toEndOfDayBalance(final Money openingBalance) {
|
||||||
|
MonetaryCurrency currency = openingBalance.getCurrency();
|
||||||
|
Money endOfDayBalance = openingBalance.copy();
|
||||||
|
if (isDeposit()) {
|
||||||
|
endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||||
|
} else if (isWithdrawal() || isWithdrawalFee()) {
|
||||||
|
endOfDayBalance = openingBalance.minus(getAmount(currency));
|
||||||
|
}
|
||||||
|
|
||||||
|
return EndOfDayBalance.from(getTransactionLocalDate(), openingBalance, endOfDayBalance, this.balanceNumberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance toEndOfDayBalanceBoundedBy(final Money openingBalance, final LocalDateInterval boundedBy) {
|
||||||
|
|
||||||
|
MonetaryCurrency currency = openingBalance.getCurrency();
|
||||||
|
Money endOfDayBalance = openingBalance.copy();
|
||||||
|
|
||||||
|
int numberOfDaysOfBalance = this.balanceNumberOfDays;
|
||||||
|
|
||||||
|
LocalDate balanceStartDate = getTransactionLocalDate();
|
||||||
|
LocalDate balanceEndDate = getEndOfBalanceLocalDate();
|
||||||
|
|
||||||
|
if (boundedBy.startDate().isAfter(balanceStartDate)) {
|
||||||
|
balanceStartDate = boundedBy.startDate();
|
||||||
|
LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate);
|
||||||
|
numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate();
|
||||||
|
} else {
|
||||||
|
if (isDeposit()) {
|
||||||
|
endOfDayBalance = openingBalance.plus(getAmount(currency));
|
||||||
|
} else if (isWithdrawal() || isWithdrawalFee()) {
|
||||||
|
endOfDayBalance = openingBalance.minus(getAmount(currency));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (balanceEndDate.isAfter(boundedBy.endDate())) {
|
||||||
|
balanceEndDate = boundedBy.endDate();
|
||||||
|
LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate);
|
||||||
|
numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EndOfDayBalance.from(balanceStartDate, openingBalance, endOfDayBalance, numberOfDaysOfBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBalanceInExistencesForOneDayOrMore() {
|
||||||
|
return this.balanceNumberOfDays != null && this.balanceNumberOfDays.intValue() >= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean fallsWithin(final LocalDateInterval periodInterval) {
|
||||||
|
LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionLocalDate(), getEndOfBalanceLocalDate());
|
||||||
|
return periodInterval.contains(balanceInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean spansAnyPortionOf(final LocalDateInterval periodInterval) {
|
||||||
|
LocalDateInterval balanceInterval = LocalDateInterval.create(getTransactionLocalDate(), getEndOfBalanceLocalDate());
|
||||||
|
return balanceInterval.containsPortionOf(periodInterval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface SavingsCompoundInterestCalculator {
|
|
||||||
|
|
||||||
BigDecimal calculate(List<SavingsAccountDailyBalance> dailyBalances, Integer numberOfDays);
|
|
||||||
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.MathContext;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates interest on a savings account using the <b>Average Balance</b>
|
|
||||||
* method.
|
|
||||||
*/
|
|
||||||
public class SavingsCompoundInterestCalculatorForAverageBalance implements SavingsCompoundInterestCalculator {
|
|
||||||
|
|
||||||
private final BigDecimal periodsInOneYearAsFraction;
|
|
||||||
private final BigDecimal annualInterestRateAsFraction;
|
|
||||||
|
|
||||||
public SavingsCompoundInterestCalculatorForAverageBalance(final BigDecimal periodsInOneYearAsFraction,
|
|
||||||
final BigDecimal annualInterestRateAsFraction) {
|
|
||||||
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
|
|
||||||
this.annualInterestRateAsFraction = annualInterestRateAsFraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal calculate(final List<SavingsAccountDailyBalance> dailyBalances, final Integer numberOfDays) {
|
|
||||||
|
|
||||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
|
||||||
final BigDecimal dailyInterestRate = annualInterestRateAsFraction.multiply(periodsInOneYearAsFraction, mc);
|
|
||||||
final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays.longValue()));
|
|
||||||
|
|
||||||
final BigDecimal numberOfDaysBigDecimal = BigDecimal.valueOf(numberOfDays.longValue());
|
|
||||||
|
|
||||||
BigDecimal totalCumulativeBalanceForPeriod = BigDecimal.ZERO;
|
|
||||||
for (SavingsAccountDailyBalance balance : dailyBalances) {
|
|
||||||
if (balance.isGreaterThanZero()) {
|
|
||||||
final BigDecimal cumulativeBalance = balance.cumulativeBalance();
|
|
||||||
totalCumulativeBalanceForPeriod = totalCumulativeBalanceForPeriod.add(cumulativeBalance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final BigDecimal averageDailyBalance = totalCumulativeBalanceForPeriod.divide(numberOfDaysBigDecimal, mc);
|
|
||||||
|
|
||||||
return averageDailyBalance.multiply(periodicInterestRate, mc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.math.MathContext;
|
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates interest on a savings account using the <b>Daily Balance</b>
|
|
||||||
* method.
|
|
||||||
*/
|
|
||||||
public class SavingsCompoundInterestCalculatorForDailyBalance implements SavingsCompoundInterestCalculator {
|
|
||||||
|
|
||||||
private final BigDecimal periodsInOneYearAsFraction;
|
|
||||||
private final BigDecimal annualInterestRateAsFraction;
|
|
||||||
|
|
||||||
public SavingsCompoundInterestCalculatorForDailyBalance(final BigDecimal periodsInOneYearAsFraction,
|
|
||||||
final BigDecimal annualInterestRateAsFraction) {
|
|
||||||
this.periodsInOneYearAsFraction = periodsInOneYearAsFraction;
|
|
||||||
this.annualInterestRateAsFraction = annualInterestRateAsFraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public BigDecimal calculate(final List<SavingsAccountDailyBalance> dailyBalances, final Integer numberOfDays) {
|
|
||||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
|
||||||
final BigDecimal dailyInterestRate = annualInterestRateAsFraction.multiply(periodsInOneYearAsFraction, mc);
|
|
||||||
|
|
||||||
BigDecimal interestCalculated = BigDecimal.ZERO;
|
|
||||||
|
|
||||||
for (SavingsAccountDailyBalance balance : dailyBalances) {
|
|
||||||
if (balance.isGreaterThanZero()) {
|
|
||||||
final BigDecimal interestForBalance = balance.interestUsingDailyBalanceMethod(dailyInterestRate, balance.numberOfDays());
|
|
||||||
interestCalculated = interestCalculated.add(interestForBalance, mc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return interestCalculated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.interest.CompoundInterestHelper;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
|
||||||
|
|
||||||
|
public final class SavingsHelper {
|
||||||
|
|
||||||
|
private final CompoundInterestHelper compoundInterestHelper = new CompoundInterestHelper();
|
||||||
|
|
||||||
|
public List<LocalDateInterval> determineInterestPostingPeriods(final LocalDate activationLocalDate,
|
||||||
|
final LocalDate interestPostingUpToDate, final SavingsPostingInterestPeriodType postingPeriodType) {
|
||||||
|
|
||||||
|
List<LocalDateInterval> postingPeriods = new ArrayList<LocalDateInterval>();
|
||||||
|
|
||||||
|
LocalDate periodStartDate = activationLocalDate;
|
||||||
|
LocalDate periodEndDate = periodStartDate;
|
||||||
|
|
||||||
|
while (!periodStartDate.isAfter(interestPostingUpToDate) && !periodEndDate.isAfter(interestPostingUpToDate)) {
|
||||||
|
|
||||||
|
final LocalDate interestPostingLocalDate = determineInterestPostingPeriodEndDateFrom(periodStartDate, postingPeriodType);
|
||||||
|
periodEndDate = interestPostingLocalDate.minusDays(1);
|
||||||
|
|
||||||
|
if (!interestPostingLocalDate.isAfter(DateUtils.getLocalDateOfTenant())) {
|
||||||
|
postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
|
||||||
|
} else {
|
||||||
|
postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
periodEndDate = interestPostingLocalDate;
|
||||||
|
periodStartDate = interestPostingLocalDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return postingPeriods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalDate determineInterestPostingPeriodEndDateFrom(final LocalDate periodStartDate,
|
||||||
|
final SavingsPostingInterestPeriodType interestPostingPeriodType) {
|
||||||
|
|
||||||
|
LocalDate periodEndDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
|
||||||
|
switch (interestPostingPeriodType) {
|
||||||
|
case INVALID:
|
||||||
|
break;
|
||||||
|
case MONTHLY:
|
||||||
|
// produce period end date on last day of current month
|
||||||
|
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||||
|
break;
|
||||||
|
case QUATERLY:
|
||||||
|
// jan 1st to mar 31st, 1st apr to jun 30, jul 1st to sept 30,
|
||||||
|
// oct 1st to dec 31
|
||||||
|
int year = periodStartDate.getYearOfEra();
|
||||||
|
int monthofYear = periodStartDate.getMonthOfYear();
|
||||||
|
if (monthofYear <= 3) {
|
||||||
|
periodEndDate = new DateTime().withDate(year, 3, 31).toLocalDate();
|
||||||
|
} else if (monthofYear <= 6) {
|
||||||
|
periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
|
||||||
|
} else if (monthofYear <= 9) {
|
||||||
|
periodEndDate = new DateTime().withDate(year, 9, 30).toLocalDate();
|
||||||
|
} else if (monthofYear <= 12) {
|
||||||
|
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANNUAL:
|
||||||
|
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||||
|
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interest posting always occurs on next day after the period end date.
|
||||||
|
periodEndDate = periodEndDate.plusDays(1);
|
||||||
|
|
||||||
|
return periodEndDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money calculateInterestForAllPostingPeriods(final MonetaryCurrency currency, final List<PostingPeriod> allPeriods) {
|
||||||
|
return this.compoundInterestHelper.calculateInterestForAllPostingPeriods(currency, allPeriods);
|
||||||
|
}
|
||||||
|
}
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
public class SavingsInterestCalculatorFactory {
|
|
||||||
|
|
||||||
public SavingsCompoundInterestCalculator createFrom(final SavingsInterestCalculationType interestCalculationType,
|
|
||||||
final BigDecimal periodsInOneYearAsFraction, final BigDecimal annualInterestRateAsFraction) {
|
|
||||||
|
|
||||||
SavingsCompoundInterestCalculator savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
|
|
||||||
annualInterestRateAsFraction);
|
|
||||||
switch (interestCalculationType) {
|
|
||||||
case AVERAGE_DAILY_BALANCE:
|
|
||||||
savingsInterestCalculator = new SavingsCompoundInterestCalculatorForAverageBalance(periodsInOneYearAsFraction,
|
|
||||||
annualInterestRateAsFraction);
|
|
||||||
break;
|
|
||||||
case DAILY_BALANCE:
|
|
||||||
savingsInterestCalculator = new SavingsCompoundInterestCalculatorForDailyBalance(periodsInOneYearAsFraction,
|
|
||||||
annualInterestRateAsFraction);
|
|
||||||
break;
|
|
||||||
case INVALID:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return savingsInterestCalculator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-56
@@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interest posting period is the span of time at the end of which savings
|
|
||||||
* earned but not yet credited/posted in a client's account is credited/posted.
|
|
||||||
*/
|
|
||||||
public enum SavingsInterestPostingPeriodType {
|
|
||||||
|
|
||||||
INVALID(0, "savingsInterestPostingPeriodType.invalid"), //
|
|
||||||
MONTHLY(4, "savingsInterestPostingPeriodType.monthly"), //
|
|
||||||
QUATERLY(5, "savingsInterestPostingPeriodType.quarterly"), //
|
|
||||||
BI_ANNUAL(6, "savingsInterestPostingPeriodType.biannual"), //
|
|
||||||
ANNUAL(7, "savingsInterestPostingPeriodType.annual");
|
|
||||||
|
|
||||||
private final Integer value;
|
|
||||||
private final String code;
|
|
||||||
|
|
||||||
private SavingsInterestPostingPeriodType(final Integer value, final String code) {
|
|
||||||
this.value = value;
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SavingsInterestPostingPeriodType fromInt(final Integer type) {
|
|
||||||
SavingsInterestPostingPeriodType repaymentFrequencyType = SavingsInterestPostingPeriodType.INVALID;
|
|
||||||
if (type != null) {
|
|
||||||
switch (type) {
|
|
||||||
case 4:
|
|
||||||
repaymentFrequencyType = SavingsInterestPostingPeriodType.MONTHLY;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
repaymentFrequencyType = SavingsInterestPostingPeriodType.QUATERLY;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
repaymentFrequencyType = SavingsInterestPostingPeriodType.BI_ANNUAL;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
repaymentFrequencyType = SavingsInterestPostingPeriodType.ANNUAL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return repaymentFrequencyType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+129
-71
@@ -5,27 +5,30 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings.domain;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.localeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountingRuleParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
@@ -36,9 +39,17 @@ import javax.persistence.Table;
|
|||||||
import org.joda.time.MonthDay;
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@@ -68,7 +79,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
private Integer interestCompoundingPeriodType;
|
private Integer interestCompoundingPeriodType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value from the {@link SavingsInterestPostingPeriodType} enumeration.
|
* A value from the {@link SavingsPostingInterestPeriodType} enumeration.
|
||||||
*/
|
*/
|
||||||
@Column(name = "interest_posting_period_enum", nullable = false)
|
@Column(name = "interest_posting_period_enum", nullable = false)
|
||||||
private Integer interestPostingPeriodType;
|
private Integer interestPostingPeriodType;
|
||||||
@@ -118,7 +129,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
|
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
|
||||||
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
@@ -136,7 +147,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
private SavingsProduct(final String name, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
|
private SavingsProduct(final String name, final String description, final MonetaryCurrency currency, final BigDecimal interestRate,
|
||||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
@@ -157,16 +168,16 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||||
if (lockinPeriodFrequencyType != null) {
|
if (lockinPeriodFrequency != null && lockinPeriodFrequencyType != null) {
|
||||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||||
if (withdrawalFeeType != null) {
|
if (withdrawalFeeAmount != null && withdrawalFeeType != null) {
|
||||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||||
}
|
}
|
||||||
this.annualFeeAmount = annualFeeAmount;
|
this.annualFeeAmount = annualFeeAmount;
|
||||||
if (annualFeeOnMonthDay != null) {
|
if (annualFeeAmount != null && annualFeeOnMonthDay != null) {
|
||||||
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||||
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||||
}
|
}
|
||||||
@@ -192,8 +203,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
return SavingsCompoundingInterestPeriodType.fromInt(this.interestCompoundingPeriodType);
|
return SavingsCompoundingInterestPeriodType.fromInt(this.interestCompoundingPeriodType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavingsInterestPostingPeriodType interestPostingPeriodType() {
|
public SavingsPostingInterestPeriodType interestPostingPeriodType() {
|
||||||
return SavingsInterestPostingPeriodType.fromInt(this.interestPostingPeriodType);
|
return SavingsPostingInterestPeriodType.fromInt(this.interestPostingPeriodType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavingsInterestCalculationType interestCalculationType() {
|
public SavingsInterestCalculationType interestCalculationType() {
|
||||||
@@ -295,7 +306,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
if (command.isChangeInIntegerParameterNamed(interestPostingPeriodTypeParamName, this.interestPostingPeriodType)) {
|
if (command.isChangeInIntegerParameterNamed(interestPostingPeriodTypeParamName, this.interestPostingPeriodType)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
||||||
actualChanges.put(interestPostingPeriodTypeParamName, newValue);
|
actualChanges.put(interestPostingPeriodTypeParamName, newValue);
|
||||||
this.interestPostingPeriodType = SavingsInterestPostingPeriodType.fromInt(newValue).getValue();
|
this.interestPostingPeriodType = SavingsPostingInterestPeriodType.fromInt(newValue).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(interestCalculationTypeParamName, this.interestCalculationType)) {
|
if (command.isChangeInIntegerParameterNamed(interestCalculationTypeParamName, this.interestCalculationType)) {
|
||||||
@@ -310,15 +321,16 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
this.interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(newValue).getValue();
|
this.interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(newValue).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInBigDecimalParameterNamed(minRequiredOpeningBalanceParamName, this.minRequiredOpeningBalance)) {
|
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minRequiredOpeningBalanceParamName,
|
||||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(minRequiredOpeningBalanceParamName);
|
this.minRequiredOpeningBalance)) {
|
||||||
|
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredOpeningBalanceParamName);
|
||||||
actualChanges.put(minRequiredOpeningBalanceParamName, newValue);
|
actualChanges.put(minRequiredOpeningBalanceParamName, newValue);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.minRequiredOpeningBalance = newValue;
|
this.minRequiredOpeningBalance = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(lockinPeriodFrequencyParamName, this.lockinPeriodFrequency)) {
|
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(lockinPeriodFrequencyParamName, this.lockinPeriodFrequency)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyParamName);
|
final Integer newValue = command.integerValueOfParameterNamedDefaultToNullIfZero(lockinPeriodFrequencyParamName);
|
||||||
actualChanges.put(lockinPeriodFrequencyParamName, newValue);
|
actualChanges.put(lockinPeriodFrequencyParamName, newValue);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.lockinPeriodFrequency = newValue;
|
this.lockinPeriodFrequency = newValue;
|
||||||
@@ -327,47 +339,63 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
if (command.isChangeInIntegerParameterNamed(lockinPeriodFrequencyTypeParamName, this.lockinPeriodFrequencyType)) {
|
if (command.isChangeInIntegerParameterNamed(lockinPeriodFrequencyTypeParamName, this.lockinPeriodFrequencyType)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
||||||
actualChanges.put(lockinPeriodFrequencyTypeParamName, newValue);
|
actualChanges.put(lockinPeriodFrequencyTypeParamName, newValue);
|
||||||
this.lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(newValue).getValue();
|
this.lockinPeriodFrequencyType = newValue != null ? SavingsPeriodFrequencyType.fromInt(newValue).getValue() : newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInBigDecimalParameterNamed(withdrawalFeeAmountParamName, this.withdrawalFeeAmount)) {
|
// set period type to null if frequency is null
|
||||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
if (this.lockinPeriodFrequency == null) {
|
||||||
|
this.lockinPeriodFrequencyType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(withdrawalFeeAmountParamName, this.withdrawalFeeAmount)) {
|
||||||
|
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeAmountParamName);
|
||||||
actualChanges.put(withdrawalFeeAmountParamName, newValue);
|
actualChanges.put(withdrawalFeeAmountParamName, newValue);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.withdrawalFeeAmount = newValue;
|
this.withdrawalFeeAmount = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(withdrawalFeeTypeParamName, this.withdrawalFeeType)) {
|
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(withdrawalFeeTypeParamName, this.withdrawalFeeType)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
final Integer newValue = command.integerValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeTypeParamName);
|
||||||
actualChanges.put(withdrawalFeeTypeParamName, newValue);
|
actualChanges.put(withdrawalFeeTypeParamName, newValue);
|
||||||
this.withdrawalFeeType = newValue != null? SavingsWithdrawalFeesType.fromInt(newValue).getValue(): newValue;
|
this.withdrawalFeeType = newValue != null ? SavingsWithdrawalFeesType.fromInt(newValue).getValue() : newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInBigDecimalParameterNamed(annualFeeAmountParamName, this.annualFeeAmount)) {
|
// set period type to null if frequency is null
|
||||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
if (this.withdrawalFeeAmount == null) {
|
||||||
|
this.withdrawalFeeType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(annualFeeAmountParamName, this.annualFeeAmount)) {
|
||||||
|
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(annualFeeAmountParamName);
|
||||||
actualChanges.put(annualFeeAmountParamName, newValue);
|
actualChanges.put(annualFeeAmountParamName, newValue);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.annualFeeAmount = newValue;
|
this.annualFeeAmount = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnDay)) {
|
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(annualFeeOnMonthDayParamName, this.annualFeeOnDay)) {
|
||||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||||
final Integer newValue = monthDay != null? monthDay.getDayOfMonth(): null;
|
final Integer newValue = monthDay != null ? monthDay.getDayOfMonth() : null;
|
||||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.annualFeeOnDay = newValue;
|
this.annualFeeOnDay = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(annualFeeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
||||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||||
final Integer newValue = monthDay != null? monthDay.getMonthOfYear(): null;
|
final Integer newValue = monthDay != null ? monthDay.getMonthOfYear() : null;
|
||||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||||
actualChanges.put(localeParamName, localeAsInput);
|
actualChanges.put(localeParamName, localeAsInput);
|
||||||
this.annualFeeOnMonth = newValue;
|
this.annualFeeOnMonth = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set period type to null if frequency is null
|
||||||
|
if (this.annualFeeAmount == null) {
|
||||||
|
this.annualFeeOnDay = null;
|
||||||
|
this.annualFeeOnMonth = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (command.isChangeInIntegerParameterNamed(accountingRuleParamName, this.accountingRule)) {
|
if (command.isChangeInIntegerParameterNamed(accountingRuleParamName, this.accountingRule)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(accountingRuleParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(accountingRuleParamName);
|
||||||
actualChanges.put(accountingRuleParamName, newValue);
|
actualChanges.put(accountingRuleParamName, newValue);
|
||||||
@@ -382,42 +410,72 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateAnnualFeeDetails() {
|
private void validateAnnualFeeDetails() {
|
||||||
if (isInvalidConfigurationOfAnnualFeeSettings()) {
|
|
||||||
Object[] defaultUserMessageArgs = new Object[] { annualFeeAmountParamName };
|
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.annualfee.settings",
|
|
||||||
"Invalid configuration of annual fee settings.", defaultUserMessageArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInvalidConfigurationOfAnnualFeeSettings() {
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
return (this.annualFeeAmount == null && (this.annualFeeOnDay != null || this.annualFeeOnMonth != null))
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
|| ((this.annualFeeOnDay == null || this.annualFeeOnMonth == null) && this.annualFeeAmount != null);
|
.resource(SAVINGS_PRODUCT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
if (this.annualFeeAmount == null) {
|
||||||
|
|
||||||
|
if (this.annualFeeOnMonth != null || this.annualFeeOnDay != null) {
|
||||||
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).notNull();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (this.annualFeeOnMonth == null || this.annualFeeOnDay == null) {
|
||||||
|
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(this.annualFeeOnMonth).notNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(this.annualFeeAmount).zeroOrPositiveAmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateWithdrawalFeeDetails() {
|
private void validateWithdrawalFeeDetails() {
|
||||||
if (isInvalidConfigurationOfWithdrawalFeeSettings()) {
|
|
||||||
Object[] defaultUserMessageArgs = new Object[] { withdrawalFeeAmountParamName };
|
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.withdrawalfee.settings",
|
|
||||||
"Invalid configuration of withdrawal fee settings.", defaultUserMessageArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInvalidConfigurationOfWithdrawalFeeSettings() {
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
return (this.withdrawalFeeAmount == null && this.withdrawalFeeType != null)
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
|| (this.withdrawalFeeType == null && this.withdrawalFeeAmount != null);
|
.resource(SAVINGS_PRODUCT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
if (this.withdrawalFeeAmount == null) {
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(this.withdrawalFeeType).ignoreIfNull()
|
||||||
|
.isOneOfTheseValues(1, 2);
|
||||||
|
|
||||||
|
if (this.withdrawalFeeType != null) {
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(this.withdrawalFeeAmount).notNull();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(this.withdrawalFeeAmount).zeroOrPositiveAmount();
|
||||||
|
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(this.withdrawalFeeType).notNull()
|
||||||
|
.isOneOfTheseValues(1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateLockinDetails() {
|
private void validateLockinDetails() {
|
||||||
if (isInvalidConfigurationOfLockinSettings()) {
|
|
||||||
Object[] defaultUserMessageArgs = new Object[] { lockinPeriodFrequencyParamName };
|
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.lockin.settings",
|
|
||||||
"Invalid configuration of lock in settings.", defaultUserMessageArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInvalidConfigurationOfLockinSettings() {
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
return (this.lockinPeriodFrequency == null && this.lockinPeriodFrequencyType != null)
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
|| (this.lockinPeriodFrequencyType == null && this.lockinPeriodFrequency != null);
|
.resource(SAVINGS_PRODUCT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
if (this.lockinPeriodFrequency == null) {
|
||||||
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).ignoreIfNull()
|
||||||
|
.inMinMaxRange(0, 3);
|
||||||
|
|
||||||
|
if (this.lockinPeriodFrequencyType != null) {
|
||||||
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull()
|
||||||
|
.integerZeroOrGreater();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequencyType).integerZeroOrGreater();
|
||||||
|
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull()
|
||||||
|
.inMinMaxRange(0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCashBasedAccountingEnabled() {
|
public boolean isCashBasedAccountingEnabled() {
|
||||||
|
|||||||
+29
-22
@@ -5,22 +5,22 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings.domain;
|
||||||
|
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@@ -28,6 +28,12 @@ import org.joda.time.MonthDay;
|
|||||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -50,10 +56,10 @@ public class SavingsProductAssembler {
|
|||||||
interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
|
interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
SavingsInterestPostingPeriodType interestPostingPeriodType = null;
|
SavingsPostingInterestPeriodType interestPostingPeriodType = null;
|
||||||
final Integer interestPostingPeriodTypeValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
final Integer interestPostingPeriodTypeValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
||||||
if (interestPostingPeriodTypeValue != null) {
|
if (interestPostingPeriodTypeValue != null) {
|
||||||
interestPostingPeriodType = SavingsInterestPostingPeriodType.fromInt(interestPostingPeriodTypeValue);
|
interestPostingPeriodType = SavingsPostingInterestPeriodType.fromInt(interestPostingPeriodTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
SavingsInterestCalculationType interestCalculationType = null;
|
SavingsInterestCalculationType interestCalculationType = null;
|
||||||
@@ -69,23 +75,24 @@ public class SavingsProductAssembler {
|
|||||||
interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(interestCalculationDaysInYearTypeValue);
|
interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(interestCalculationDaysInYearTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal minRequiredOpeningBalance = command.bigDecimalValueOfParameterNamed(minRequiredOpeningBalanceParamName);
|
final BigDecimal minRequiredOpeningBalance = command
|
||||||
|
.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredOpeningBalanceParamName);
|
||||||
|
|
||||||
final Integer lockinPeriodFrequency = command.integerValueOfParameterNamed(lockinPeriodFrequencyParamName);
|
final Integer lockinPeriodFrequency = command.integerValueOfParameterNamedDefaultToNullIfZero(lockinPeriodFrequencyParamName);
|
||||||
SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
|
SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
|
||||||
final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
||||||
if (lockinPeriodFrequencyTypeValue != null) {
|
if (lockinPeriodFrequencyTypeValue != null) {
|
||||||
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal withdrawalFeeAmount = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
final BigDecimal withdrawalFeeAmount = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(withdrawalFeeAmountParamName);
|
||||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||||
if (withdrawalFeeTypeValue != null) {
|
if (withdrawalFeeTypeValue != null) {
|
||||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal annualFeeAmount = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
final BigDecimal annualFeeAmount = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(annualFeeAmountParamName);
|
||||||
final MonthDay monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
final MonthDay monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||||
|
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
|
||||||
|
public class CompoundInterestHelper {
|
||||||
|
|
||||||
|
public Money calculateInterestForAllPostingPeriods(final MonetaryCurrency currency, final List<PostingPeriod> allPeriods) {
|
||||||
|
|
||||||
|
// sum up the 'rounded' values that are posted each posting period
|
||||||
|
Money interestEarned = Money.zero(currency);
|
||||||
|
|
||||||
|
// total interest earned in previous periods but not yet recognised
|
||||||
|
BigDecimal interestEarnedButNotPosted = BigDecimal.ZERO;
|
||||||
|
for (PostingPeriod postingPeriod : allPeriods) {
|
||||||
|
|
||||||
|
final BigDecimal interestEarnedThisPeriod = postingPeriod.calculateInterest(interestEarnedButNotPosted);
|
||||||
|
|
||||||
|
Money moneyToBePostedForPeriod = Money.of(currency, interestEarnedThisPeriod);
|
||||||
|
|
||||||
|
interestEarned = interestEarned.plus(moneyToBePostedForPeriod);
|
||||||
|
|
||||||
|
interestEarnedButNotPosted = interestEarnedButNotPosted.add(moneyToBePostedForPeriod.getAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
|
||||||
|
public interface CompoundingPeriod {
|
||||||
|
|
||||||
|
BigDecimal calculateInterest(BigDecimal interestRateAsFraction, long daysInYear);
|
||||||
|
|
||||||
|
BigDecimal calculateInterest(SavingsCompoundingInterestPeriodType compoundingInterestPeriodType,
|
||||||
|
SavingsInterestCalculationType interestCalculationType, BigDecimal interestFromPreviousPostingPeriod,
|
||||||
|
BigDecimal interestRateAsFraction, long daysInYear);
|
||||||
|
}
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
|
||||||
|
public class DailyCompoundingPeriod implements CompoundingPeriod {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final LocalDateInterval periodInterval;
|
||||||
|
private final List<EndOfDayBalance> endOfDayBalances;
|
||||||
|
|
||||||
|
public static DailyCompoundingPeriod create(final LocalDateInterval periodInterval, final List<EndOfDayBalance> allEndOfDayBalances) {
|
||||||
|
|
||||||
|
final List<EndOfDayBalance> endOfDayBalancesWithinPeriod = endOfDayBalancesWithinPeriodInterval(periodInterval, allEndOfDayBalances);
|
||||||
|
|
||||||
|
return new DailyCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<EndOfDayBalance> endOfDayBalancesWithinPeriodInterval(final LocalDateInterval compoundingPeriodInterval,
|
||||||
|
final List<EndOfDayBalance> allEndOfDayBalances) {
|
||||||
|
|
||||||
|
List<EndOfDayBalance> endOfDayBalancesForPeriodInterval = new ArrayList<EndOfDayBalance>();
|
||||||
|
|
||||||
|
EndOfDayBalance cappedToPeriodEndDate = null;
|
||||||
|
|
||||||
|
for (EndOfDayBalance endOfDayBalance : allEndOfDayBalances) {
|
||||||
|
|
||||||
|
if (compoundingPeriodInterval.contains(endOfDayBalance.date())) {
|
||||||
|
cappedToPeriodEndDate = endOfDayBalance.upTo(compoundingPeriodInterval);
|
||||||
|
} else if (endOfDayBalance.contains(compoundingPeriodInterval)) {
|
||||||
|
cappedToPeriodEndDate = endOfDayBalance.upTo(compoundingPeriodInterval);
|
||||||
|
} else {
|
||||||
|
LocalDateInterval latestPeriod = LocalDateInterval.create(compoundingPeriodInterval.startDate(),
|
||||||
|
DateUtils.getLocalDateOfTenant());
|
||||||
|
cappedToPeriodEndDate = endOfDayBalance.upTo(latestPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cappedToPeriodEndDate != null) {
|
||||||
|
endOfDayBalancesForPeriodInterval.add(cappedToPeriodEndDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return endOfDayBalancesForPeriodInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DailyCompoundingPeriod(final LocalDateInterval periodInterval, final List<EndOfDayBalance> endOfDayBalances) {
|
||||||
|
this.periodInterval = periodInterval;
|
||||||
|
this.endOfDayBalances = endOfDayBalances;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (EndOfDayBalance balance : this.endOfDayBalances) {
|
||||||
|
BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, daysInYear);
|
||||||
|
interestEarned = interestEarned.add(interestOnBalanceUnrounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal calculateInterest(
|
||||||
|
@SuppressWarnings("unused") final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType,
|
||||||
|
@SuppressWarnings("unused") final SavingsInterestCalculationType interestCalculationType,
|
||||||
|
final BigDecimal interestFromPreviousPostingPeriod, final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
// for daily compounding - each interest calculated from previous daily
|
||||||
|
// calculations is 'compounded'
|
||||||
|
BigDecimal interestToCompound = interestFromPreviousPostingPeriod;
|
||||||
|
for (EndOfDayBalance balance : this.endOfDayBalances) {
|
||||||
|
BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound,
|
||||||
|
interestRateAsFraction, daysInYear);
|
||||||
|
interestToCompound = interestToCompound.add(interestOnBalanceUnrounded, MathContext.DECIMAL64).setScale(9);
|
||||||
|
interestEarned = interestEarned.add(interestOnBalanceUnrounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
|
||||||
|
public class EndOfDayBalance {
|
||||||
|
|
||||||
|
private final LocalDate date;
|
||||||
|
private final Money openingBalance;
|
||||||
|
private final Money endOfDayBalance;
|
||||||
|
private final int numberOfDays;
|
||||||
|
|
||||||
|
public static EndOfDayBalance from(final LocalDate date, final Money openingBalance, final Money endOfDayBalance, final int numberOfDays) {
|
||||||
|
return new EndOfDayBalance(date, openingBalance, endOfDayBalance, numberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance(final LocalDate date, final Money openingBalance, final Money endOfDayBalance, final int numberOfDays) {
|
||||||
|
this.date = date;
|
||||||
|
this.openingBalance = openingBalance;
|
||||||
|
this.endOfDayBalance = endOfDayBalance;
|
||||||
|
this.numberOfDays = numberOfDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate date() {
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money closingBalance() {
|
||||||
|
return this.endOfDayBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal cumulativeBalance(final BigDecimal interestToCompound) {
|
||||||
|
final BigDecimal daysAsBigDecimal = BigDecimal.valueOf(this.numberOfDays);
|
||||||
|
final BigDecimal realBalanceForInterestCalculation = this.endOfDayBalance.getAmount().add(interestToCompound);
|
||||||
|
return realBalanceForInterestCalculation.multiply(daysAsBigDecimal, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal calculateInterestOnBalance(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction,
|
||||||
|
final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64);
|
||||||
|
BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64);
|
||||||
|
BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(this.numberOfDays), MathContext.DECIMAL64);
|
||||||
|
|
||||||
|
BigDecimal realBalanceForInterestCalculation = this.endOfDayBalance.getAmount().add(interestToCompound);
|
||||||
|
|
||||||
|
return realBalanceForInterestCalculation.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Future Value (FV) = PV x (1+r)^n
|
||||||
|
*
|
||||||
|
* Interest = FV - PV PV = Principal or the Account Balance r = rate per
|
||||||
|
* compounding period (so for daily, r = nominalInterestRateAsFraction x
|
||||||
|
* 1/365 n = number of periods rate is compounded
|
||||||
|
*/
|
||||||
|
public BigDecimal calculateInterestOnBalanceAndInterest(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction,
|
||||||
|
final long daysInYear) {
|
||||||
|
BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64);
|
||||||
|
|
||||||
|
BigDecimal presentValue = endOfDayBalance.getAmount().add(interestToCompound);
|
||||||
|
|
||||||
|
BigDecimal r = interestRateAsFraction.multiply(multiplicand);
|
||||||
|
|
||||||
|
BigDecimal interestRateForCompoundingPeriodPlusOne = BigDecimal.ONE.add(r);
|
||||||
|
|
||||||
|
double interestRateForCompoundingPeriodPowered = Math.pow(interestRateForCompoundingPeriodPlusOne.doubleValue(),
|
||||||
|
Integer.valueOf(this.numberOfDays).doubleValue());
|
||||||
|
|
||||||
|
BigDecimal futureValue = presentValue.multiply(BigDecimal.valueOf(interestRateForCompoundingPeriodPowered), MathContext.DECIMAL64)
|
||||||
|
.setScale(9, RoundingMode.HALF_EVEN);
|
||||||
|
return futureValue.subtract(presentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval) {
|
||||||
|
|
||||||
|
Money startingBalance = openingBalance;
|
||||||
|
LocalDate balanceStartDate = this.date;
|
||||||
|
|
||||||
|
if (this.date.isBefore(compoundingPeriodInterval.startDate())) {
|
||||||
|
balanceStartDate = compoundingPeriodInterval.startDate();
|
||||||
|
startingBalance = endOfDayBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
int daysOfBalance = this.numberOfDays;
|
||||||
|
LocalDate balanceEndDate = balanceStartDate.plusDays(this.numberOfDays);
|
||||||
|
if (balanceEndDate.isAfter(compoundingPeriodInterval.endDate())) {
|
||||||
|
balanceEndDate = compoundingPeriodInterval.endDate();
|
||||||
|
LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate);
|
||||||
|
daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate();
|
||||||
|
}
|
||||||
|
if (balanceEndDate.isAfter(DateUtils.getLocalDateOfTenant())) {
|
||||||
|
balanceEndDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate);
|
||||||
|
daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new EndOfDayBalance(balanceStartDate, startingBalance, this.endOfDayBalance, daysOfBalance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(final LocalDateInterval compoundingPeriodInterval) {
|
||||||
|
|
||||||
|
final LocalDate balanceUpToDate = this.date.plusDays(this.numberOfDays);
|
||||||
|
|
||||||
|
final LocalDateInterval balanceInterval = LocalDateInterval.create(this.date, balanceUpToDate);
|
||||||
|
return balanceInterval.containsPortionOf(compoundingPeriodInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getNumberOfDays() {
|
||||||
|
return Integer.valueOf(this.numberOfDays);
|
||||||
|
}
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
|
||||||
|
public class MonthlyCompoundingPeriod implements CompoundingPeriod {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final LocalDateInterval periodInterval;
|
||||||
|
private final List<EndOfDayBalance> endOfDayBalances;
|
||||||
|
|
||||||
|
public static MonthlyCompoundingPeriod create(final LocalDateInterval periodInterval, final List<EndOfDayBalance> allEndOfDayBalances) {
|
||||||
|
|
||||||
|
final List<EndOfDayBalance> endOfDayBalancesWithinPeriod = endOfDayBalancesWithinPeriodInterval(periodInterval, allEndOfDayBalances);
|
||||||
|
|
||||||
|
return new MonthlyCompoundingPeriod(periodInterval, endOfDayBalancesWithinPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal calculateInterest(final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
for (EndOfDayBalance balance : endOfDayBalances) {
|
||||||
|
BigDecimal interestOnBalanceUnrounded = balance.calculateInterestOnBalance(BigDecimal.ZERO, interestRateAsFraction, daysInYear);
|
||||||
|
interestEarned = interestEarned.add(interestOnBalanceUnrounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal calculateInterest(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType,
|
||||||
|
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestToCompound,
|
||||||
|
final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
switch (interestCalculationType) {
|
||||||
|
case DAILY_BALANCE:
|
||||||
|
interestEarned = calculateUsingDailyBalanceMethod(compoundingInterestPeriodType, interestToCompound,
|
||||||
|
interestRateAsFraction, daysInYear);
|
||||||
|
break;
|
||||||
|
case AVERAGE_DAILY_BALANCE:
|
||||||
|
interestEarned = calculateUsingAverageDailyBalanceMethod(interestToCompound, interestRateAsFraction, daysInYear);
|
||||||
|
break;
|
||||||
|
case INVALID:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal calculateUsingAverageDailyBalanceMethod(final BigDecimal interestToCompound,
|
||||||
|
final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal cumulativeBalance = BigDecimal.ZERO;
|
||||||
|
Integer numberOfDays = Integer.valueOf(0);
|
||||||
|
|
||||||
|
for (EndOfDayBalance balance : endOfDayBalances) {
|
||||||
|
BigDecimal endOfDayCumulativeBalance = balance.cumulativeBalance(interestToCompound);
|
||||||
|
cumulativeBalance = cumulativeBalance.add(endOfDayCumulativeBalance);
|
||||||
|
|
||||||
|
Integer balanceExistsForNumberOfDays = balance.getNumberOfDays();
|
||||||
|
numberOfDays = numberOfDays + balanceExistsForNumberOfDays;
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
if (cumulativeBalance.compareTo(BigDecimal.ZERO) != 0 && numberOfDays > 0) {
|
||||||
|
BigDecimal averageDailyBalance = cumulativeBalance.divide(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64).setScale(9,
|
||||||
|
RoundingMode.HALF_EVEN);
|
||||||
|
|
||||||
|
BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64);
|
||||||
|
BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64);
|
||||||
|
BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(numberOfDays), MathContext.DECIMAL64);
|
||||||
|
|
||||||
|
interestEarned = averageDailyBalance.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal calculateUsingDailyBalanceMethod(final SavingsCompoundingInterestPeriodType compoundingInterestPeriodType,
|
||||||
|
final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
BigDecimal interestOnBalanceUnrounded = BigDecimal.ZERO;
|
||||||
|
for (EndOfDayBalance balance : endOfDayBalances) {
|
||||||
|
|
||||||
|
switch (compoundingInterestPeriodType) {
|
||||||
|
case DAILY:
|
||||||
|
interestOnBalanceUnrounded = balance.calculateInterestOnBalanceAndInterest(interestToCompound, interestRateAsFraction,
|
||||||
|
daysInYear);
|
||||||
|
break;
|
||||||
|
case MONTHLY:
|
||||||
|
interestOnBalanceUnrounded = balance.calculateInterestOnBalance(interestToCompound, interestRateAsFraction, daysInYear);
|
||||||
|
break;
|
||||||
|
// case QUATERLY:
|
||||||
|
// break;
|
||||||
|
// case WEEKLY:
|
||||||
|
// break;
|
||||||
|
// case BIWEEKLY:
|
||||||
|
// break;
|
||||||
|
// case BI_ANNUAL:
|
||||||
|
// break;
|
||||||
|
// case ANNUAL:
|
||||||
|
// break;
|
||||||
|
// case NO_COMPOUNDING_SIMPLE_INTEREST:
|
||||||
|
// break;
|
||||||
|
case INVALID:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
interestEarned = interestEarned.add(interestOnBalanceUnrounded);
|
||||||
|
}
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<EndOfDayBalance> endOfDayBalancesWithinPeriodInterval(final LocalDateInterval compoundingPeriodInterval,
|
||||||
|
final List<EndOfDayBalance> allEndOfDayBalances) {
|
||||||
|
|
||||||
|
List<EndOfDayBalance> endOfDayBalancesForPeriodInterval = new ArrayList<EndOfDayBalance>();
|
||||||
|
|
||||||
|
for (EndOfDayBalance endOfDayBalance : allEndOfDayBalances) {
|
||||||
|
|
||||||
|
if (compoundingPeriodInterval.contains(endOfDayBalance.date())) {
|
||||||
|
final EndOfDayBalance cappedToPeriodEndDate = endOfDayBalance.upTo(compoundingPeriodInterval);
|
||||||
|
endOfDayBalancesForPeriodInterval.add(cappedToPeriodEndDate);
|
||||||
|
} else if (endOfDayBalance.contains(compoundingPeriodInterval)) {
|
||||||
|
final EndOfDayBalance cappedToPeriodEndDate = endOfDayBalance.upTo(compoundingPeriodInterval);
|
||||||
|
endOfDayBalancesForPeriodInterval.add(cappedToPeriodEndDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return endOfDayBalancesForPeriodInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MonthlyCompoundingPeriod(final LocalDateInterval periodInterval, final List<EndOfDayBalance> endOfDayBalances) {
|
||||||
|
this.periodInterval = periodInterval;
|
||||||
|
this.endOfDayBalances = endOfDayBalances;
|
||||||
|
}
|
||||||
|
}
|
||||||
+248
@@ -0,0 +1,248 @@
|
|||||||
|
package org.mifosplatform.portfolio.savings.domain.interest;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||||
|
|
||||||
|
public class PostingPeriod {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final LocalDateInterval periodInterval;
|
||||||
|
private final MonetaryCurrency currency;
|
||||||
|
private final SavingsCompoundingInterestPeriodType interestCompoundingType;
|
||||||
|
private final BigDecimal interestRateAsFraction;
|
||||||
|
private final long daysInYear;
|
||||||
|
private final List<CompoundingPeriod> compoundingPeriods;
|
||||||
|
|
||||||
|
// interest posting details
|
||||||
|
private final LocalDate dateOfPostingTransaction;
|
||||||
|
private BigDecimal interestEarnedUnrounded;
|
||||||
|
private Money interestEarnedRounded;
|
||||||
|
|
||||||
|
// opening/closing details
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private final Money openingBalance;
|
||||||
|
private final Money closingBalance;
|
||||||
|
private final SavingsInterestCalculationType interestCalculationType;
|
||||||
|
|
||||||
|
public static PostingPeriod createFrom(final LocalDateInterval periodInterval, final Money periodStartingBalance,
|
||||||
|
final List<SavingsAccountTransaction> orderedListOfTransactions, final MonetaryCurrency currency,
|
||||||
|
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||||
|
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear) {
|
||||||
|
|
||||||
|
List<EndOfDayBalance> accountEndOfDayBalances = new ArrayList<EndOfDayBalance>();
|
||||||
|
|
||||||
|
Money openingDayBalance = periodStartingBalance;
|
||||||
|
Money closeOfDayBalance = openingDayBalance;
|
||||||
|
for (SavingsAccountTransaction transaction : orderedListOfTransactions) {
|
||||||
|
|
||||||
|
if (transaction.fallsWithin(periodInterval)) {
|
||||||
|
// the balance of the transaction falls entirely within this
|
||||||
|
// period so no need to do any cropping/bounding
|
||||||
|
EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalance(openingDayBalance);
|
||||||
|
accountEndOfDayBalances.add(endOfDayBalance);
|
||||||
|
|
||||||
|
openingDayBalance = endOfDayBalance.closingBalance();
|
||||||
|
} else if (transaction.spansAnyPortionOf(periodInterval)) {
|
||||||
|
EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalanceBoundedBy(openingDayBalance, periodInterval);
|
||||||
|
accountEndOfDayBalances.add(endOfDayBalance);
|
||||||
|
|
||||||
|
closeOfDayBalance = endOfDayBalance.closingBalance();
|
||||||
|
openingDayBalance = closeOfDayBalance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountEndOfDayBalances.isEmpty()) {
|
||||||
|
EndOfDayBalance endOfDayBalance = EndOfDayBalance.from(periodInterval.startDate(), openingDayBalance, closeOfDayBalance,
|
||||||
|
periodInterval.daysInPeriodInclusiveOfEndDate());
|
||||||
|
accountEndOfDayBalances.add(endOfDayBalance);
|
||||||
|
|
||||||
|
closeOfDayBalance = endOfDayBalance.closingBalance();
|
||||||
|
openingDayBalance = closeOfDayBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<CompoundingPeriod> compoundingPeriods = compoundingPeriodsInPostingPeriod(periodInterval, interestCompoundingPeriodType,
|
||||||
|
accountEndOfDayBalances);
|
||||||
|
|
||||||
|
return new PostingPeriod(periodInterval, currency, periodStartingBalance, openingDayBalance, interestCompoundingPeriodType,
|
||||||
|
interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PostingPeriod(final LocalDateInterval periodInterval, final MonetaryCurrency currency, final Money openingBalance,
|
||||||
|
final Money closingBalance, final SavingsCompoundingInterestPeriodType interestCompoundingType,
|
||||||
|
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
|
||||||
|
final List<CompoundingPeriod> compoundingPeriods) {
|
||||||
|
this.periodInterval = periodInterval;
|
||||||
|
this.currency = currency;
|
||||||
|
this.openingBalance = openingBalance;
|
||||||
|
this.closingBalance = closingBalance;
|
||||||
|
this.interestCompoundingType = interestCompoundingType;
|
||||||
|
this.interestCalculationType = interestCalculationType;
|
||||||
|
this.interestRateAsFraction = interestRateAsFraction;
|
||||||
|
this.daysInYear = daysInYear;
|
||||||
|
this.compoundingPeriods = compoundingPeriods;
|
||||||
|
|
||||||
|
this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money interest() {
|
||||||
|
return this.interestEarnedRounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate dateOfPostingTransaction() {
|
||||||
|
return this.dateOfPostingTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money closingBalance() {
|
||||||
|
return this.closingBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal calculateInterest(final BigDecimal interestFromPreviousPostingPeriod) {
|
||||||
|
BigDecimal interestEarned = BigDecimal.ZERO;
|
||||||
|
|
||||||
|
// for each compounding period accumulate the amount of interest
|
||||||
|
// to be applied to the balanced for interest calculation
|
||||||
|
BigDecimal interestCompounded = interestFromPreviousPostingPeriod;
|
||||||
|
for (CompoundingPeriod compoundingPeriod : this.compoundingPeriods) {
|
||||||
|
|
||||||
|
BigDecimal interestUnrounded = compoundingPeriod.calculateInterest(this.interestCompoundingType, this.interestCalculationType,
|
||||||
|
interestCompounded, this.interestRateAsFraction, this.daysInYear);
|
||||||
|
interestCompounded = interestCompounded.add(interestUnrounded);
|
||||||
|
interestEarned = interestEarned.add(interestUnrounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.interestEarnedUnrounded = interestEarned;
|
||||||
|
this.interestEarnedRounded = Money.of(this.currency, this.interestEarnedUnrounded);
|
||||||
|
|
||||||
|
return interestEarned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Money getInterestEarned() {
|
||||||
|
return this.interestEarnedRounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<CompoundingPeriod> compoundingPeriodsInPostingPeriod(final LocalDateInterval postingPeriodInterval,
|
||||||
|
final SavingsCompoundingInterestPeriodType interestPeriodType, final List<EndOfDayBalance> allEndOfDayBalances) {
|
||||||
|
|
||||||
|
List<CompoundingPeriod> compoundingPeriods = new ArrayList<CompoundingPeriod>();
|
||||||
|
|
||||||
|
CompoundingPeriod compoundingPeriod = null;
|
||||||
|
switch (interestPeriodType) {
|
||||||
|
case INVALID:
|
||||||
|
break;
|
||||||
|
case DAILY:
|
||||||
|
compoundingPeriod = DailyCompoundingPeriod.create(postingPeriodInterval, allEndOfDayBalances);
|
||||||
|
compoundingPeriods.add(compoundingPeriod);
|
||||||
|
break;
|
||||||
|
case MONTHLY:
|
||||||
|
|
||||||
|
final LocalDate postingPeriodEndDate = postingPeriodInterval.endDate();
|
||||||
|
|
||||||
|
LocalDate periodStartDate = postingPeriodInterval.startDate();
|
||||||
|
LocalDate periodEndDate = periodStartDate;
|
||||||
|
|
||||||
|
while (!periodStartDate.isAfter(postingPeriodEndDate) && !periodEndDate.isAfter(postingPeriodEndDate)) {
|
||||||
|
|
||||||
|
periodEndDate = determineInterestPeriodEndDateFrom(periodStartDate, interestPeriodType);
|
||||||
|
if (periodEndDate.isAfter(postingPeriodEndDate)) {
|
||||||
|
periodEndDate = postingPeriodEndDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
final LocalDateInterval compoundingPeriodInterval = LocalDateInterval.create(periodStartDate, periodEndDate);
|
||||||
|
if (postingPeriodInterval.contains(compoundingPeriodInterval)) {
|
||||||
|
|
||||||
|
compoundingPeriod = MonthlyCompoundingPeriod.create(compoundingPeriodInterval, allEndOfDayBalances);
|
||||||
|
compoundingPeriods.add(compoundingPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move periodStartDate forward to day after this period
|
||||||
|
periodStartDate = periodEndDate.plusDays(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// case WEEKLY:
|
||||||
|
// break;
|
||||||
|
// case BIWEEKLY:
|
||||||
|
// break;
|
||||||
|
// case QUATERLY:
|
||||||
|
// break;
|
||||||
|
// case BI_ANNUAL:
|
||||||
|
// break;
|
||||||
|
// case ANNUAL:
|
||||||
|
// break;
|
||||||
|
// case NO_COMPOUNDING_SIMPLE_INTEREST:
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return compoundingPeriods;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate determineInterestPeriodEndDateFrom(final LocalDate periodStartDate,
|
||||||
|
final SavingsCompoundingInterestPeriodType interestPeriodType) {
|
||||||
|
|
||||||
|
LocalDate periodEndDate = DateUtils.getLocalDateOfTenant();
|
||||||
|
|
||||||
|
switch (interestPeriodType) {
|
||||||
|
case INVALID:
|
||||||
|
break;
|
||||||
|
case DAILY:
|
||||||
|
periodEndDate = periodStartDate;
|
||||||
|
break;
|
||||||
|
// case WEEKLY:
|
||||||
|
// periodEndDate = periodStartDate.dayOfWeek().withMaximumValue();
|
||||||
|
// break;
|
||||||
|
// case BIWEEKLY:
|
||||||
|
// final LocalDate closestEndOfWeek =
|
||||||
|
// periodStartDate.dayOfWeek().withMaximumValue();
|
||||||
|
// periodEndDate = closestEndOfWeek.plusWeeks(1);
|
||||||
|
// break;
|
||||||
|
case MONTHLY:
|
||||||
|
// produce period end date on last day of current month
|
||||||
|
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||||
|
break;
|
||||||
|
// case QUATERLY:
|
||||||
|
// // jan 1st to mar 31st, 1st apr to jun 30, jul 1st to sept 30,
|
||||||
|
// // oct 1st to dec 31
|
||||||
|
// int year = periodStartDate.getYearOfEra();
|
||||||
|
// int monthofYear = periodStartDate.getMonthOfYear();
|
||||||
|
// if (monthofYear <= 3) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 3, 31).toLocalDate();
|
||||||
|
// } else if (monthofYear <= 6) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
|
||||||
|
// } else if (monthofYear <= 9) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 9, 30).toLocalDate();
|
||||||
|
// } else if (monthofYear <= 12) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case BI_ANNUAL:
|
||||||
|
// // jan 1st to 30, jul 1st to dec 31
|
||||||
|
// year = periodStartDate.getYearOfEra();
|
||||||
|
// monthofYear = periodStartDate.getMonthOfYear();
|
||||||
|
// if (monthofYear <= 6) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
|
||||||
|
// } else if (monthofYear <= 12) {
|
||||||
|
// periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case ANNUAL:
|
||||||
|
// periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||||
|
// periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||||
|
// break;
|
||||||
|
// case NO_COMPOUNDING_SIMPLE_INTEREST:
|
||||||
|
// periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||||
|
// periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return periodEndDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-3
@@ -15,8 +15,10 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRul
|
|||||||
*/
|
*/
|
||||||
public class InsufficientAccountBalanceException extends AbstractPlatformDomainRuleException {
|
public class InsufficientAccountBalanceException extends AbstractPlatformDomainRuleException {
|
||||||
|
|
||||||
public InsufficientAccountBalanceException(final String paramName, final BigDecimal accountBalance, final BigDecimal withdrawalFee, final BigDecimal transactionAmount) {
|
public InsufficientAccountBalanceException(final String paramName, final BigDecimal accountBalance, final BigDecimal withdrawalFee,
|
||||||
super(withdrawalFee != null? "error.msg.savingsaccount.transaction.insufficient.account.balance.withdraw" : "error.msg.savingsaccount.transaction.insufficient.account.balance",
|
final BigDecimal transactionAmount) {
|
||||||
"Insufficient account balance.", paramName, accountBalance, withdrawalFee, transactionAmount);
|
super(withdrawalFee != null ? "error.msg.savingsaccount.transaction.insufficient.account.balance.withdraw"
|
||||||
|
: "error.msg.savingsaccount.transaction.insufficient.account.balance", "Insufficient account balance.", paramName,
|
||||||
|
accountBalance, withdrawalFee, transactionAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -16,16 +16,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class ActivateSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class ActivateSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ActivateSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public ActivateSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.writePlatformService = savingAccountWritePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.activate(command.getSavingsId(), command);
|
return this.writePlatformService.activate(command.getSavingsId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-4
@@ -16,16 +16,17 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class CalculateInterestSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class CalculateInterestSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public CalculateInterestSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public CalculateInterestSavingsAccountCommandHandler(
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
final SavingsAccountWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.calculateInterest(command.getSavingsId(), command);
|
return this.writePlatformService.calculateInterest(command.getSavingsId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -16,16 +16,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class DepositSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class DepositSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DepositSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public DepositSavingsAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.deposit(command.getSavingsId(), command);
|
return this.writePlatformService.deposit(command.getSavingsId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-4
@@ -16,16 +16,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class PostInterestSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class PostInterestSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public PostInterestSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public PostInterestSavingsAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.postInterest(command.getSavingsId(), command);
|
return this.writePlatformService.postInterest(command.getSavingsId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+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.savings.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.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SavingsAccountApplicationApprovalCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final SavingsApplicationProcessWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsAccountApplicationApprovalCommandHandler(final SavingsApplicationProcessWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.writePlatformService.approveApplication(command.entityId(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+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.savings.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.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SavingsAccountApplicationApprovalUndoCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final SavingsApplicationProcessWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsAccountApplicationApprovalUndoCommandHandler(final SavingsApplicationProcessWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.writePlatformService.undoApplicationApproval(command.entityId(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -8,25 +8,25 @@ package org.mifosplatform.portfolio.savings.handler;
|
|||||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DeleteSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class SavingsAccountApplicationDeletionCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DeleteSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public SavingsAccountApplicationDeletionCommandHandler(final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.deleteSavingAccount(command.entityId());
|
return this.savingAccountWritePlatformService.deleteApplication(command.entityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+6
-7
@@ -8,25 +8,24 @@ package org.mifosplatform.portfolio.savings.handler;
|
|||||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class UpdateSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class SavingsAccountApplicationModificationCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UpdateSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public SavingsAccountApplicationModificationCommandHandler(final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.updateSavingAccount(command.entityId(), command);
|
return this.savingAccountWritePlatformService.modifyApplication(command.entityId(), command);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
+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.savings.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.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SavingsAccountApplicationRejectedCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final SavingsApplicationProcessWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsAccountApplicationRejectedCommandHandler(final SavingsApplicationProcessWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.writePlatformService.rejectApplication(command.entityId(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -8,24 +8,24 @@ package org.mifosplatform.portfolio.savings.handler;
|
|||||||
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.mifosplatform.portfolio.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CreateSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class SavingsAccountApplicationSubmittalCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public CreateSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public SavingsAccountApplicationSubmittalCommandHandler(final SavingsApplicationProcessWritePlatformService savingAccountWritePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.createSavingAccount(command);
|
return this.savingAccountWritePlatformService.submitApplication(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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.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.savings.service.SavingsApplicationProcessWritePlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SavingsAccountApplicationWithdrawnByApplicantCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final SavingsApplicationProcessWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsAccountApplicationWithdrawnByApplicantCommandHandler(
|
||||||
|
final SavingsApplicationProcessWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
return this.writePlatformService.applicantWithdrawsFromApplication(command.entityId(), command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-4
@@ -16,16 +16,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@Service
|
@Service
|
||||||
public class WithdrawSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
public class WithdrawSavingsAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService savingAccountWritePlatformService;
|
private final SavingsAccountWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public WithdrawSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
|
public WithdrawSavingsAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
||||||
this.savingAccountWritePlatformService = savingAccountWritePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
return this.savingAccountWritePlatformService.withdrawal(command.getSavingsId(), command);
|
return this.writePlatformService.withdrawal(command.getSavingsId(), command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+129
@@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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 final class SavingsAccountApplicationTransitionApiJsonValidator {
|
||||||
|
|
||||||
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsAccountApplicationTransitionApiJsonValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||||
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateApproval(final String json) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
|
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("approvedOnDate", "note", "locale", "dateFormat"));
|
||||||
|
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||||
|
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("savingsaccountapplication");
|
||||||
|
|
||||||
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
final LocalDate approvedOnDate = fromApiJsonHelper.extractLocalDateNamed("approvedOnDate", element);
|
||||||
|
baseDataValidator.reset().parameter("approvedOnDate").value(approvedOnDate).notNull();
|
||||||
|
|
||||||
|
final String note = fromApiJsonHelper.extractStringNamed("note", element);
|
||||||
|
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||||
|
|
||||||
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateRejection(final String json) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
|
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("rejectedOnDate", "note", "locale", "dateFormat"));
|
||||||
|
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||||
|
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("savingsaccountapplication");
|
||||||
|
|
||||||
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
final LocalDate rejectedOnDate = fromApiJsonHelper.extractLocalDateNamed("rejectedOnDate", element);
|
||||||
|
baseDataValidator.reset().parameter("rejectedOnDate").value(rejectedOnDate).notNull();
|
||||||
|
|
||||||
|
final String note = fromApiJsonHelper.extractStringNamed("note", element);
|
||||||
|
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||||
|
|
||||||
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateApplicantWithdrawal(final String json) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
|
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("withdrawnOnDate", "note", "locale", "dateFormat"));
|
||||||
|
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||||
|
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("savingsaccountapplication");
|
||||||
|
|
||||||
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
final LocalDate withdrawnOnDate = fromApiJsonHelper.extractLocalDateNamed("withdrawnOnDate", element);
|
||||||
|
baseDataValidator.reset().parameter("withdrawnOnDate").value(withdrawnOnDate).notNull();
|
||||||
|
|
||||||
|
final String note = fromApiJsonHelper.extractStringNamed("note", element);
|
||||||
|
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||||
|
|
||||||
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateForUndo(final String json) {
|
||||||
|
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||||
|
|
||||||
|
final Set<String> undoSupportedParameters = new HashSet<String>(Arrays.asList("note"));
|
||||||
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
|
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, undoSupportedParameters);
|
||||||
|
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
|
.resource("savingsaccountapplication.undo");
|
||||||
|
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||||
|
|
||||||
|
final String note = "note";
|
||||||
|
if (fromApiJsonHelper.parameterExists(note, element)) {
|
||||||
|
final String noteText = fromApiJsonHelper.extractStringNamed(note, element);
|
||||||
|
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -18,7 +18,7 @@ public interface SavingsAccountReadPlatformService {
|
|||||||
|
|
||||||
SavingsAccountData retrieveOne(Long savingsId);
|
SavingsAccountData retrieveOne(Long savingsId);
|
||||||
|
|
||||||
SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long productId);
|
SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long productId, boolean staffInSelectedOfficeOnly);
|
||||||
|
|
||||||
SavingsAccountTransactionData retrieveDepositTransactionTemplate(Long savingsId);
|
SavingsAccountTransactionData retrieveDepositTransactionTemplate(Long savingsId);
|
||||||
|
|
||||||
|
|||||||
+151
-38
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.savings.service;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
@@ -23,23 +24,26 @@ import org.mifosplatform.infrastructure.core.service.PaginationHelper;
|
|||||||
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||||
|
import org.mifosplatform.organisation.staff.data.StaffData;
|
||||||
|
import org.mifosplatform.organisation.staff.service.StaffReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
import org.mifosplatform.portfolio.group.data.GroupGeneralData;
|
||||||
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
|
import org.mifosplatform.portfolio.group.service.GroupReadPlatformService;
|
||||||
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
import org.mifosplatform.portfolio.group.service.SearchParameters;
|
||||||
import org.mifosplatform.portfolio.paymentdetail.data.PaymentDetailData;
|
import org.mifosplatform.portfolio.paymentdetail.data.PaymentDetailData;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountSummaryData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountSummaryData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
|
||||||
import org.mifosplatform.portfolio.savings.exception.SavingsAccountNotFoundException;
|
import org.mifosplatform.portfolio.savings.exception.SavingsAccountNotFoundException;
|
||||||
import org.mifosplatform.useradministration.domain.AppUser;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -47,6 +51,7 @@ import org.springframework.dao.EmptyResultDataAccessException;
|
|||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.jdbc.core.RowMapper;
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountReadPlatformService {
|
public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountReadPlatformService {
|
||||||
@@ -56,10 +61,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
private final ClientReadPlatformService clientReadPlatformService;
|
private final ClientReadPlatformService clientReadPlatformService;
|
||||||
private final GroupReadPlatformService groupReadPlatformService;
|
private final GroupReadPlatformService groupReadPlatformService;
|
||||||
private final SavingsProductReadPlatformService savingsProductReadPlatformService;
|
private final SavingsProductReadPlatformService savingsProductReadPlatformService;
|
||||||
|
private final StaffReadPlatformService staffReadPlatformService;
|
||||||
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
||||||
private final SavingsAccountTransactionTemplateMapper transactionTemplateMapper;
|
private final SavingsAccountTransactionTemplateMapper transactionTemplateMapper;
|
||||||
private final SavingsAccountTransactionsMapper transactionsMapper;
|
private final SavingsAccountTransactionsMapper transactionsMapper;
|
||||||
|
|
||||||
private final PaginationHelper<SavingsAccountData> paginationHelper = new PaginationHelper<SavingsAccountData>();
|
private final PaginationHelper<SavingsAccountData> paginationHelper = new PaginationHelper<SavingsAccountData>();
|
||||||
private final SavingAccountMapper savingAccountMapper = new SavingAccountMapper();
|
private final SavingAccountMapper savingAccountMapper = new SavingAccountMapper();
|
||||||
|
|
||||||
@@ -67,15 +73,16 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
public SavingsAccountReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
public SavingsAccountReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
|
||||||
final ClientReadPlatformService clientReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
|
final ClientReadPlatformService clientReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
|
||||||
final SavingsProductReadPlatformService savingProductReadPlatformService,
|
final SavingsProductReadPlatformService savingProductReadPlatformService,
|
||||||
final SavingsDropdownReadPlatformService dropdownReadPlatformService) {
|
final StaffReadPlatformService staffReadPlatformService, final SavingsDropdownReadPlatformService dropdownReadPlatformService) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
this.clientReadPlatformService = clientReadPlatformService;
|
this.clientReadPlatformService = clientReadPlatformService;
|
||||||
this.groupReadPlatformService = groupReadPlatformService;
|
this.groupReadPlatformService = groupReadPlatformService;
|
||||||
this.savingsProductReadPlatformService = savingProductReadPlatformService;
|
this.savingsProductReadPlatformService = savingProductReadPlatformService;
|
||||||
|
this.staffReadPlatformService = staffReadPlatformService;
|
||||||
this.dropdownReadPlatformService = dropdownReadPlatformService;
|
this.dropdownReadPlatformService = dropdownReadPlatformService;
|
||||||
transactionTemplateMapper = new SavingsAccountTransactionTemplateMapper();
|
this.transactionTemplateMapper = new SavingsAccountTransactionTemplateMapper();
|
||||||
transactionsMapper = new SavingsAccountTransactionsMapper();
|
this.transactionsMapper = new SavingsAccountTransactionsMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -151,13 +158,40 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
public SavingAccountMapper() {
|
public SavingAccountMapper() {
|
||||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||||
sqlBuilder.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, ");
|
sqlBuilder.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, ");
|
||||||
sqlBuilder.append("sa.status_enum as statusEnum, sa.activation_date as activationDate, ");
|
|
||||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||||
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
||||||
|
sqlBuilder.append("s.id fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||||
|
sqlBuilder.append("sa.status_enum as statusEnum, ");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.submittedon_date as submittedOnDate,");
|
||||||
|
sqlBuilder.append("sbu.username as submittedByUsername,");
|
||||||
|
sqlBuilder.append("sbu.firstname as submittedByFirstname, sbu.lastname as submittedByLastname,");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.rejectedon_date as rejectedOnDate,");
|
||||||
|
sqlBuilder.append("rbu.username as rejectedByUsername,");
|
||||||
|
sqlBuilder.append("rbu.firstname as rejectedByFirstname, rbu.lastname as rejectedByLastname,");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.withdrawnon_date as withdrawnOnDate,");
|
||||||
|
sqlBuilder.append("wbu.username as withdrawnByUsername,");
|
||||||
|
sqlBuilder.append("wbu.firstname as withdrawnByFirstname, wbu.lastname as withdrawnByLastname,");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.approvedon_date as approvedOnDate,");
|
||||||
|
sqlBuilder.append("abu.username as approvedByUsername,");
|
||||||
|
sqlBuilder.append("abu.firstname as approvedByFirstname, abu.lastname as approvedByLastname,");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.activatedon_date as activatedOnDate,");
|
||||||
|
sqlBuilder.append("avbu.username as activatedByUsername,");
|
||||||
|
sqlBuilder.append("avbu.firstname as activatedByFirstname, avbu.lastname as activatedByLastname,");
|
||||||
|
|
||||||
|
sqlBuilder.append("sa.closedon_date as closedOnDate,");
|
||||||
|
sqlBuilder.append("cbu.username as closedByUsername,");
|
||||||
|
sqlBuilder.append("cbu.firstname as closedByFirstname, cbu.lastname as closedByLastname,");
|
||||||
|
|
||||||
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, ");
|
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, ");
|
||||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
|
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
|
||||||
|
|
||||||
sqlBuilder.append("sa.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
|
sqlBuilder.append("sa.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
|
||||||
sqlBuilder.append("sa.interest_compounding_period_enum as interestCompoundingPeriodType, ");
|
sqlBuilder.append("sa.interest_compounding_period_enum as interestCompoundingPeriodType, ");
|
||||||
sqlBuilder.append("sa.interest_posting_period_enum as interestPostingPeriodType, ");
|
sqlBuilder.append("sa.interest_posting_period_enum as interestPostingPeriodType, ");
|
||||||
@@ -180,10 +214,17 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append("sa.total_interest_posted_derived as totalInterestPosted, ");
|
sqlBuilder.append("sa.total_interest_posted_derived as totalInterestPosted, ");
|
||||||
sqlBuilder.append("sa.account_balance_derived as accountBalance ");
|
sqlBuilder.append("sa.account_balance_derived as accountBalance ");
|
||||||
sqlBuilder.append("from m_savings_account sa ");
|
sqlBuilder.append("from m_savings_account sa ");
|
||||||
sqlBuilder.append("left outer join m_client c ON c.id = sa.client_id ");
|
|
||||||
sqlBuilder.append("left outer join m_group g ON g.id = sa.group_id ");
|
|
||||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
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("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 ");
|
||||||
|
sqlBuilder.append("left join m_appuser sbu on sbu.id = sa.submittedon_userid ");
|
||||||
|
sqlBuilder.append("left join m_appuser rbu on rbu.id = sa.rejectedon_userid ");
|
||||||
|
sqlBuilder.append("left join m_appuser wbu on wbu.id = sa.withdrawnon_userid ");
|
||||||
|
sqlBuilder.append("left join m_appuser abu on abu.id = sa.approvedon_userid ");
|
||||||
|
sqlBuilder.append("left join m_appuser avbu on rbu.id = sa.activatedon_userid ");
|
||||||
|
sqlBuilder.append("left join m_appuser cbu on cbu.id = sa.closedon_userid ");
|
||||||
|
|
||||||
this.schemaSql = sqlBuilder.toString();
|
this.schemaSql = sqlBuilder.toString();
|
||||||
}
|
}
|
||||||
@@ -199,11 +240,6 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
final String accountNo = rs.getString("accountNo");
|
final String accountNo = rs.getString("accountNo");
|
||||||
final String externalId = rs.getString("externalId");
|
final String externalId = rs.getString("externalId");
|
||||||
|
|
||||||
final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
|
|
||||||
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusEnum);
|
|
||||||
|
|
||||||
final LocalDate activationDate = JdbcSupport.getLocalDate(rs, "activationDate");
|
|
||||||
|
|
||||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||||
final String groupName = rs.getString("groupName");
|
final String groupName = rs.getString("groupName");
|
||||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||||
@@ -212,6 +248,49 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
final Long productId = rs.getLong("productId");
|
final Long productId = rs.getLong("productId");
|
||||||
final String productName = rs.getString("productName");
|
final String productName = rs.getString("productName");
|
||||||
|
|
||||||
|
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||||
|
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||||
|
|
||||||
|
final Integer statusEnum = JdbcSupport.getInteger(rs, "statusEnum");
|
||||||
|
final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusEnum);
|
||||||
|
|
||||||
|
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
|
||||||
|
final String submittedByUsername = rs.getString("submittedByUsername");
|
||||||
|
final String submittedByFirstname = rs.getString("submittedByFirstname");
|
||||||
|
final String submittedByLastname = rs.getString("submittedByLastname");
|
||||||
|
|
||||||
|
final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedOnDate");
|
||||||
|
final String rejectedByUsername = rs.getString("rejectedByUsername");
|
||||||
|
final String rejectedByFirstname = rs.getString("rejectedByFirstname");
|
||||||
|
final String rejectedByLastname = rs.getString("rejectedByLastname");
|
||||||
|
|
||||||
|
final LocalDate withdrawnOnDate = JdbcSupport.getLocalDate(rs, "withdrawnOnDate");
|
||||||
|
final String withdrawnByUsername = rs.getString("withdrawnByUsername");
|
||||||
|
final String withdrawnByFirstname = rs.getString("withdrawnByFirstname");
|
||||||
|
final String withdrawnByLastname = rs.getString("withdrawnByLastname");
|
||||||
|
|
||||||
|
final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate");
|
||||||
|
final String approvedByUsername = rs.getString("approvedByUsername");
|
||||||
|
final String approvedByFirstname = rs.getString("approvedByFirstname");
|
||||||
|
final String approvedByLastname = rs.getString("approvedByLastname");
|
||||||
|
|
||||||
|
final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedOnDate");
|
||||||
|
final String activatedByUsername = rs.getString("activatedByUsername");
|
||||||
|
final String activatedByFirstname = rs.getString("activatedByFirstname");
|
||||||
|
final String activatedByLastname = rs.getString("activatedByLastname");
|
||||||
|
|
||||||
|
final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
|
||||||
|
final String closedByUsername = rs.getString("closedByUsername");
|
||||||
|
final String closedByFirstname = rs.getString("closedByFirstname");
|
||||||
|
final String closedByLastname = rs.getString("closedByLastname");
|
||||||
|
|
||||||
|
final SavingsAccountApplicationTimelineData timeline = new SavingsAccountApplicationTimelineData(submittedOnDate,
|
||||||
|
submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername,
|
||||||
|
rejectedByFirstname, rejectedByLastname, withdrawnOnDate, withdrawnByUsername, withdrawnByFirstname,
|
||||||
|
withdrawnByLastname, approvedOnDate, approvedByUsername, approvedByFirstname, approvedByLastname, activatedOnDate,
|
||||||
|
activatedByUsername, activatedByFirstname, activatedByLastname, closedOnDate, closedByUsername, closedByFirstname,
|
||||||
|
closedByLastname);
|
||||||
|
|
||||||
final String currencyCode = rs.getString("currencyCode");
|
final String currencyCode = rs.getString("currencyCode");
|
||||||
final String currencyName = rs.getString("currencyName");
|
final String currencyName = rs.getString("currencyName");
|
||||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||||
@@ -226,7 +305,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
||||||
"interestCompoundingPeriodType")));
|
"interestCompoundingPeriodType")));
|
||||||
|
|
||||||
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType
|
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(SavingsPostingInterestPeriodType
|
||||||
.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));
|
.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));
|
||||||
|
|
||||||
final EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
|
final EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
|
||||||
@@ -277,27 +356,31 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
|
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
|
||||||
totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance);
|
totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance);
|
||||||
|
|
||||||
return SavingsAccountData.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
return SavingsAccountData.instance(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||||
productId, productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
annualFeeNextDueDate, summary);
|
annualFeeOnMonthDay, annualFeeNextDueDate, summary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SavingsAccountData retrieveTemplate(final Long clientId, final Long groupId, final Long productId) {
|
public SavingsAccountData retrieveTemplate(final Long clientId, final Long groupId, final Long productId,
|
||||||
|
final boolean staffInSelectedOfficeOnly) {
|
||||||
|
|
||||||
context.authenticatedUser();
|
AppUser loggedInUser = context.authenticatedUser();
|
||||||
|
Long officeId = loggedInUser.getOffice().getId();
|
||||||
|
|
||||||
ClientData client = null;
|
ClientData client = null;
|
||||||
if (clientId != null) {
|
if (clientId != null) {
|
||||||
client = this.clientReadPlatformService.retrieveOne(clientId);
|
client = this.clientReadPlatformService.retrieveOne(clientId);
|
||||||
|
officeId = client.officeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupGeneralData group = null;
|
GroupGeneralData group = null;
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
group = this.groupReadPlatformService.retrieveOne(groupId);
|
group = this.groupReadPlatformService.retrieveOne(groupId);
|
||||||
|
officeId = group.officeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Collection<SavingsProductData> productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
|
final Collection<SavingsProductData> productOptions = this.savingsProductReadPlatformService.retrieveAllForLookup();
|
||||||
@@ -328,9 +411,35 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
|
|
||||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||||
|
|
||||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
|
Collection<StaffData> fieldOfficerOptions = null;
|
||||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
if (officeId != null) {
|
||||||
|
|
||||||
|
if (staffInSelectedOfficeOnly) {
|
||||||
|
// only bring back loan officers in selected branch/office
|
||||||
|
Collection<StaffData> fieldOfficersInBranch = this.staffReadPlatformService
|
||||||
|
.retrieveAllLoanOfficersInOfficeById(officeId);
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(fieldOfficersInBranch)) {
|
||||||
|
fieldOfficerOptions = new ArrayList<StaffData>(fieldOfficersInBranch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// by default bring back all officers in selected
|
||||||
|
// branch/office as well as officers in office above
|
||||||
|
// this office
|
||||||
|
final boolean restrictToLoanOfficersOnly = true;
|
||||||
|
Collection<StaffData> loanOfficersInHierarchy = this.staffReadPlatformService
|
||||||
|
.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId, restrictToLoanOfficersOnly);
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
|
||||||
|
fieldOfficerOptions = new ArrayList<StaffData>(loanOfficersInHierarchy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template = SavingsAccountData.withTemplateOptions(template, productOptions, fieldOfficerOptions,
|
||||||
|
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||||
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
String clientName = null;
|
String clientName = null;
|
||||||
@@ -345,6 +454,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
|
|
||||||
template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
|
template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
|
||||||
|
|
||||||
|
final Collection<StaffData> fieldOfficerOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||||
@@ -354,9 +464,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
|
|
||||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||||
|
|
||||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
|
template = SavingsAccountData.withTemplateOptions(template, productOptions, fieldOfficerOptions,
|
||||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return template;
|
return template;
|
||||||
@@ -553,7 +663,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
||||||
"interestCompoundingPeriodType")));
|
"interestCompoundingPeriodType")));
|
||||||
|
|
||||||
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType
|
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(SavingsPostingInterestPeriodType
|
||||||
.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));
|
.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));
|
||||||
|
|
||||||
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
|
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
|
||||||
@@ -604,16 +714,19 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
groupName = group.getName();
|
groupName = group.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Long fieldOfficerId = null;
|
||||||
|
final String fieldOfficerName = null;
|
||||||
final SavingsAccountStatusEnumData status = null;
|
final SavingsAccountStatusEnumData status = null;
|
||||||
final LocalDate activationDate = null;
|
|
||||||
final LocalDate annualFeeNextDueDate = null;
|
final LocalDate annualFeeNextDueDate = null;
|
||||||
final SavingsAccountSummaryData summary = null;
|
final SavingsAccountSummaryData summary = null;
|
||||||
|
|
||||||
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
|
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
||||||
productId, productName, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
return SavingsAccountData.instance(null, null, null, groupId, groupName, clientId, clientName, productId, productName,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType,
|
||||||
annualFeeNextDueDate, summary);
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
|
annualFeeOnMonthDay, annualFeeNextDueDate, summary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-9
@@ -10,21 +10,15 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
|||||||
|
|
||||||
public interface SavingsAccountWritePlatformService {
|
public interface SavingsAccountWritePlatformService {
|
||||||
|
|
||||||
CommandProcessingResult createSavingAccount(JsonCommand command);
|
|
||||||
|
|
||||||
CommandProcessingResult updateSavingAccount(Long accountId, JsonCommand command);
|
|
||||||
|
|
||||||
CommandProcessingResult deleteSavingAccount(Long accountId);
|
|
||||||
|
|
||||||
CommandProcessingResult activate(Long savingsId, JsonCommand command);
|
CommandProcessingResult activate(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult deposit(Long savingsId, JsonCommand command);
|
CommandProcessingResult deposit(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult withdrawal(Long savingsId, JsonCommand command);
|
CommandProcessingResult withdrawal(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
CommandProcessingResult applyAnnualFee(Long savingsId);
|
CommandProcessingResult applyAnnualFee(Long savingsId);
|
||||||
|
|
||||||
CommandProcessingResult calculateInterest(Long savingsId, JsonCommand command);
|
CommandProcessingResult calculateInterest(Long savingsId);
|
||||||
|
|
||||||
CommandProcessingResult postInterest(Long savingsId, JsonCommand command);
|
CommandProcessingResult postInterest(Long savingsId);
|
||||||
}
|
}
|
||||||
+54
-199
@@ -6,6 +6,8 @@
|
|||||||
package org.mifosplatform.portfolio.savings.service;
|
package org.mifosplatform.portfolio.savings.service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.math.RoundingMode;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -19,66 +21,45 @@ import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatfo
|
|||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
|
||||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
|
||||||
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
|
||||||
import org.mifosplatform.portfolio.client.domain.Client;
|
|
||||||
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
|
||||||
import org.mifosplatform.portfolio.group.domain.Group;
|
|
||||||
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
|
||||||
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
|
||||||
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
|
||||||
import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
import org.mifosplatform.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
|
||||||
import org.mifosplatform.portfolio.savings.api.SavingsApiConstants;
|
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountDataValidator;
|
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDataValidator;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDataValidator;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionRepository;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionRepository;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
|
import org.mifosplatform.portfolio.savings.domain.SavingsHelper;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository;
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements SavingsAccountWritePlatformService {
|
public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements SavingsAccountWritePlatformService {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SavingsAccountWritePlatformServiceJpaRepositoryImpl.class);
|
|
||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final SavingsAccountRepositoryWrapper savingAccountRepository;
|
private final SavingsAccountRepositoryWrapper savingAccountRepository;
|
||||||
private final SavingsAccountTransactionRepository savingsAccountTransactionRepository;
|
private final SavingsAccountTransactionRepository savingsAccountTransactionRepository;
|
||||||
private final SavingsAccountAssembler savingAccountAssembler;
|
private final SavingsAccountAssembler savingAccountAssembler;
|
||||||
private final SavingsAccountDataValidator savingsAccountDataValidator;
|
|
||||||
private final SavingsAccountTransactionDataValidator savingsAccountTransactionDataValidator;
|
private final SavingsAccountTransactionDataValidator savingsAccountTransactionDataValidator;
|
||||||
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
|
||||||
private final ClientRepositoryWrapper clientRepository;
|
|
||||||
private final GroupRepository groupRepository;
|
|
||||||
private final SavingsProductRepository savingsProductRepository;
|
|
||||||
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
private final PaymentDetailWritePlatformService paymentDetailWritePlatformService;
|
||||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper;
|
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper;
|
||||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
|
|
||||||
|
private final SavingsHelper savingsHelper = new SavingsHelper();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
final SavingsAccountRepositoryWrapper savingAccountRepository,
|
final SavingsAccountRepositoryWrapper savingAccountRepository,
|
||||||
final SavingsAccountTransactionRepository savingsAccountTransactionRepository,
|
final SavingsAccountTransactionRepository savingsAccountTransactionRepository,
|
||||||
final SavingsAccountAssembler savingAccountAssembler, final SavingsAccountDataValidator savingsAccountDataValidator,
|
final SavingsAccountAssembler savingAccountAssembler,
|
||||||
final SavingsAccountTransactionDataValidator savingsAccountTransactionDataValidator,
|
final SavingsAccountTransactionDataValidator savingsAccountTransactionDataValidator,
|
||||||
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final ClientRepositoryWrapper clientRepository,
|
|
||||||
final GroupRepository groupRepository, final SavingsProductRepository savingsProductRepository,
|
|
||||||
final PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
final PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||||
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper,
|
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper,
|
||||||
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
||||||
@@ -87,184 +68,29 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
||||||
this.savingAccountAssembler = savingAccountAssembler;
|
this.savingAccountAssembler = savingAccountAssembler;
|
||||||
this.savingsAccountTransactionDataValidator = savingsAccountTransactionDataValidator;
|
this.savingsAccountTransactionDataValidator = savingsAccountTransactionDataValidator;
|
||||||
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
|
||||||
this.savingsAccountDataValidator = savingsAccountDataValidator;
|
|
||||||
this.clientRepository = clientRepository;
|
|
||||||
this.groupRepository = groupRepository;
|
|
||||||
this.savingsProductRepository = savingsProductRepository;
|
|
||||||
this.paymentDetailWritePlatformService = paymentDetailWritePlatformService;
|
this.paymentDetailWritePlatformService = paymentDetailWritePlatformService;
|
||||||
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
||||||
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Guaranteed to throw an exception no matter what the data integrity issue
|
|
||||||
* is.
|
|
||||||
*/
|
|
||||||
private void handleDataIntegrityIssues(final JsonCommand command, final DataAccessException dve) {
|
|
||||||
|
|
||||||
final StringBuilder errorCodeBuilder = new StringBuilder("error.msg.").append(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
|
||||||
|
|
||||||
final Throwable realCause = dve.getMostSpecificCause();
|
|
||||||
if (realCause.getMessage().contains("sa_account_no_UNIQUE")) {
|
|
||||||
final String accountNo = command.stringValueOfParameterNamed("accountNo");
|
|
||||||
errorCodeBuilder.append(".duplicate.accountNo");
|
|
||||||
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Savings account with accountNo " + accountNo
|
|
||||||
+ " already exists", "accountNo", accountNo);
|
|
||||||
|
|
||||||
} else if (realCause.getMessage().contains("sa_external_id_UNIQUE")) {
|
|
||||||
|
|
||||||
final String externalId = command.stringValueOfParameterNamed("externalId");
|
|
||||||
errorCodeBuilder.append(".duplicate.externalId");
|
|
||||||
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Savings account with externalId " + externalId
|
|
||||||
+ " already exists", "externalId", externalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorCodeBuilder.append(".unknown.data.integrity.issue");
|
|
||||||
logger.error(dve.getMessage(), dve);
|
|
||||||
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Unknown data integrity issue with savings account.");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public CommandProcessingResult createSavingAccount(final JsonCommand command) {
|
|
||||||
try {
|
|
||||||
this.context.authenticatedUser();
|
|
||||||
this.savingsAccountDataValidator.validateForCreate(command.json());
|
|
||||||
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
|
||||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(command, existingTransactionIds,
|
|
||||||
existingReversedTransactionIds);
|
|
||||||
this.savingAccountRepository.save(account);
|
|
||||||
|
|
||||||
if (account.isAccountNumberRequiresAutoGeneration()) {
|
|
||||||
final AccountNumberGenerator accountNoGenerator = this.accountIdentifierGeneratorFactory
|
|
||||||
.determineLoanAccountNoGenerator(account.getId());
|
|
||||||
account.updateAccountNo(accountNoGenerator.generate());
|
|
||||||
|
|
||||||
this.savingAccountRepository.save(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
|
||||||
|
|
||||||
final Long savingsId = account.getId();
|
|
||||||
return new CommandProcessingResultBuilder() //
|
|
||||||
.withCommandId(command.commandId()) //
|
|
||||||
.withEntityId(savingsId) //
|
|
||||||
.withOfficeId(account.officeId()) //
|
|
||||||
.withClientId(account.clientId()) //
|
|
||||||
.withGroupId(account.groupId()) //
|
|
||||||
.withSavingsId(savingsId) //
|
|
||||||
.build();
|
|
||||||
} catch (DataAccessException dve) {
|
|
||||||
handleDataIntegrityIssues(command, dve);
|
|
||||||
return CommandProcessingResult.empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public CommandProcessingResult updateSavingAccount(final Long savingsId, final JsonCommand command) {
|
|
||||||
try {
|
|
||||||
this.context.authenticatedUser();
|
|
||||||
this.savingsAccountDataValidator.validateForUpdate(command.json());
|
|
||||||
|
|
||||||
final Map<String, Object> changes = new LinkedHashMap<String, Object>(20);
|
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
|
||||||
|
|
||||||
account.update(command, changes);
|
|
||||||
|
|
||||||
if (!changes.isEmpty()) {
|
|
||||||
|
|
||||||
if (changes.containsKey(SavingsApiConstants.clientIdParamName)) {
|
|
||||||
final Long clientId = command.longValueOfParameterNamed(SavingsApiConstants.clientIdParamName);
|
|
||||||
if (clientId != null) {
|
|
||||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
|
||||||
account.update(client);
|
|
||||||
} else {
|
|
||||||
final Client client = null;
|
|
||||||
account.update(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changes.containsKey(SavingsApiConstants.groupIdParamName)) {
|
|
||||||
final Long groupId = command.longValueOfParameterNamed(SavingsApiConstants.groupIdParamName);
|
|
||||||
if (groupId != null) {
|
|
||||||
final Group group = this.groupRepository.findOne(groupId);
|
|
||||||
if (group == null) { throw new GroupNotFoundException(groupId); }
|
|
||||||
account.update(group);
|
|
||||||
} else {
|
|
||||||
final Group group = null;
|
|
||||||
account.update(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changes.containsKey(SavingsApiConstants.productIdParamName)) {
|
|
||||||
final Long productId = command.longValueOfParameterNamed(SavingsApiConstants.productIdParamName);
|
|
||||||
final SavingsProduct product = this.savingsProductRepository.findOne(productId);
|
|
||||||
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
|
||||||
|
|
||||||
account.update(product);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.savingAccountRepository.saveAndFlush(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
|
||||||
.withCommandId(command.commandId()) //
|
|
||||||
.withEntityId(savingsId) //
|
|
||||||
.withOfficeId(account.officeId()) //
|
|
||||||
.withClientId(account.clientId()) //
|
|
||||||
.withGroupId(account.groupId()) //
|
|
||||||
.withSavingsId(savingsId) //
|
|
||||||
.with(changes) //
|
|
||||||
.build();
|
|
||||||
} catch (DataAccessException dve) {
|
|
||||||
handleDataIntegrityIssues(command, dve);
|
|
||||||
return new CommandProcessingResult(Long.valueOf(-1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public CommandProcessingResult deleteSavingAccount(final Long savingsId) {
|
|
||||||
|
|
||||||
this.context.authenticatedUser();
|
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
|
||||||
|
|
||||||
this.savingAccountRepository.delete(account);
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
|
||||||
.withEntityId(savingsId) //
|
|
||||||
.withOfficeId(account.officeId()) //
|
|
||||||
.withClientId(account.clientId()) //
|
|
||||||
.withGroupId(account.groupId()) //
|
|
||||||
.withSavingsId(savingsId) //
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult activate(final Long savingsId, final JsonCommand command) {
|
public CommandProcessingResult activate(final Long savingsId, final JsonCommand command) {
|
||||||
|
|
||||||
this.context.authenticatedUser();
|
final AppUser user = this.context.authenticatedUser();
|
||||||
|
|
||||||
this.savingsAccountTransactionDataValidator.validateActivation(command);
|
this.savingsAccountTransactionDataValidator.validateActivation(command);
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final Locale locale = command.extractLocale();
|
|
||||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
|
||||||
final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate");
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
account.activate(fmt, activationDate, existingReversedTransactionIds, existingReversedTransactionIds);
|
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant(),
|
||||||
|
existingReversedTransactionIds, existingReversedTransactionIds);
|
||||||
this.savingAccountRepository.save(account);
|
if (!changes.isEmpty()) {
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
}
|
||||||
|
|
||||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
@@ -274,6 +100,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.withClientId(account.clientId()) //
|
.withClientId(account.clientId()) //
|
||||||
.withGroupId(account.groupId()) //
|
.withGroupId(account.groupId()) //
|
||||||
.withSavingsId(savingsId) //
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +112,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
|
|
||||||
this.savingsAccountTransactionDataValidator.validate(command);
|
this.savingsAccountTransactionDataValidator.validate(command);
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final Locale locale = command.extractLocale();
|
final Locale locale = command.extractLocale();
|
||||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||||
@@ -298,8 +125,18 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
|
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
|
||||||
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||||
|
|
||||||
|
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||||
final SavingsAccountTransaction deposit = account.deposit(fmt, transactionDate, transactionAmount, existingTransactionIds,
|
final SavingsAccountTransaction deposit = account.deposit(fmt, transactionDate, transactionAmount, existingTransactionIds,
|
||||||
existingReversedTransactionIds, paymentDetail);
|
existingReversedTransactionIds, paymentDetail);
|
||||||
|
|
||||||
|
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.postInterest(this.savingsHelper, mc, today, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
} else {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.calculateInterestUsing(this.savingsHelper, mc, today);
|
||||||
|
}
|
||||||
|
|
||||||
final Long transactionId = saveTransactionToGenerateTransactionId(deposit);
|
final Long transactionId = saveTransactionToGenerateTransactionId(deposit);
|
||||||
|
|
||||||
this.savingAccountRepository.save(account);
|
this.savingAccountRepository.save(account);
|
||||||
@@ -329,7 +166,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
|
|
||||||
this.savingsAccountTransactionDataValidator.validate(command);
|
this.savingsAccountTransactionDataValidator.validate(command);
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||||
@@ -342,8 +179,18 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
|
final Map<String, Object> changes = new LinkedHashMap<String, Object>();
|
||||||
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
PaymentDetail paymentDetail = paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||||
|
|
||||||
|
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||||
final SavingsAccountTransaction withdrawal = account.withdraw(fmt, transactionDate, transactionAmount, existingTransactionIds,
|
final SavingsAccountTransaction withdrawal = account.withdraw(fmt, transactionDate, transactionAmount, existingTransactionIds,
|
||||||
existingReversedTransactionIds, paymentDetail);
|
existingReversedTransactionIds, paymentDetail);
|
||||||
|
|
||||||
|
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.postInterest(this.savingsHelper, mc, today, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
} else {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.calculateInterestUsing(this.savingsHelper, mc, today);
|
||||||
|
}
|
||||||
|
|
||||||
final Long transactionId = saveTransactionToGenerateTransactionId(withdrawal);
|
final Long transactionId = saveTransactionToGenerateTransactionId(withdrawal);
|
||||||
this.savingAccountRepository.save(account);
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
@@ -363,7 +210,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult applyAnnualFee(final Long savingsId) {
|
public CommandProcessingResult applyAnnualFee(final Long savingsId) {
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final LocalDate transactionDate = LocalDate.now();
|
final LocalDate transactionDate = LocalDate.now();
|
||||||
|
|
||||||
@@ -372,8 +219,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final SavingsAccountTransaction annualFee = account.addAnnualFee(fmt, transactionDate, existingTransactionIds,
|
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||||
existingReversedTransactionIds);
|
final SavingsAccountTransaction annualFee = account.addAnnualFee(this.savingsHelper, mc, fmt, transactionDate,
|
||||||
|
existingTransactionIds, existingReversedTransactionIds);
|
||||||
final Long transactionId = saveTransactionToGenerateTransactionId(annualFee);
|
final Long transactionId = saveTransactionToGenerateTransactionId(annualFee);
|
||||||
this.savingAccountRepository.save(account);
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
@@ -388,14 +236,19 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult calculateInterest(final Long savingsId, final JsonCommand command) {
|
public CommandProcessingResult calculateInterest(final Long savingsId) {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
account.calculateInterest(today);
|
|
||||||
|
final MathContext mc = new MathContext(15, RoundingMode.HALF_EVEN);
|
||||||
|
|
||||||
|
account.calculateInterestUsing(this.savingsHelper, mc, today);
|
||||||
|
|
||||||
this.savingAccountRepository.save(account);
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
@@ -409,15 +262,17 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult postInterest(final Long savingsId, final JsonCommand command) {
|
public CommandProcessingResult postInterest(final Long savingsId) {
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
account.postInterest(today, existingTransactionIds, existingReversedTransactionIds);
|
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||||
|
|
||||||
|
account.postInterest(this.savingsHelper, mc, today, existingTransactionIds, existingReversedTransactionIds);
|
||||||
this.savingAccountRepository.save(account);
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
|
||||||
|
public interface SavingsApplicationProcessWritePlatformService {
|
||||||
|
|
||||||
|
CommandProcessingResult submitApplication(JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult modifyApplication(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult deleteApplication(Long savingsId);
|
||||||
|
|
||||||
|
CommandProcessingResult approveApplication(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult undoApplicationApproval(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult rejectApplication(Long savingsId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult applicantWithdrawsFromApplication(Long savingsId, JsonCommand command);
|
||||||
|
}
|
||||||
+382
@@ -0,0 +1,382 @@
|
|||||||
|
/**
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||||
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||||
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
|
||||||
|
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
|
||||||
|
import org.mifosplatform.portfolio.client.domain.Client;
|
||||||
|
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
|
||||||
|
import org.mifosplatform.portfolio.group.domain.Group;
|
||||||
|
import org.mifosplatform.portfolio.group.domain.GroupRepository;
|
||||||
|
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
|
||||||
|
import org.mifosplatform.portfolio.note.domain.Note;
|
||||||
|
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
|
||||||
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountDataValidator;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
|
||||||
|
import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository;
|
||||||
|
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||||
|
import org.mifosplatform.useradministration.domain.AppUser;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl implements SavingsApplicationProcessWritePlatformService {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.class);
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final SavingsAccountRepositoryWrapper savingAccountRepository;
|
||||||
|
private final SavingsAccountAssembler savingAccountAssembler;
|
||||||
|
private final SavingsAccountDataValidator savingsAccountDataValidator;
|
||||||
|
private final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory;
|
||||||
|
private final ClientRepositoryWrapper clientRepository;
|
||||||
|
private final GroupRepository groupRepository;
|
||||||
|
private final SavingsProductRepository savingsProductRepository;
|
||||||
|
private final NoteRepository noteRepository;
|
||||||
|
private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator;
|
||||||
|
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper;
|
||||||
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
|
final SavingsAccountRepositoryWrapper savingAccountRepository, final SavingsAccountAssembler savingAccountAssembler,
|
||||||
|
final SavingsAccountDataValidator savingsAccountDataValidator,
|
||||||
|
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final ClientRepositoryWrapper clientRepository,
|
||||||
|
final GroupRepository groupRepository, final SavingsProductRepository savingsProductRepository,
|
||||||
|
final NoteRepository noteRepository,
|
||||||
|
final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator,
|
||||||
|
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper,
|
||||||
|
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
||||||
|
this.context = context;
|
||||||
|
this.savingAccountRepository = savingAccountRepository;
|
||||||
|
this.savingAccountAssembler = savingAccountAssembler;
|
||||||
|
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
|
||||||
|
this.savingsAccountDataValidator = savingsAccountDataValidator;
|
||||||
|
this.clientRepository = clientRepository;
|
||||||
|
this.groupRepository = groupRepository;
|
||||||
|
this.savingsProductRepository = savingsProductRepository;
|
||||||
|
this.noteRepository = noteRepository;
|
||||||
|
this.savingsAccountApplicationTransitionApiJsonValidator = savingsAccountApplicationTransitionApiJsonValidator;
|
||||||
|
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
||||||
|
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guaranteed to throw an exception no matter what the data integrity issue
|
||||||
|
* is.
|
||||||
|
*/
|
||||||
|
private void handleDataIntegrityIssues(final JsonCommand command, final DataAccessException dve) {
|
||||||
|
|
||||||
|
final StringBuilder errorCodeBuilder = new StringBuilder("error.msg.").append(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
final Throwable realCause = dve.getMostSpecificCause();
|
||||||
|
if (realCause.getMessage().contains("sa_account_no_UNIQUE")) {
|
||||||
|
final String accountNo = command.stringValueOfParameterNamed("accountNo");
|
||||||
|
errorCodeBuilder.append(".duplicate.accountNo");
|
||||||
|
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Savings account with accountNo " + accountNo
|
||||||
|
+ " already exists", "accountNo", accountNo);
|
||||||
|
|
||||||
|
} else if (realCause.getMessage().contains("sa_external_id_UNIQUE")) {
|
||||||
|
|
||||||
|
final String externalId = command.stringValueOfParameterNamed("externalId");
|
||||||
|
errorCodeBuilder.append(".duplicate.externalId");
|
||||||
|
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Savings account with externalId " + externalId
|
||||||
|
+ " already exists", "externalId", externalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCodeBuilder.append(".unknown.data.integrity.issue");
|
||||||
|
logger.error(dve.getMessage(), dve);
|
||||||
|
throw new PlatformDataIntegrityException(errorCodeBuilder.toString(), "Unknown data integrity issue with savings account.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult submitApplication(final JsonCommand command) {
|
||||||
|
try {
|
||||||
|
this.savingsAccountDataValidator.validateForSubmit(command.json());
|
||||||
|
|
||||||
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(command);
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
|
if (account.isAccountNumberRequiresAutoGeneration()) {
|
||||||
|
final AccountNumberGenerator accountNoGenerator = this.accountIdentifierGeneratorFactory
|
||||||
|
.determineSavingsAccountNoGenerator(account.getId());
|
||||||
|
account.updateAccountNo(accountNoGenerator.generate());
|
||||||
|
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
|
||||||
|
final Long savingsId = account.getId();
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(account.officeId()) //
|
||||||
|
.withClientId(account.clientId()) //
|
||||||
|
.withGroupId(account.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.build();
|
||||||
|
} catch (DataAccessException dve) {
|
||||||
|
handleDataIntegrityIssues(command, dve);
|
||||||
|
return CommandProcessingResult.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult modifyApplication(final Long savingsId, final JsonCommand command) {
|
||||||
|
try {
|
||||||
|
this.savingsAccountDataValidator.validateForUpdate(command.json());
|
||||||
|
|
||||||
|
final Map<String, Object> changes = new LinkedHashMap<String, Object>(20);
|
||||||
|
|
||||||
|
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
||||||
|
|
||||||
|
account.update(command, changes);
|
||||||
|
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
|
||||||
|
if (changes.containsKey(SavingsApiConstants.clientIdParamName)) {
|
||||||
|
final Long clientId = command.longValueOfParameterNamed(SavingsApiConstants.clientIdParamName);
|
||||||
|
if (clientId != null) {
|
||||||
|
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||||
|
account.update(client);
|
||||||
|
} else {
|
||||||
|
final Client client = null;
|
||||||
|
account.update(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes.containsKey(SavingsApiConstants.groupIdParamName)) {
|
||||||
|
final Long groupId = command.longValueOfParameterNamed(SavingsApiConstants.groupIdParamName);
|
||||||
|
if (groupId != null) {
|
||||||
|
final Group group = this.groupRepository.findOne(groupId);
|
||||||
|
if (group == null) { throw new GroupNotFoundException(groupId); }
|
||||||
|
account.update(group);
|
||||||
|
} else {
|
||||||
|
final Group group = null;
|
||||||
|
account.update(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changes.containsKey(SavingsApiConstants.productIdParamName)) {
|
||||||
|
final Long productId = command.longValueOfParameterNamed(SavingsApiConstants.productIdParamName);
|
||||||
|
final SavingsProduct product = this.savingsProductRepository.findOne(productId);
|
||||||
|
if (product == null) { throw new SavingsProductNotFoundException(productId); }
|
||||||
|
|
||||||
|
account.update(product);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.savingAccountRepository.saveAndFlush(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(account.officeId()) //
|
||||||
|
.withClientId(account.clientId()) //
|
||||||
|
.withGroupId(account.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
} catch (DataAccessException dve) {
|
||||||
|
handleDataIntegrityIssues(command, dve);
|
||||||
|
return new CommandProcessingResult(Long.valueOf(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult deleteApplication(final Long savingsId) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
|
final SavingsAccount account = this.savingAccountRepository.findOneWithNotFoundDetection(savingsId);
|
||||||
|
|
||||||
|
List<Note> relatedNotes = this.noteRepository.findBySavingsAccountId(savingsId);
|
||||||
|
this.noteRepository.deleteInBatch(relatedNotes);
|
||||||
|
|
||||||
|
this.savingAccountRepository.delete(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(account.officeId()) //
|
||||||
|
.withClientId(account.clientId()) //
|
||||||
|
.withGroupId(account.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult approveApplication(final Long savingsId, final JsonCommand command) {
|
||||||
|
|
||||||
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
this.savingsAccountApplicationTransitionApiJsonValidator.validateApproval(command.json());
|
||||||
|
|
||||||
|
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
|
final Map<String, Object> changes = savingsAccount.approveApplication(currentUser, command, DateUtils.getLocalDateOfTenant());
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
this.savingAccountRepository.save(savingsAccount);
|
||||||
|
|
||||||
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
|
Note note = Note.savingNote(savingsAccount, noteText);
|
||||||
|
changes.put("note", noteText);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(savingsAccount.officeId()) //
|
||||||
|
.withClientId(savingsAccount.clientId()) //
|
||||||
|
.withGroupId(savingsAccount.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult undoApplicationApproval(final Long savingsId, final JsonCommand command) {
|
||||||
|
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
this.savingsAccountApplicationTransitionApiJsonValidator.validateForUndo(command.json());
|
||||||
|
|
||||||
|
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
|
final Map<String, Object> changes = savingsAccount.undoApplicationApproval();
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
this.savingAccountRepository.save(savingsAccount);
|
||||||
|
|
||||||
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
|
Note note = Note.savingNote(savingsAccount, noteText);
|
||||||
|
changes.put("note", noteText);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(savingsAccount.officeId()) //
|
||||||
|
.withClientId(savingsAccount.clientId()) //
|
||||||
|
.withGroupId(savingsAccount.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult rejectApplication(final Long savingsId, final JsonCommand command) {
|
||||||
|
|
||||||
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
this.savingsAccountApplicationTransitionApiJsonValidator.validateRejection(command.json());
|
||||||
|
|
||||||
|
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
|
final Map<String, Object> changes = savingsAccount.rejectApplication(currentUser, command, DateUtils.getLocalDateOfTenant());
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
this.savingAccountRepository.save(savingsAccount);
|
||||||
|
|
||||||
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
|
Note note = Note.savingNote(savingsAccount, noteText);
|
||||||
|
changes.put("note", noteText);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(savingsAccount.officeId()) //
|
||||||
|
.withClientId(savingsAccount.clientId()) //
|
||||||
|
.withGroupId(savingsAccount.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult applicantWithdrawsFromApplication(final Long savingsId, final JsonCommand command) {
|
||||||
|
final AppUser currentUser = context.authenticatedUser();
|
||||||
|
|
||||||
|
this.savingsAccountApplicationTransitionApiJsonValidator.validateApplicantWithdrawal(command.json());
|
||||||
|
|
||||||
|
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||||
|
|
||||||
|
final Map<String, Object> changes = savingsAccount.applicantWithdrawsFromApplication(currentUser, command,
|
||||||
|
DateUtils.getLocalDateOfTenant());
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
this.savingAccountRepository.save(savingsAccount);
|
||||||
|
|
||||||
|
final String noteText = command.stringValueOfParameterNamed("note");
|
||||||
|
if (StringUtils.isNotBlank(noteText)) {
|
||||||
|
Note note = Note.savingNote(savingsAccount, noteText);
|
||||||
|
changes.put("note", noteText);
|
||||||
|
this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(savingsId) //
|
||||||
|
.withOfficeId(savingsAccount.officeId()) //
|
||||||
|
.withClientId(savingsAccount.clientId()) //
|
||||||
|
.withGroupId(savingsAccount.groupId()) //
|
||||||
|
.withSavingsId(savingsId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postJournalEntries(final SavingsAccount savingsAccount, final List<Long> existingTransactionIds,
|
||||||
|
final List<Long> existingReversedTransactionIds) {
|
||||||
|
|
||||||
|
final MonetaryCurrency currency = savingsAccount.getCurrency();
|
||||||
|
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepositoryWrapper.findOneWithNotFoundDetection(currency);
|
||||||
|
|
||||||
|
final Map<String, Object> accountingBridgeData = savingsAccount.deriveAccountingBridgeData(applicationCurrency.toData(),
|
||||||
|
existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
journalEntryWritePlatformService.createJournalEntriesForSavings(accountingBridgeData);
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-17
@@ -10,12 +10,12 @@ import java.util.Collection;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsWithdrawalFeesType;
|
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -47,13 +47,13 @@ public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownRe
|
|||||||
public Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions() {
|
public Collection<EnumOptionData> retrieveCompoundingInterestPeriodTypeOptions() {
|
||||||
List<EnumOptionData> allowedOptions = Arrays.asList( //
|
List<EnumOptionData> allowedOptions = Arrays.asList( //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY), //
|
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.DAILY), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.WEEKLY), //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.WEEKLY), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BIWEEKLY), //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BIWEEKLY), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.MONTHLY), //
|
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.MONTHLY)
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.QUATERLY), //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.QUATERLY), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BI_ANNUAL), //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BI_ANNUAL), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL), //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL), //
|
||||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST) //
|
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST) //
|
||||||
);
|
);
|
||||||
|
|
||||||
return allowedOptions;
|
return allowedOptions;
|
||||||
@@ -62,10 +62,9 @@ public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownRe
|
|||||||
@Override
|
@Override
|
||||||
public Collection<EnumOptionData> retrieveInterestPostingPeriodTypeOptions() {
|
public Collection<EnumOptionData> retrieveInterestPostingPeriodTypeOptions() {
|
||||||
List<EnumOptionData> allowedOptions = Arrays.asList( //
|
List<EnumOptionData> allowedOptions = Arrays.asList( //
|
||||||
SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType.MONTHLY), //
|
SavingsEnumerations.interestPostingPeriodType(SavingsPostingInterestPeriodType.MONTHLY), //
|
||||||
SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType.QUATERLY), //
|
SavingsEnumerations.interestPostingPeriodType(SavingsPostingInterestPeriodType.QUATERLY), //
|
||||||
SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType.BI_ANNUAL), //
|
SavingsEnumerations.interestPostingPeriodType(SavingsPostingInterestPeriodType.ANNUAL) //
|
||||||
SavingsEnumerations.interestPostingPeriodType(SavingsInterestPostingPeriodType.ANNUAL) //
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return allowedOptions;
|
return allowedOptions;
|
||||||
|
|||||||
+92
-54
@@ -6,16 +6,16 @@
|
|||||||
package org.mifosplatform.portfolio.savings.service;
|
package org.mifosplatform.portfolio.savings.service;
|
||||||
|
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsAccountTransactionType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
|
import org.mifosplatform.portfolio.savings.SavingsWithdrawalFeesType;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
|
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransactionType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
|
||||||
import org.mifosplatform.portfolio.savings.domain.SavingsWithdrawalFeesType;
|
|
||||||
|
|
||||||
public class SavingsEnumerations {
|
public class SavingsEnumerations {
|
||||||
|
|
||||||
@@ -94,59 +94,81 @@ public class SavingsEnumerations {
|
|||||||
|
|
||||||
public static SavingsAccountStatusEnumData status(final SavingsAccountStatusType type) {
|
public static SavingsAccountStatusEnumData status(final SavingsAccountStatusType type) {
|
||||||
|
|
||||||
|
final boolean submittedAndPendingApproval = type.isSubmittedAndPendingApproval();
|
||||||
|
final boolean isApproved = type.isApproved();
|
||||||
|
final boolean isRejected = type.isRejected();
|
||||||
|
final boolean isWithdrawnByApplicant = type.isApplicationWithdrawnByApplicant();
|
||||||
|
final boolean isActive = type.isActive();
|
||||||
|
final boolean isClosed = type.isClosed();
|
||||||
|
|
||||||
SavingsAccountStatusEnumData optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(),
|
SavingsAccountStatusEnumData optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(),
|
||||||
SavingsAccountStatusType.INVALID.getCode(), "Invalid", false, false, false);
|
SavingsAccountStatusType.INVALID.getCode(), "Invalid", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INVALID:
|
case INVALID:
|
||||||
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(),
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(),
|
||||||
SavingsAccountStatusType.INVALID.getCode(), "Invalid", type.isUnactivated(), type.isActive(), type.isClosed());
|
SavingsAccountStatusType.INVALID.getCode(), "Invalid", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
break;
|
break;
|
||||||
case UNACTIVATED:
|
case SUBMITTED_AND_PENDING_APPROVAL:
|
||||||
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.UNACTIVATED.getValue().longValue(),
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue()
|
||||||
SavingsAccountStatusType.UNACTIVATED.getCode(), "Unactivated", type.isUnactivated(), type.isActive(),
|
.longValue(), SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getCode(), "Submitted and pending approval",
|
||||||
type.isClosed());
|
submittedAndPendingApproval, isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed);
|
||||||
|
break;
|
||||||
|
case REJECTED:
|
||||||
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.REJECTED.getValue().longValue(),
|
||||||
|
SavingsAccountStatusType.REJECTED.getCode(), "Rejected", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
|
break;
|
||||||
|
case WITHDRAWN_BY_APPLICANT:
|
||||||
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT.getValue().longValue(),
|
||||||
|
SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT.getCode(), "Withdrawn by applicant", submittedAndPendingApproval,
|
||||||
|
isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed);
|
||||||
|
break;
|
||||||
|
case APPROVED:
|
||||||
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.APPROVED.getValue().longValue(),
|
||||||
|
SavingsAccountStatusType.APPROVED.getCode(), "Approved", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
break;
|
break;
|
||||||
case ACTIVE:
|
case ACTIVE:
|
||||||
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.ACTIVE.getValue().longValue(),
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.ACTIVE.getValue().longValue(),
|
||||||
SavingsAccountStatusType.ACTIVE.getCode(), "Active", type.isUnactivated(), type.isActive(), type.isClosed());
|
SavingsAccountStatusType.ACTIVE.getCode(), "Active", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
break;
|
break;
|
||||||
case CLOSED:
|
case CLOSED:
|
||||||
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.CLOSED.getValue().longValue(),
|
optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.CLOSED.getValue().longValue(),
|
||||||
SavingsAccountStatusType.CLOSED.getCode(), "Closed", type.isUnactivated(), type.isActive(), type.isClosed());
|
SavingsAccountStatusType.CLOSED.getCode(), "Closed", submittedAndPendingApproval, isApproved, isRejected,
|
||||||
|
isWithdrawnByApplicant, isActive, isClosed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return optionData;
|
return optionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EnumOptionData interestPostingPeriodType(final Integer type) {
|
public static EnumOptionData interestPostingPeriodType(final Integer type) {
|
||||||
return interestPostingPeriodType(SavingsInterestPostingPeriodType.fromInt(type));
|
return interestPostingPeriodType(SavingsPostingInterestPeriodType.fromInt(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EnumOptionData interestPostingPeriodType(final SavingsInterestPostingPeriodType type) {
|
public static EnumOptionData interestPostingPeriodType(final SavingsPostingInterestPeriodType type) {
|
||||||
|
|
||||||
final String codePrefix = "savings.interest.posting.period.";
|
final String codePrefix = "savings.interest.posting.period.";
|
||||||
EnumOptionData optionData = new EnumOptionData(SavingsInterestPostingPeriodType.INVALID.getValue().longValue(),
|
EnumOptionData optionData = new EnumOptionData(SavingsPostingInterestPeriodType.INVALID.getValue().longValue(),
|
||||||
SavingsInterestPostingPeriodType.INVALID.getCode(), "Invalid");
|
SavingsPostingInterestPeriodType.INVALID.getCode(), "Invalid");
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INVALID:
|
case INVALID:
|
||||||
break;
|
break;
|
||||||
case MONTHLY:
|
case MONTHLY:
|
||||||
optionData = new EnumOptionData(SavingsInterestPostingPeriodType.MONTHLY.getValue().longValue(), codePrefix
|
optionData = new EnumOptionData(SavingsPostingInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
|
||||||
+ SavingsInterestPostingPeriodType.MONTHLY.getCode(), "Monthly");
|
+ SavingsPostingInterestPeriodType.MONTHLY.getCode(), "Monthly");
|
||||||
break;
|
break;
|
||||||
case QUATERLY:
|
case QUATERLY:
|
||||||
optionData = new EnumOptionData(SavingsInterestPostingPeriodType.QUATERLY.getValue().longValue(), codePrefix
|
optionData = new EnumOptionData(SavingsPostingInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix
|
||||||
+ SavingsInterestPostingPeriodType.QUATERLY.getCode(), "Quarterly");
|
+ SavingsPostingInterestPeriodType.QUATERLY.getCode(), "Quarterly");
|
||||||
break;
|
|
||||||
case BI_ANNUAL:
|
|
||||||
optionData = new EnumOptionData(SavingsInterestPostingPeriodType.BI_ANNUAL.getValue().longValue(), codePrefix
|
|
||||||
+ SavingsInterestPostingPeriodType.BI_ANNUAL.getCode(), "Semi-Annual");
|
|
||||||
break;
|
break;
|
||||||
case ANNUAL:
|
case ANNUAL:
|
||||||
optionData = new EnumOptionData(SavingsInterestPostingPeriodType.ANNUAL.getValue().longValue(), codePrefix
|
optionData = new EnumOptionData(SavingsPostingInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix
|
||||||
+ SavingsInterestPostingPeriodType.ANNUAL.getCode(), "Annually");
|
+ SavingsPostingInterestPeriodType.ANNUAL.getCode(), "Annually");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,35 +192,51 @@ public class SavingsEnumerations {
|
|||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.DAILY.getValue().longValue(), codePrefix
|
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.DAILY.getValue().longValue(), codePrefix
|
||||||
+ SavingsCompoundingInterestPeriodType.DAILY.getCode(), "Daily");
|
+ SavingsCompoundingInterestPeriodType.DAILY.getCode(), "Daily");
|
||||||
break;
|
break;
|
||||||
case WEEKLY:
|
// case WEEKLY:
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.WEEKLY.getValue().longValue(), codePrefix
|
// optionData = new
|
||||||
+ SavingsCompoundingInterestPeriodType.WEEKLY.getCode(), "Weekly");
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.WEEKLY.getValue().longValue(),
|
||||||
break;
|
// codePrefix
|
||||||
case BIWEEKLY:
|
// + SavingsCompoundingInterestPeriodType.WEEKLY.getCode(),
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BIWEEKLY.getValue().longValue(), codePrefix
|
// "Weekly");
|
||||||
+ SavingsCompoundingInterestPeriodType.BIWEEKLY.getCode(), "Bi-Weekly");
|
// break;
|
||||||
break;
|
// case BIWEEKLY:
|
||||||
|
// optionData = new
|
||||||
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.BIWEEKLY.getValue().longValue(),
|
||||||
|
// codePrefix
|
||||||
|
// + SavingsCompoundingInterestPeriodType.BIWEEKLY.getCode(),
|
||||||
|
// "Bi-Weekly");
|
||||||
|
// break;
|
||||||
case MONTHLY:
|
case MONTHLY:
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
|
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.MONTHLY.getValue().longValue(), codePrefix
|
||||||
+ SavingsCompoundingInterestPeriodType.MONTHLY.getCode(), "Monthly");
|
+ SavingsCompoundingInterestPeriodType.MONTHLY.getCode(), "Monthly");
|
||||||
break;
|
break;
|
||||||
case QUATERLY:
|
// case QUATERLY:
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.QUATERLY.getValue().longValue(), codePrefix
|
// optionData = new
|
||||||
+ SavingsCompoundingInterestPeriodType.QUATERLY.getCode(), "Quarterly");
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.QUATERLY.getValue().longValue(),
|
||||||
break;
|
// codePrefix
|
||||||
case BI_ANNUAL:
|
// + SavingsCompoundingInterestPeriodType.QUATERLY.getCode(),
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.BI_ANNUAL.getValue().longValue(), codePrefix
|
// "Quarterly");
|
||||||
+ SavingsCompoundingInterestPeriodType.BI_ANNUAL.getCode(), "Semi-Annual");
|
// break;
|
||||||
break;
|
// case BI_ANNUAL:
|
||||||
case ANNUAL:
|
// optionData = new
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.ANNUAL.getValue().longValue(), codePrefix
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.BI_ANNUAL.getValue().longValue(),
|
||||||
+ SavingsCompoundingInterestPeriodType.ANNUAL.getCode(), "Annually");
|
// codePrefix
|
||||||
break;
|
// + SavingsCompoundingInterestPeriodType.BI_ANNUAL.getCode(),
|
||||||
case NO_COMPOUNDING_SIMPLE_INTEREST:
|
// "Semi-Annual");
|
||||||
optionData = new EnumOptionData(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getValue().longValue(),
|
// break;
|
||||||
codePrefix + SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getCode(),
|
// case ANNUAL:
|
||||||
"No Compounding - Simple Interest");
|
// optionData = new
|
||||||
break;
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.ANNUAL.getValue().longValue(),
|
||||||
|
// codePrefix
|
||||||
|
// + SavingsCompoundingInterestPeriodType.ANNUAL.getCode(), "Annually");
|
||||||
|
// break;
|
||||||
|
// case NO_COMPOUNDING_SIMPLE_INTEREST:
|
||||||
|
// optionData = new
|
||||||
|
// EnumOptionData(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getValue().longValue(),
|
||||||
|
// codePrefix +
|
||||||
|
// SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST.getCode(),
|
||||||
|
// "No Compounding - Simple Interest");
|
||||||
|
// break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return optionData;
|
return optionData;
|
||||||
|
|||||||
+2
-1
@@ -24,7 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountingRuleParamName;
|
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements SavingsProductWritePlatformService {
|
public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements SavingsProductWritePlatformService {
|
||||||
|
|||||||
-1
@@ -205,5 +205,4 @@ public class ScheduledJobRunnerServiceImpl implements ScheduledJobRunnerService
|
|||||||
|
|
||||||
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + savingsIds.size());
|
logger.info(ThreadLocalContextUtil.getTenant().getName() + ": Results affected by update: " + savingsIds.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+13
-13
@@ -4,20 +4,20 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
|||||||
|
|
||||||
public class MonetaryCurrencyBuilder {
|
public class MonetaryCurrencyBuilder {
|
||||||
|
|
||||||
private String code = "XOF";
|
private String code = "XOF";
|
||||||
private int digitsAfterDecimal = 0;
|
private int digitsAfterDecimal = 0;
|
||||||
|
|
||||||
public MonetaryCurrency build() {
|
public MonetaryCurrency build() {
|
||||||
return new MonetaryCurrency(code, digitsAfterDecimal);
|
return new MonetaryCurrency(code, digitsAfterDecimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonetaryCurrencyBuilder withCode(String withCode) {
|
public MonetaryCurrencyBuilder withCode(final String withCode) {
|
||||||
this.code = withCode;
|
this.code = withCode;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonetaryCurrencyBuilder withDigitsAfterDecimal(int withDigitsAfterDecimal) {
|
public MonetaryCurrencyBuilder withDigitsAfterDecimal(final int withDigitsAfterDecimal) {
|
||||||
this.digitsAfterDecimal = withDigitsAfterDecimal;
|
this.digitsAfterDecimal = withDigitsAfterDecimal;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-15
@@ -7,20 +7,20 @@ import org.mifosplatform.organisation.monetary.domain.Money;
|
|||||||
|
|
||||||
public class MoneyBuilder {
|
public class MoneyBuilder {
|
||||||
|
|
||||||
private MonetaryCurrency currencyDetail = new MonetaryCurrencyBuilder().build();
|
private MonetaryCurrency currencyDetail = new MonetaryCurrencyBuilder().build();
|
||||||
private BigDecimal newAmount = BigDecimal.ZERO;
|
private BigDecimal newAmount = BigDecimal.ZERO;
|
||||||
|
|
||||||
public Money build() {
|
|
||||||
return Money.of(currencyDetail, newAmount);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MoneyBuilder with(MonetaryCurrency withDetail) {
|
public Money build() {
|
||||||
this.currencyDetail = withDetail;
|
return Money.of(currencyDetail, newAmount);
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
public MoneyBuilder with(final MonetaryCurrency withDetail) {
|
||||||
public MoneyBuilder with(String withAmount) {
|
this.currencyDetail = withDetail;
|
||||||
this.newAmount = BigDecimal.valueOf(Double.valueOf(withAmount));
|
return this;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
public MoneyBuilder with(final String withAmount) {
|
||||||
|
this.newAmount = BigDecimal.valueOf(Double.valueOf(withAmount));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user