MIFOSX-1055 - added standing instructions

This commit is contained in:
Pramod Nuthakki
2014-04-08 23:01:10 +05:30
parent b9bfced9c5
commit 209dd48031
58 changed files with 5396 additions and 461 deletions
+1479
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,126 @@
CREATE TABLE `m_account_transfer_details` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`from_office_id` BIGINT(20) NOT NULL,
`to_office_id` BIGINT(20) NOT NULL,
`from_client_id` BIGINT(20) NULL DEFAULT NULL,
`to_client_id` BIGINT(20) NULL DEFAULT NULL,
`from_savings_account_id` BIGINT(20) NULL DEFAULT NULL,
`to_savings_account_id` BIGINT(20) NULL DEFAULT NULL,
`from_loan_account_id` BIGINT(20) NULL DEFAULT NULL,
`to_loan_account_id` BIGINT(20) NULL DEFAULT NULL,
`transfer_type` SMALLINT(2) NULL DEFAULT NULL,
`from_savings_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`from_loan_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`to_savings_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`to_loan_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`is_reversed` TINYINT(1) NOT NULL,
`transaction_date` DATE NOT NULL,
`currency_code` VARCHAR(3) NOT NULL,
`currency_digits` SMALLINT(5) NOT NULL,
`currency_multiplesof` SMALLINT(5) NULL DEFAULT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`description` VARCHAR(200) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_m_account_transfer_details_from_office` (`from_office_id`),
INDEX `FK_m_account_transfer_details_to_office` (`to_office_id`),
INDEX `FK_m_account_transfer_details_from_client` (`from_client_id`),
INDEX `FK_m_account_transfer_details_to_client` (`to_client_id`),
INDEX `FK_m_account_transfer_details_from_savings_account` (`from_savings_account_id`),
INDEX `FK_m_account_transfer_details_to_savings_account` (`to_savings_account_id`),
INDEX `FK_m_account_transfer_details_from_loan_account` (`from_loan_account_id`),
INDEX `FK_m_account_transfer_details_to_loan_account` (`to_loan_account_id`),
CONSTRAINT `FK_m_account_transfer_details_from_client` FOREIGN KEY (`from_client_id`) REFERENCES `m_client` (`id`),
CONSTRAINT `FK_m_account_transfer_details_from_loan_account` FOREIGN KEY (`from_loan_account_id`) REFERENCES `m_loan` (`id`),
CONSTRAINT `FK_m_account_transfer_details_from_office` FOREIGN KEY (`from_office_id`) REFERENCES `m_office` (`id`),
CONSTRAINT `FK_m_account_transfer_details_from_savings_account` FOREIGN KEY (`from_savings_account_id`) REFERENCES `m_savings_account` (`id`),
CONSTRAINT `FK_m_account_transfer_details_to_client` FOREIGN KEY (`to_client_id`) REFERENCES `m_client` (`id`),
CONSTRAINT `FK_m_account_transfer_details_to_loan_account` FOREIGN KEY (`to_loan_account_id`) REFERENCES `m_loan` (`id`),
CONSTRAINT `FK_m_account_transfer_details_to_office` FOREIGN KEY (`to_office_id`) REFERENCES `m_office` (`id`),
CONSTRAINT `FK_m_account_transfer_details_to_savings_account` FOREIGN KEY (`to_savings_account_id`) REFERENCES `m_savings_account` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
CREATE TABLE `m_account_transfer_standing_instructions` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(250) NOT NULL,
`account_transfer_details_id` BIGINT(20) NOT NULL,
`priority` TINYINT(2) NOT NULL,
`status` TINYINT(2) NOT NULL,
`instruction_type` TINYINT(2) NOT NULL,
`amount` DECIMAL(19,6) NULL DEFAULT NULL,
`valid_from` DATE NOT NULL,
`valid_till` DATE NULL DEFAULT NULL,
`recurrence_type` TINYINT(1) NOT NULL,
`recurrence_frequency` SMALLINT(5) NULL DEFAULT NULL,
`recurrence_interval` SMALLINT(5) NULL DEFAULT NULL,
`recurrence_on_day` SMALLINT(2) NULL DEFAULT NULL,
`recurrence_on_month` SMALLINT(2) NULL DEFAULT NULL,
`last_run_date` DATE NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `name` (`name`),
INDEX `FK_m_standing_instructions_account_transfer_details` (`account_transfer_details_id`),
CONSTRAINT `FK_m_standing_instructions_account_transfer_details` FOREIGN KEY (`account_transfer_details_id`) REFERENCES `m_account_transfer_details` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
CREATE TABLE `m_account_transfer_transaction` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`account_transfer_details_id` BIGINT(20) NOT NULL,
`from_savings_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`from_loan_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`to_savings_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`to_loan_transaction_id` BIGINT(20) NULL DEFAULT NULL,
`is_reversed` TINYINT(1) NOT NULL,
`transaction_date` DATE NOT NULL,
`currency_code` VARCHAR(3) NOT NULL,
`currency_digits` SMALLINT(5) NOT NULL,
`currency_multiplesof` SMALLINT(5) NULL DEFAULT NULL,
`amount` DECIMAL(19,6) NOT NULL,
`description` VARCHAR(200) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_m_account_transfer_transaction_from_m_savings_transaction` (`from_savings_transaction_id`),
INDEX `FK_m_account_transfer_transaction_to_m_savings_transaction` (`to_savings_transaction_id`),
INDEX `FK_m_account_transfer_transaction_to_m_loan_transaction` (`to_loan_transaction_id`),
INDEX `FK_m_account_transfer_transaction_from_m_loan_transaction` (`from_loan_transaction_id`),
INDEX `FK_m_account_transfer_transaction_account_detail` (`account_transfer_details_id`),
CONSTRAINT `FK_m_account_transfer_transaction_account_detail` FOREIGN KEY (`account_transfer_details_id`) REFERENCES `m_account_transfer_details` (`id`),
CONSTRAINT `FK_m_account_transfer_transaction_from_m_loan_transaction` FOREIGN KEY (`from_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`),
CONSTRAINT `FK_m_account_transfer_transaction_from_m_savings_transaction` FOREIGN KEY (`from_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`),
CONSTRAINT `FK_m_account_transfer_transaction_to_m_loan_transaction` FOREIGN KEY (`to_loan_transaction_id`) REFERENCES `m_loan_transaction` (`id`),
CONSTRAINT `FK_m_account_transfer_transaction_to_m_savings_transaction` FOREIGN KEY (`to_savings_transaction_id`) REFERENCES `m_savings_account_transaction` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
INSERT INTO `m_account_transfer_details` (`from_office_id`, `to_office_id`, `from_client_id`, `to_client_id`, `from_savings_account_id`, `to_savings_account_id`, `from_loan_account_id`, `to_loan_account_id`, `from_savings_transaction_id`, `from_loan_transaction_id`, `to_savings_transaction_id`, `to_loan_transaction_id`, `is_reversed`, `transaction_date`, `currency_code`, `currency_digits`, `currency_multiplesof`, `amount`, `description`) select at.from_office_id,at.to_office_id,at.from_client_id,at.to_client_id,at.from_savings_account_id,at.to_savings_account_id,at.from_loan_account_id,at.to_loan_account_id,at.from_savings_transaction_id,at.from_loan_transaction_id,at.to_savings_transaction_id,at.to_loan_transaction_id,at.is_reversed,at.transaction_date,at.currency_code,at.currency_digits,at.currency_multiplesof,at.amount,at.description from m_savings_account_transfer at;
INSERT INTO `m_account_transfer_transaction` (`account_transfer_details_id`, `from_savings_transaction_id`, `from_loan_transaction_id`, `to_savings_transaction_id`, `to_loan_transaction_id`, `is_reversed`, `transaction_date`, `currency_code`, `currency_digits`, `currency_multiplesof`, `amount`, `description`) select ad.id,ad.from_savings_transaction_id,ad.from_loan_transaction_id,ad.to_savings_transaction_id,ad.to_loan_transaction_id,ad.is_reversed,ad.transaction_date,ad.currency_code,ad.currency_digits,ad.currency_multiplesof,ad.amount,ad.description from m_account_transfer_details ad;
ALTER TABLE `m_account_transfer_details`
DROP COLUMN `from_savings_transaction_id`,
DROP COLUMN `from_loan_transaction_id`,
DROP COLUMN `to_savings_transaction_id`,
DROP COLUMN `to_loan_transaction_id`,
DROP COLUMN `is_reversed`,
DROP COLUMN `transaction_date`,
DROP COLUMN `currency_code`,
DROP COLUMN `currency_digits`,
DROP COLUMN `currency_multiplesof`,
DROP COLUMN `amount`,
DROP COLUMN `description`;
DROP TABLE `m_savings_account_transfer`;
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('account_transfer', 'READ_STANDINGINSTRUCTION ', 'STANDINGINSTRUCTION ', 'READ', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('account_transfer', 'CREATE_STANDINGINSTRUCTION ', 'STANDINGINSTRUCTION ', 'CREATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('account_transfer', 'UPDATE_STANDINGINSTRUCTION ', 'STANDINGINSTRUCTION ', 'UPDATE', 0);
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES ('account_transfer', 'DELETE_STANDINGINSTRUCTION ', 'STANDINGINSTRUCTION ', 'DELETE', 0);
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`, `is_misfired`) VALUES ('Execute Standing Instruction', 'Execute Standing Instruction', '0 0 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0, 0);
@@ -341,7 +341,7 @@ public class CommandWrapper {
public boolean isTemplateRessource() {
return this.entityName.equalsIgnoreCase("Template");
}
public boolean isApproveLoanApplication() {
return this.actionName.equalsIgnoreCase("APPROVE") && this.entityName.equalsIgnoreCase("LOAN");
}
@@ -390,6 +390,10 @@ public class CommandWrapper {
return this.actionName.equalsIgnoreCase("UPDATE") && this.entityName.equalsIgnoreCase("DISBURSEMENTDETAIL");
}
public boolean isStandingInstruction() {
return this.entityName.equalsIgnoreCase("STANDINGINSTRUCTION");
}
public boolean isCloseLoanAsObligationsMet() {
return this.actionName.equalsIgnoreCase("CLOSE") && this.entityName.equalsIgnoreCase("LOAN");
}
@@ -32,7 +32,7 @@ public class CommandWrapperBuilder {
this.loanId = withLoanId;
return this;
}
public CommandWrapperBuilder withSavingsId(final Long withSavingsId) {
this.savingsId = withSavingsId;
return this;
@@ -42,17 +42,17 @@ public class CommandWrapperBuilder {
this.clientId = withClientId;
return this;
}
public CommandWrapperBuilder withGroupId(final Long withGroupId) {
this.groupId = withGroupId;
return this;
}
public CommandWrapperBuilder withEntityName(final String withEntityName) {
this.entityName = withEntityName;
return this;
}
public CommandWrapperBuilder withSubEntityId(final Long withSubEntityId) {
this.subentityId = withSubEntityId;
return this;
@@ -949,6 +949,30 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder createStandingInstruction() {
this.actionName = "CREATE";
this.entityName = "STANDINGINSTRUCTION";
this.entityId = null;
this.href = "/standinginstructions";
return this;
}
public CommandWrapperBuilder updateStandingInstruction(final Long standingInstructionId) {
this.actionName = "UPDATE";
this.entityName = "STANDINGINSTRUCTION";
this.entityId = standingInstructionId;
this.href = "/standinginstructions";
return this;
}
public CommandWrapperBuilder deleteStandingInstruction(final Long standingInstructionId) {
this.actionName = "DELETE";
this.entityName = "STANDINGINSTRUCTION";
this.entityId = standingInstructionId;
this.href = "/standinginstructions";
return this;
}
public CommandWrapperBuilder savingsAccountDeposit(final Long accountId) {
this.actionName = "DEPOSIT";
this.entityName = "SAVINGSACCOUNT";
@@ -1452,7 +1476,7 @@ public class CommandWrapperBuilder {
this.href = "/clients/" + clientId + "?command=assignStaff";
return this;
}
public CommandWrapperBuilder updateClientSavingsAccount(final Long clientId) {
this.actionName = "UPDATESAVINGSACCOUNT";
this.entityName = "CLIENT";
@@ -1462,7 +1486,6 @@ public class CommandWrapperBuilder {
return this;
}
public CommandWrapperBuilder createProductMix(final Long productId) {
this.actionName = "CREATE";
this.entityName = "PRODUCTMIX";
@@ -638,6 +638,17 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isStandingInstruction()) {
if (wrapper.isCreate()) {
handler = this.applicationContext.getBean("createStandingInstructionCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isUpdate()) {
handler = this.applicationContext.getBean("updateStandingInstructionCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isDelete()) {
handler = this.applicationContext.getBean("deleteStandingInstructionCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else {
throw new UnsupportedCommandException(wrapper.commandName());
@@ -16,6 +16,7 @@ import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.property.RRule;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.quartz.CronExpression;
import org.springframework.util.ObjectUtils;
@@ -767,4 +768,22 @@ public class DataValidatorBuilder {
return this;
}
public DataValidatorBuilder validateDateAfter(final LocalDate date) {
if (this.value == null && this.ignoreNullValue) { return this; }
if (this.value != null && date != null) {
final LocalDate dateVal = (LocalDate) this.value;
if (date.isAfter(dateVal)) {
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
.append(this.parameter).append(".is.less.than.date");
final StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(this.parameter)
.append(" must be greter than provided date").append(date);
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
defaultEnglishMessage.toString(), this.parameter, dateVal, date);
this.dataValidationErrors.add(error);
}
}
return this;
}
}
@@ -11,7 +11,8 @@ public enum JobName {
TRANSFER_FEE_CHARGE_FOR_LOANS("Transfer Fee For Loans From Savings"), //
ACCOUNTING_RUNNING_BALANCE_UPDATE("Update Accounting Running Balances"), //
PAY_DUE_SAVINGS_CHARGES("Pay Due Savings Charges"), //
APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans");
APPLY_CHARGE_TO_OVERDUE_LOAN_INSTALLMENT("Apply penalty to overdue loans"),
EXECUTE_STANDING_INSTRUCTIONS("Execute Standing Instruction");
private final String name;
@@ -0,0 +1,27 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account;
public class AccountDetailConstants {
// general
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
// savings product and account parameters
public static final String idParamName = "id";
public static final String fromOfficeIdParamName = "fromOfficeId";
public static final String fromClientIdParamName = "fromClientId";
public static final String fromAccountIdParamName = "fromAccountId";
public static final String fromAccountTypeParamName = "fromAccountType";
public static final String toOfficeIdParamName = "toOfficeId";
public static final String toClientIdParamName = "toClientId";
public static final String toAccountIdParamName = "toAccountId";
public static final String toAccountTypeParamName = "toAccountType";
public static final String transferTypeParamName = "transferType";
}
@@ -1,50 +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.account;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.mifosplatform.portfolio.account.data.AccountTransferData;
public class AccountTransfersApiConstants {
public static final String ACCOUNT_TRANSFER_RESOURCE_NAME = "accounttransfer";
// general
public static final String localeParamName = "locale";
public static final String dateFormatParamName = "dateFormat";
// savings product and account parameters
public static final String idParamName = "id";
public static final String fromOfficeIdParamName = "fromOfficeId";
public static final String fromClientIdParamName = "fromClientId";
public static final String fromAccountIdParamName = "fromAccountId";
public static final String fromAccountTypeParamName = "fromAccountType";
public static final String toOfficeIdParamName = "toOfficeId";
public static final String toClientIdParamName = "toClientId";
public static final String toAccountIdParamName = "toAccountId";
public static final String toAccountTypeParamName = "toAccountType";
// transaction parameters
public static final String transferDateParamName = "transferDate";
public static final String transferAmountParamName = "transferAmount";
public static final String transferDescriptionParamName = "transferDescription";
public static final Set<String> REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName, dateFormatParamName,
fromOfficeIdParamName, fromClientIdParamName, fromAccountTypeParamName, fromAccountIdParamName, toOfficeIdParamName,
toClientIdParamName, toAccountTypeParamName, toAccountIdParamName, transferDateParamName, transferAmountParamName,
transferDescriptionParamName));
/**
* These parameters will match the class level parameters of
* {@link AccountTransferData}. Where possible, we try to get response
* parameters to match those of request parameters.
*/
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(idParamName, transferDescriptionParamName,
"currency"));
}
@@ -0,0 +1,38 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.mifosplatform.portfolio.account.AccountDetailConstants;
import org.mifosplatform.portfolio.account.data.AccountTransferData;
public class AccountTransfersApiConstants {
public static final String ACCOUNT_TRANSFER_RESOURCE_NAME = "accounttransfer";
// transaction parameters
public static final String transferDateParamName = "transferDate";
public static final String transferAmountParamName = "transferAmount";
public static final String transferDescriptionParamName = "transferDescription";
public static final Set<String> REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(AccountDetailConstants.localeParamName,
AccountDetailConstants.dateFormatParamName, AccountDetailConstants.fromOfficeIdParamName,
AccountDetailConstants.fromClientIdParamName, AccountDetailConstants.fromAccountTypeParamName,
AccountDetailConstants.fromAccountIdParamName, AccountDetailConstants.toOfficeIdParamName,
AccountDetailConstants.toClientIdParamName, AccountDetailConstants.toAccountTypeParamName,
AccountDetailConstants.toAccountIdParamName, transferDateParamName, transferAmountParamName, transferDescriptionParamName));
/**
* These parameters will match the class level parameters of
* {@link AccountTransferData}. Where possible, we try to get response
* parameters to match those of request parameters.
*/
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(AccountDetailConstants.idParamName,
transferDescriptionParamName, "currency"));
}
@@ -25,7 +25,6 @@ import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSeriali
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.account.AccountTransfersApiConstants;
import org.mifosplatform.portfolio.account.data.AccountTransferData;
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.group.service.SearchParameters;
@@ -94,14 +93,14 @@ public class AccountTransfersApiResource {
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("externalId") final String externalId, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder) {
@QueryParam("sortOrder") final String sortOrder,@QueryParam("accountDetailId") final Long accountDetailId) {
this.context.authenticatedUser().validateHasReadPermission(AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(sqlSearch, externalId, offset, limit, orderBy,
sortOrder);
final Page<AccountTransferData> transfers = this.accountTransfersReadPlatformService.retrieveAll(searchParameters);
final Page<AccountTransferData> transfers = this.accountTransfersReadPlatformService.retrieveAll(searchParameters, accountDetailId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, transfers, AccountTransfersApiConstants.RESPONSE_DATA_PARAMETERS);
@@ -0,0 +1,50 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.api;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.mifosplatform.portfolio.account.AccountDetailConstants;
public class StandingInstructionApiConstants {
public static final String STANDING_INSTRUCTION_RESOURCE_NAME = "standinginstructions";
public static final String nameParamName = "name";
public static final String priorityParamName = "priority";
public static final String instructionTypeParamName = "instructionType";
public static final String statusParamName = "status";
public static final String amountParamName = "amount";
public static final String validFromParamName = "validFrom";
public static final String validTillParamName = "validTill";
public static final String recurrenceTypeParamName = "recurrenceType";
public static final String recurrenceFrequencyParamName = "recurrenceFrequency";
public static final String recurrenceIntervalParamName = "recurrenceInterval";
public static final String recurrenceOnMonthDayParamName = "recurrenceOnMonthDay";
public static final String monthDayFormatParamName = "monthDayFormat";
public static final Set<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
AccountDetailConstants.localeParamName, AccountDetailConstants.dateFormatParamName,
AccountDetailConstants.fromOfficeIdParamName, AccountDetailConstants.fromClientIdParamName,
AccountDetailConstants.fromAccountTypeParamName, AccountDetailConstants.fromAccountIdParamName,
AccountDetailConstants.toOfficeIdParamName, AccountDetailConstants.toClientIdParamName,
AccountDetailConstants.toAccountTypeParamName, AccountDetailConstants.toAccountIdParamName,
AccountDetailConstants.transferTypeParamName, priorityParamName, instructionTypeParamName, statusParamName, amountParamName,
validFromParamName, validTillParamName, recurrenceTypeParamName, recurrenceFrequencyParamName, recurrenceIntervalParamName,
recurrenceOnMonthDayParamName, nameParamName, monthDayFormatParamName));
public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
AccountDetailConstants.localeParamName, AccountDetailConstants.dateFormatParamName, priorityParamName,
instructionTypeParamName, statusParamName, amountParamName, validFromParamName, validTillParamName, recurrenceTypeParamName,
recurrenceFrequencyParamName, recurrenceIntervalParamName, recurrenceOnMonthDayParamName, monthDayFormatParamName));
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(AccountDetailConstants.idParamName,
nameParamName, priorityParamName, instructionTypeParamName, statusParamName, AccountDetailConstants.transferTypeParamName,
validFromParamName, validTillParamName));
}
@@ -0,0 +1,195 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.api;
import java.util.Arrays;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.account.data.AccountTransferData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDTO;
import org.mifosplatform.portfolio.account.data.StandingInstructionData;
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.account.service.StandingInstructionReadPlatformService;
import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/standinginstructions")
@Component
@Scope("singleton")
public class StandingInstructionApiResource {
private final PlatformSecurityContext context;
private final DefaultToApiJsonSerializer<StandingInstructionData> toApiJsonSerializer;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
@Autowired
public StandingInstructionApiResource(final PlatformSecurityContext context,
final DefaultToApiJsonSerializer<StandingInstructionData> toApiJsonSerializer,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final ApiRequestParameterHelper apiRequestParameterHelper,
final StandingInstructionReadPlatformService standingInstructionReadPlatformService,
final AccountTransfersReadPlatformService accountTransfersReadPlatformService) {
this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.standingInstructionReadPlatformService = standingInstructionReadPlatformService;
this.accountTransfersReadPlatformService = accountTransfersReadPlatformService;
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String template(@QueryParam("fromOfficeId") final Long fromOfficeId, @QueryParam("fromClientId") final Long fromClientId,
@QueryParam("fromAccountId") final Long fromAccountId, @QueryParam("fromAccountType") final Integer fromAccountType,
@QueryParam("toOfficeId") final Long toOfficeId, @QueryParam("toClientId") final Long toClientId,
@QueryParam("toAccountId") final Long toAccountId, @QueryParam("toAccountType") final Integer toAccountType,
@QueryParam("transferType") final Integer transferType, @Context final UriInfo uriInfo) {
this.context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
final StandingInstructionData standingInstructionData = this.standingInstructionReadPlatformService.retrieveTemplate(fromOfficeId,
fromClientId, fromAccountId, fromAccountType, toOfficeId, toClientId, toAccountId, toAccountType, transferType);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, standingInstructionData,
StandingInstructionApiConstants.RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String create(final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createStandingInstruction().withJson(apiRequestBodyAsJson)
.build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
@PUT
@Path("{standingInstructionId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String update(@PathParam("standingInstructionId") final Long standingInstructionId, final String apiRequestBodyAsJson,
@QueryParam("command") final String commandParam) {
CommandWrapper commandRequest = null;
if (is(commandParam, "update")) {
commandRequest = new CommandWrapperBuilder().updateStandingInstruction(standingInstructionId).withJson(apiRequestBodyAsJson)
.build();
} else if (is(commandParam, "delete")) {
commandRequest = new CommandWrapperBuilder().deleteStandingInstruction(standingInstructionId).withJson(apiRequestBodyAsJson)
.build();
}
if (commandRequest == null) { throw new UnrecognizedQueryParamException("command", commandParam); }
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAll(@Context final UriInfo uriInfo, @QueryParam("sqlSearch") final String sqlSearch,
@QueryParam("externalId") final String externalId, @QueryParam("offset") final Integer offset,
@QueryParam("limit") final Integer limit, @QueryParam("orderBy") final String orderBy,
@QueryParam("sortOrder") final String sortOrder, @QueryParam("transferType") final Integer transferType,
@QueryParam("clientName") final String clientName, @QueryParam("clientId") final Long clientId,
@QueryParam("fromAccountId") final Long fromAccount, @QueryParam("fromAccountType") final Integer fromAccountType) {
this.context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(sqlSearch, externalId, offset, limit, orderBy,
sortOrder);
StandingInstructionDTO standingInstructionDTO = new StandingInstructionDTO(searchParameters, transferType, clientName, clientId,
fromAccount, fromAccountType);
final Page<StandingInstructionData> transfers = this.standingInstructionReadPlatformService.retrieveAll(standingInstructionDTO);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, transfers, StandingInstructionApiConstants.RESPONSE_DATA_PARAMETERS);
}
@GET
@Path("{standingInstructionId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveOne(@PathParam("standingInstructionId") final Long standingInstructionId, @Context final UriInfo uriInfo,
@QueryParam("sqlSearch") final String sqlSearch, @QueryParam("externalId") final String externalId,
@QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
StandingInstructionData standingInstructionData = this.standingInstructionReadPlatformService.retrieveOne(standingInstructionId);
final SearchParameters searchParameters = SearchParameters.forAccountTransfer(sqlSearch, externalId, offset, limit, orderBy,
sortOrder);
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
Page<AccountTransferData> transfers = null;
if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) {
associationParameters.addAll(Arrays.asList("transactions", "template"));
}
if (associationParameters.contains("transactions")) {
transfers = this.accountTransfersReadPlatformService.retrieveByStandingInstruction(standingInstructionId, searchParameters);
standingInstructionData = StandingInstructionData.withTransferData(standingInstructionData, transfers);
}
if (associationParameters.contains("template")) {
final StandingInstructionData templateData = this.standingInstructionReadPlatformService.retrieveTemplate(
standingInstructionData.fromClient().officeId(), standingInstructionData.fromClient().id(), standingInstructionData
.fromAccount().accountId(), standingInstructionData.fromAccountType().getValue(), standingInstructionData
.toClient().officeId(), standingInstructionData.toClient().id(), standingInstructionData.toAccount()
.accountId(), standingInstructionData.toAccountType().getValue(), standingInstructionData.transferType()
.getValue());
standingInstructionData = StandingInstructionData.withTemplateData(standingInstructionData, templateData);
}
}
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, standingInstructionData,
StandingInstructionApiConstants.RESPONSE_DATA_PARAMETERS);
}
}
@@ -6,6 +6,7 @@ import java.util.Locale;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
public class AccountTransferDTO {
@@ -24,12 +25,14 @@ public class AccountTransferDTO {
private final Integer toTransferType;
private final Long chargeId;
private final Integer loanInstallmentNumber;
private final Integer transferType;
private final AccountTransferDetails accountTransferDetails;
public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount,
final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId,
final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt,
final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId,
Integer loanInstallmentNumber) {
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails) {
this.transactionDate = transactionDate;
this.transactionAmount = transactionAmount;
this.fromAccountType = fromAccountType;
@@ -44,6 +47,8 @@ public class AccountTransferDTO {
this.toTransferType = toTransferType;
this.chargeId = chargeId;
this.loanInstallmentNumber = loanInstallmentNumber;
this.transferType = transferType;
this.accountTransferDetails = accountTransferDetails;
}
public LocalDate getTransactionDate() {
@@ -102,4 +107,14 @@ public class AccountTransferDTO {
return this.loanInstallmentNumber;
}
public Integer getTransferType() {
return this.transferType;
}
public AccountTransferDetails getAccountTransferDetails() {
return this.accountTransferDetails;
}
}
@@ -5,19 +5,11 @@
*/
package org.mifosplatform.portfolio.account.data;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDescriptionParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferDescriptionParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -43,10 +35,13 @@ import com.google.gson.reflect.TypeToken;
public class AccountTransfersDataValidator {
private final FromJsonHelper fromApiJsonHelper;
private final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator;
@Autowired
public AccountTransfersDataValidator(final FromJsonHelper fromApiJsonHelper) {
public AccountTransfersDataValidator(final FromJsonHelper fromApiJsonHelper,
final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.accountTransfersDetailDataValidator = accountTransfersDetailDataValidator;
}
public void validate(final JsonCommand command) {
@@ -64,31 +59,7 @@ public class AccountTransfersDataValidator {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
baseDataValidator.reset().parameter(fromOfficeIdParamName).value(fromOfficeId).notNull().integerGreaterThanZero();
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
baseDataValidator.reset().parameter(fromClientIdParamName).value(fromClientId).notNull().integerGreaterThanZero();
final Long fromAccountId = this.fromApiJsonHelper.extractLongNamed(fromAccountIdParamName, element);
baseDataValidator.reset().parameter(fromAccountIdParamName).value(fromAccountId).notNull().integerGreaterThanZero();
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
baseDataValidator.reset().parameter(fromAccountTypeParamName).value(fromAccountType)
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
baseDataValidator.reset().parameter(toOfficeIdParamName).value(toOfficeId).notNull().integerGreaterThanZero();
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
baseDataValidator.reset().parameter(toClientIdParamName).value(toClientId).notNull().integerGreaterThanZero();
final Long toAccountId = this.fromApiJsonHelper.extractLongNamed(toAccountIdParamName, element);
baseDataValidator.reset().parameter(toAccountIdParamName).value(toAccountId).notNull().integerGreaterThanZero();
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
baseDataValidator.reset().parameter(toAccountTypeParamName).value(toAccountType)
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
this.accountTransfersDetailDataValidator.validate(command, baseDataValidator);
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transferDateParamName, element);
baseDataValidator.reset().parameter(transferDateParamName).value(transactionDate).notNull();
@@ -0,0 +1,67 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.data;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toOfficeIdParamName;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
@Component
public class AccountTransfersDetailDataValidator {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public AccountTransfersDetailDataValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validate(final JsonCommand command, final DataValidatorBuilder baseDataValidator) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
baseDataValidator.reset().parameter(fromOfficeIdParamName).value(fromOfficeId).notNull().integerGreaterThanZero();
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
baseDataValidator.reset().parameter(fromClientIdParamName).value(fromClientId).notNull().integerGreaterThanZero();
final Long fromAccountId = this.fromApiJsonHelper.extractLongNamed(fromAccountIdParamName, element);
baseDataValidator.reset().parameter(fromAccountIdParamName).value(fromAccountId).notNull().integerGreaterThanZero();
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
baseDataValidator.reset().parameter(fromAccountTypeParamName).value(fromAccountType).notNull()
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
baseDataValidator.reset().parameter(toOfficeIdParamName).value(toOfficeId).notNull().integerGreaterThanZero();
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
baseDataValidator.reset().parameter(toClientIdParamName).value(toClientId).notNull().integerGreaterThanZero();
final Long toAccountId = this.fromApiJsonHelper.extractLongNamed(toAccountIdParamName, element);
baseDataValidator.reset().parameter(toAccountIdParamName).value(toAccountId).notNull().integerGreaterThanZero();
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
baseDataValidator.reset().parameter(toAccountTypeParamName).value(toAccountType).notNull()
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
}
}
@@ -0,0 +1,49 @@
package org.mifosplatform.portfolio.account.data;
import org.mifosplatform.portfolio.group.service.SearchParameters;
public class StandingInstructionDTO {
final SearchParameters searchParameters;
final Long clientId;
final String clientName;
final Integer transferType;
final Integer fromAccountType;
final Long fromAccount;
public StandingInstructionDTO(final SearchParameters searchParameters, final Integer transferType, final String clientName,
final Long clientId, final Long fromAccount,final Integer fromAccountType) {
this.searchParameters = searchParameters;
this.transferType = transferType;
this.clientName = clientName;
this.clientId = clientId;
this.fromAccount = fromAccount;
this.fromAccountType = fromAccountType;
}
public SearchParameters searchParameters() {
return this.searchParameters;
}
public Long clientId() {
return this.clientId;
}
public String clientName() {
return this.clientName;
}
public Integer transferType() {
return this.transferType;
}
public Long fromAccount() {
return this.fromAccount;
}
public Integer fromAccountType() {
return this.fromAccountType;
}
}
@@ -0,0 +1,376 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.data;
import java.math.BigDecimal;
import java.util.Collection;
import org.joda.time.DateTimeFieldType;
import org.joda.time.LocalDate;
import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionType;
/**
* Immutable data object representing a savings account.
*/
@SuppressWarnings("unused")
public class StandingInstructionData {
private final Long id;
private final Long accountDetailId;
private final String name;
private final OfficeData fromOffice;
private final ClientData fromClient;
private final EnumOptionData fromAccountType;
private final PortfolioAccountData fromAccount;
private final OfficeData toOffice;
private final ClientData toClient;
private final EnumOptionData toAccountType;
private final PortfolioAccountData toAccount;
private final EnumOptionData transferType;
private final EnumOptionData priority;
private final EnumOptionData instructionType;
private final EnumOptionData status;
private final BigDecimal amount;
private final LocalDate validFrom;
private final LocalDate validTill;
private final EnumOptionData recurrenceType;
private final EnumOptionData recurrenceFrequency;
private final Integer recurrenceInterval;
private final MonthDay recurrenceOnMonthDay;
private final Page<AccountTransferData> transactions;
private final Collection<OfficeData> fromOfficeOptions;
private final Collection<ClientData> fromClientOptions;
private final Collection<EnumOptionData> fromAccountTypeOptions;
private final Collection<PortfolioAccountData> fromAccountOptions;
private final Collection<OfficeData> toOfficeOptions;
private final Collection<ClientData> toClientOptions;
private final Collection<EnumOptionData> toAccountTypeOptions;
private final Collection<PortfolioAccountData> toAccountOptions;
private final Collection<EnumOptionData> transferTypeOptions;
private final Collection<EnumOptionData> statusOptions;
private final Collection<EnumOptionData> instructionTypeOptions;
private final Collection<EnumOptionData> priorityOptions;
private final Collection<EnumOptionData> recurrenceTypeOptions;
private final Collection<EnumOptionData> recurrenceFrequencyOptions;
public static StandingInstructionData template(final Collection<OfficeData> fromOfficeOptions,
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
final Long id = null;
final Long accountDetailId = null;
final String name = null;
final OfficeData fromOffice = null;
final OfficeData toOffice = null;
final ClientData fromClient = null;
final ClientData toClient = null;
final EnumOptionData fromAccountType = null;
final PortfolioAccountData fromAccount = null;
final EnumOptionData toAccountType = null;
final PortfolioAccountData toAccount = null;
final EnumOptionData transferType = null;
final EnumOptionData priority = null;
final EnumOptionData instructionType = null;
final EnumOptionData status = null;
final BigDecimal amount = null;
final LocalDate validFrom = null;
final LocalDate validTill = null;
final EnumOptionData recurrenceType = null;
final EnumOptionData recurrenceFrequency = null;
final Integer recurrenceInterval = null;
final MonthDay recurrenceOnMonthDay = null;
final Page<AccountTransferData> transactions = null;
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
recurrenceFrequencyOptions);
}
public static StandingInstructionData instance(final Long id, final Long accountDetailId, final String name,
final OfficeData fromOffice, final OfficeData toOffice, final ClientData fromClient, final ClientData toClient,
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final EnumOptionData toAccountType,
final PortfolioAccountData toAccount, final EnumOptionData transferType, final EnumOptionData priority,
final EnumOptionData instructionType, final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom,
final LocalDate validTill, final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency,
final Integer recurrenceInterval, final MonthDay recurrenceOnMonthDay) {
final Page<AccountTransferData> transactions = null;
final Collection<OfficeData> fromOfficeOptions = null;
final Collection<ClientData> fromClientOptions = null;
final Collection<EnumOptionData> fromAccountTypeOptions = null;
final Collection<PortfolioAccountData> fromAccountOptions = null;
final Collection<OfficeData> toOfficeOptions = null;
final Collection<ClientData> toClientOptions = null;
final Collection<EnumOptionData> toAccountTypeOptions = null;
final Collection<PortfolioAccountData> toAccountOptions = null;
final Collection<EnumOptionData> transferTypeOptions = null;
final Collection<EnumOptionData> statusOptions = null;
final Collection<EnumOptionData> instructionTypeOptions = null;
final Collection<EnumOptionData> priorityOptions = null;
final Collection<EnumOptionData> recurrenceTypeOptions = null;
final Collection<EnumOptionData> recurrenceFrequencyOptions = null;
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
recurrenceFrequencyOptions);
}
public static StandingInstructionData withTemplateData(StandingInstructionData instructionData, StandingInstructionData templateData) {
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay,
instructionData.transactions, templateData.fromOfficeOptions, templateData.fromClientOptions,
templateData.fromAccountTypeOptions, templateData.fromAccountOptions, templateData.toOfficeOptions,
templateData.toClientOptions, templateData.toAccountTypeOptions, templateData.toAccountOptions,
templateData.transferTypeOptions, templateData.statusOptions, templateData.instructionTypeOptions,
templateData.priorityOptions, templateData.recurrenceTypeOptions, templateData.recurrenceFrequencyOptions);
}
private StandingInstructionData(final Long id, final Long accountDetailId, final String name, final OfficeData fromOffice,
final ClientData fromClient, final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount,
final OfficeData toOffice, final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
final EnumOptionData transferType, final EnumOptionData priority, final EnumOptionData instructionType,
final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom, LocalDate validTill,
final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency, final Integer recurrenceInterval,
final MonthDay recurrenceOnMonthDay, final Page<AccountTransferData> transactions,
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions,
final Collection<EnumOptionData> transferTypeOptions, final Collection<EnumOptionData> statusOptions,
final Collection<EnumOptionData> instructionTypeOptions, final Collection<EnumOptionData> priorityOptions,
final Collection<EnumOptionData> recurrenceTypeOptions, final Collection<EnumOptionData> recurrenceFrequencyOptions) {
this.id = id;
this.accountDetailId = accountDetailId;
this.name = name;
this.fromOffice = fromOffice;
this.fromClient = fromClient;
this.fromAccountType = fromAccountType;
this.fromAccount = fromAccount;
this.toOffice = toOffice;
this.toClient = toClient;
this.toAccountType = toAccountType;
this.toAccount = toAccount;
this.transferType = transferType;
this.priority = priority;
this.instructionType = instructionType;
this.status = status;
this.amount = amount;
this.validFrom = validFrom;
this.validTill = validTill;
this.recurrenceType = recurrenceType;
this.recurrenceFrequency = recurrenceFrequency;
this.recurrenceInterval = recurrenceInterval;
this.recurrenceOnMonthDay = recurrenceOnMonthDay;
this.fromOfficeOptions = fromOfficeOptions;
this.fromClientOptions = fromClientOptions;
this.fromAccountTypeOptions = fromAccountTypeOptions;
this.fromAccountOptions = fromAccountOptions;
this.toOfficeOptions = toOfficeOptions;
this.toClientOptions = toClientOptions;
this.toAccountTypeOptions = toAccountTypeOptions;
this.toAccountOptions = toAccountOptions;
this.transferTypeOptions = transferTypeOptions;
this.statusOptions = statusOptions;
this.instructionTypeOptions = instructionTypeOptions;
this.priorityOptions = priorityOptions;
this.recurrenceTypeOptions = recurrenceTypeOptions;
this.recurrenceFrequencyOptions = recurrenceFrequencyOptions;
this.transactions = transactions;
}
public static StandingInstructionData template(OfficeData fromOffice, ClientData fromClient, EnumOptionData fromAccountType,
PortfolioAccountData fromAccount, LocalDate transferDate, OfficeData toOffice, ClientData toClient,
EnumOptionData toAccountType, PortfolioAccountData toAccount, final Collection<OfficeData> fromOfficeOptions,
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
final Long id = null;
final Long accountDetailId = null;
final String name = null;
final EnumOptionData transferType = null;
final EnumOptionData priority = null;
final EnumOptionData instructionType = null;
final EnumOptionData status = null;
final BigDecimal amount = null;
final LocalDate validFrom = null;
final LocalDate validTill = null;
final EnumOptionData recurrenceType = null;
final EnumOptionData recurrenceFrequency = null;
final Integer recurrenceInterval = null;
final MonthDay recurrenceOnMonthDay = null;
final Page<AccountTransferData> transactions = null;
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
recurrenceFrequencyOptions);
}
public static StandingInstructionData withTransferData(StandingInstructionData instructionData,
final Page<AccountTransferData> transactions) {
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay,
transactions, instructionData.fromOfficeOptions, instructionData.fromClientOptions, instructionData.fromAccountTypeOptions,
instructionData.fromAccountOptions, instructionData.toOfficeOptions, instructionData.toClientOptions,
instructionData.toAccountTypeOptions, instructionData.toAccountOptions, instructionData.transferTypeOptions,
instructionData.statusOptions, instructionData.instructionTypeOptions, instructionData.priorityOptions,
instructionData.recurrenceTypeOptions, instructionData.recurrenceFrequencyOptions);
}
public StandingInstructionType instructionType() {
StandingInstructionType standingInstructionType = null;
if (this.instructionType != null) {
standingInstructionType = StandingInstructionType.fromInt(this.instructionType.getId().intValue());
}
return standingInstructionType;
}
public AccountTransferRecurrenceType recurrenceType() {
AccountTransferRecurrenceType recurrenceType = null;
if (this.recurrenceType != null) {
recurrenceType = AccountTransferRecurrenceType.fromInt(this.recurrenceType.getId().intValue());
}
return recurrenceType;
}
public PeriodFrequencyType recurrenceFrequency() {
PeriodFrequencyType frequencyType = null;
if (this.recurrenceFrequency != null) {
frequencyType = PeriodFrequencyType.fromInt(this.recurrenceFrequency.getId().intValue());
}
return frequencyType;
}
public PortfolioAccountType fromAccountType() {
PortfolioAccountType accountType = null;
if (this.fromAccountType != null) {
accountType = PortfolioAccountType.fromInt(this.fromAccountType.getId().intValue());
}
return accountType;
}
public PortfolioAccountType toAccountType() {
PortfolioAccountType accountType = null;
if (this.toAccountType != null) {
accountType = PortfolioAccountType.fromInt(this.toAccountType.getId().intValue());
}
return accountType;
}
public AccountTransferType transferType() {
AccountTransferType accountTransferType = null;
if (this.transferType != null) {
accountTransferType = AccountTransferType.fromInt(this.transferType.getId().intValue());
}
return accountTransferType;
}
public Integer recurrenceInterval() {
return this.recurrenceInterval;
}
public Integer recurrenceOnDay() {
Integer recurrenceOnDay = 0;
if (this.recurrenceOnMonthDay != null) {
recurrenceOnDay = this.recurrenceOnMonthDay.get(DateTimeFieldType.dayOfMonth());
}
return recurrenceOnDay;
}
public Integer recurrenceOnMonth() {
Integer recurrenceOnMonth = 0;
if (this.recurrenceOnMonthDay != null) {
recurrenceOnMonth = this.recurrenceOnMonthDay.get(DateTimeFieldType.monthOfYear());
}
return recurrenceOnMonth;
}
public LocalDate validFrom() {
return this.validFrom;
}
public BigDecimal amount() {
return this.amount;
}
public PortfolioAccountData fromAccount() {
return this.fromAccount;
}
public PortfolioAccountData toAccount() {
return this.toAccount;
}
public String name() {
return this.name;
}
public Integer toTransferType() {
Integer transferType = null;
AccountTransferType accountTransferType = transferType();
if (accountTransferType.isChargePayment()) {
transferType = LoanTransactionType.CHARGE_PAYMENT.getValue();
} else if (accountTransferType.isLoanRepayment()) {
transferType = LoanTransactionType.REPAYMENT.getValue();
}
return transferType;
}
public Long accountDetailId() {
return this.accountDetailId;
}
public ClientData fromClient() {
return this.fromClient;
}
public ClientData toClient() {
return this.toClient;
}
public Long getId() {
return this.id;
}
}
@@ -0,0 +1,237 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.data;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.CREATE_REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.UPDATE_REQUEST_DATA_PARAMETERS;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.nameParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.transferTypeParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public class StandingInstructionDataValidator {
private final FromJsonHelper fromApiJsonHelper;
private final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator;
@Autowired
public StandingInstructionDataValidator(final FromJsonHelper fromApiJsonHelper,
final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.accountTransfersDetailDataValidator = accountTransfersDetailDataValidator;
}
public void validateForCreate(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, CREATE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
this.accountTransfersDetailDataValidator.validate(command, baseDataValidator);
final JsonElement element = command.parsedJson();
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(statusParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(statusParamName).value(status).notNull().inMinMaxRange(1, 2);
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(validFromParamName, element);
baseDataValidator.reset().parameter(validFromParamName).value(validFrom).notNull();
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(validTillParamName, element);
baseDataValidator.reset().parameter(validTillParamName).value(validTill).validateDateAfter(validFrom);
final BigDecimal transferAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(amountParamName, element);
baseDataValidator.reset().parameter(amountParamName).value(transferAmount).positiveAmount();
final Integer transferType = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(transferTypeParamName).value(transferType).notNull().inMinMaxRange(1, 3);
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(priorityParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(priorityParamName).value(priority).notNull().inMinMaxRange(1, 4);
final Integer standingInstructionType = this.fromApiJsonHelper.extractIntegerNamed(instructionTypeParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(instructionTypeParamName).value(standingInstructionType).notNull().inMinMaxRange(1, 2);
final Integer recurrenceType = this.fromApiJsonHelper.extractIntegerNamed(recurrenceTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(recurrenceType).notNull().inMinMaxRange(1, 2);
boolean isPeriodic = false;
if (recurrenceType != null) {
isPeriodic = AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence();
}
final Integer recurrenceFrequency = this.fromApiJsonHelper.extractIntegerNamed(recurrenceFrequencyParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(recurrenceFrequency).inMinMaxRange(0, 3);
if (recurrenceFrequency != null) {
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(recurrenceFrequency);
if (frequencyType.isMonthly() || frequencyType.isYearly()) {
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(recurrenceOnMonthDayParamName, element);
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(monthDay).notNull();
}
}
final Integer recurrenceInterval = this.fromApiJsonHelper.extractIntegerNamed(recurrenceIntervalParamName, element,
Locale.getDefault());
if (isPeriodic) {
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(recurrenceInterval).notNull();
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(recurrenceFrequency).notNull();
}
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(recurrenceInterval).integerGreaterThanZero();
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
baseDataValidator.reset().parameter(nameParamName).value(name).notNull();
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
if (toAccountType != null && PortfolioAccountType.fromInt(toAccountType).isSavingsAccount()) {
baseDataValidator.reset().parameter(instructionTypeParamName).value(standingInstructionType).notNull().inMinMaxRange(1, 1);
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(recurrenceType).notNull().inMinMaxRange(1, 1);
}
if (standingInstructionType != null && StandingInstructionType.fromInt(standingInstructionType).isFixedAmoutTransfer()) {
baseDataValidator.reset().parameter(amountParamName).value(transferAmount).notNull();
}
String errorCode = null;
AccountTransferType accountTransferType = AccountTransferType.fromInt(transferType);
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
if (fromAccountType != null && toAccountType != null) {
PortfolioAccountType fromPortfolioAccountType = PortfolioAccountType.fromInt(fromAccountType);
PortfolioAccountType toPortfolioAccountType = PortfolioAccountType.fromInt(toAccountType);
if (accountTransferType.isAccountTransfer()
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isLoanAccount())) {
errorCode = "not.account.transfer";
} else if (accountTransferType.isLoanRepayment()
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isSavingsAccount())) {
errorCode = "not.loan.repayment";
}
if (errorCode != null) {
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForUpdate(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, UPDATE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
final JsonElement element = command.parsedJson();
if (this.fromApiJsonHelper.parameterExists(validFromParamName, element)) {
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(validFromParamName, element);
baseDataValidator.reset().parameter(validFromParamName).value(validFrom).notNull();
}
if (this.fromApiJsonHelper.parameterExists(validTillParamName, element)) {
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(validTillParamName, element);
baseDataValidator.reset().parameter(validTillParamName).value(validTill).notNull();
}
if (this.fromApiJsonHelper.parameterExists(amountParamName, element)) {
final BigDecimal transferAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(amountParamName, element);
baseDataValidator.reset().parameter(amountParamName).value(transferAmount).positiveAmount();
}
if (this.fromApiJsonHelper.parameterExists(statusParamName, element)) {
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(statusParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(statusParamName).value(status).notNull().inMinMaxRange(1, 2);
}
if (this.fromApiJsonHelper.parameterExists(priorityParamName, element)) {
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(priorityParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(priorityParamName).value(priority).notNull().inMinMaxRange(1, 4);
}
if (this.fromApiJsonHelper.parameterExists(instructionTypeParamName, element)) {
final Integer standingInstructionType = this.fromApiJsonHelper.extractIntegerNamed(instructionTypeParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(instructionTypeParamName).value(standingInstructionType).notNull().inMinMaxRange(1, 2);
}
if (this.fromApiJsonHelper.parameterExists(recurrenceTypeParamName, element)) {
final Integer recurrenceType = this.fromApiJsonHelper
.extractIntegerNamed(recurrenceTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(recurrenceType).notNull().inMinMaxRange(1, 2);
}
if (this.fromApiJsonHelper.parameterExists(recurrenceFrequencyParamName, element)) {
final Integer recurrenceFrequency = this.fromApiJsonHelper.extractIntegerNamed(recurrenceFrequencyParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(recurrenceFrequency).inMinMaxRange(0, 3);
}
if (this.fromApiJsonHelper.parameterExists(recurrenceIntervalParamName, element)) {
final Integer recurrenceInterval = this.fromApiJsonHelper.extractIntegerNamed(recurrenceIntervalParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(recurrenceInterval).integerGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists(nameParamName, element)) {
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
baseDataValidator.reset().parameter(nameParamName).value(name).notNull();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
@@ -0,0 +1,25 @@
package org.mifosplatform.portfolio.account.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
public class StandingInstructionDuesData {
private final LocalDate dueDate;
private final BigDecimal totalDueAmount;
public StandingInstructionDuesData(final LocalDate dueDate, final BigDecimal totalDueAmount) {
this.dueDate = dueDate;
this.totalDueAmount = totalDueAmount;
}
public LocalDate dueDate() {
return this.dueDate;
}
public BigDecimal totalDueAmount() {
return this.totalDueAmount;
}
}
@@ -1,182 +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.account.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.joda.time.LocalDate;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_savings_account_transfer")
public class AccountTransfer extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "from_office_id", nullable = false)
private Office fromOffice;
@ManyToOne
@JoinColumn(name = "from_client_id", nullable = false)
private Client fromClient;
@ManyToOne
@JoinColumn(name = "from_savings_account_id", nullable = true)
private SavingsAccount fromAccount;
@ManyToOne
@JoinColumn(name = "to_office_id", nullable = false)
private Office toOffice;
@ManyToOne
@JoinColumn(name = "to_client_id", nullable = false)
private Client toClient;
@ManyToOne
@JoinColumn(name = "to_savings_account_id", nullable = true)
private SavingsAccount toSavingsAccount;
@ManyToOne
@JoinColumn(name = "from_savings_transaction_id", nullable = true)
private SavingsAccountTransaction fromTransaction;
@ManyToOne
@JoinColumn(name = "to_savings_transaction_id", nullable = true)
private SavingsAccountTransaction toSavingsTransaction;
@ManyToOne
@JoinColumn(name = "to_loan_account_id", nullable = true)
private Loan toLoanAccount;
@ManyToOne
@JoinColumn(name = "from_loan_account_id", nullable = true)
private Loan fromLoanAccount;
@ManyToOne
@JoinColumn(name = "to_loan_transaction_id", nullable = true)
private LoanTransaction toLoanTransaction;
@ManyToOne
@JoinColumn(name = "from_loan_transaction_id", nullable = true)
private LoanTransaction fromLoanTransaction;
@Column(name = "is_reversed", nullable = false)
private boolean reversed = false;
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date")
private Date date;
@Embedded
private MonetaryCurrency currency;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@Column(name = "description", length = 100)
private String description;
public static AccountTransfer savingsToSavingsTransfer(final Office fromOffice, final Client fromClient,
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, toSavingsAccount, null,
withdrawal, deposit, null, null, transactionDate, transactionAmount, description);
}
public static AccountTransfer savingsToLoanTransfer(final Office fromOffice, final Client fromClient,
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount,
final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, null, toLoanAccount, withdrawal,
null, loanRepaymentTransaction, null, transactionDate, transactionAmount, description);
}
public static AccountTransfer LoanTosavingsTransfer(final Office fromOffice, final Client fromClient, final Loan fromLoanAccount,
final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, final SavingsAccountTransaction deposit,
final LoanTransaction loanRefundTransaction, final LocalDate transactionDate, final Money transactionAmount,
final String description) {
return new AccountTransfer(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, toSavingsAccount, null, null,
deposit, null, loanRefundTransaction, transactionDate, transactionAmount, description);
}
protected AccountTransfer() {
//
}
private AccountTransfer(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount,
final Loan fromLoanAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
final Loan toLoanAccount, final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit,
final LoanTransaction loanRepaymentTransaction, final LoanTransaction loanRefundTransaction, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
this.fromOffice = fromOffice;
this.fromClient = fromClient;
this.fromAccount = fromSavingsAccount;
this.fromLoanAccount = fromLoanAccount;
this.fromLoanTransaction = loanRefundTransaction;
this.toOffice = toOffice;
this.toClient = toClient;
this.toSavingsAccount = toSavingsAccount;
this.fromTransaction = withdrawal;
this.toSavingsTransaction = deposit;
this.toLoanAccount = toLoanAccount;
this.toLoanTransaction = loanRepaymentTransaction;
this.date = transactionDate.toDate();
this.currency = transactionAmount.getCurrency();
this.amount = transactionAmount.getAmountDefaultedToNullIfZero();
this.description = description;
}
public LoanTransaction getFromLoanTransaction() {
return this.fromLoanTransaction;
}
public SavingsAccountTransaction getFromTransaction() {
return this.fromTransaction;
}
public LoanTransaction getToLoanTransaction() {
return this.toLoanTransaction;
}
public SavingsAccountTransaction getToSavingsTransaction() {
return this.toSavingsTransaction;
}
public void reverse() {
this.reversed = true;
}
public SavingsAccount getToSavingsAccount() {
return this.toSavingsAccount;
}
public SavingsAccount getFromAccount() {
return this.fromAccount;
}
public void updateToLoanTransaction(LoanTransaction toLoanTransaction) {
this.toLoanTransaction = toLoanTransaction;
}
}
@@ -5,130 +5,72 @@
*/
package org.mifosplatform.portfolio.account.domain;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDescriptionParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferDescriptionParamName;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
@Service
public class AccountTransferAssembler {
private final ClientRepositoryWrapper clientRepository;
private final OfficeRepository officeRepository;
private final SavingsAccountAssembler savingsAccountAssembler;
private final FromJsonHelper fromApiJsonHelper;
private final AccountTransferDetailAssembler accountTransferDetailAssembler;
@Autowired
public AccountTransferAssembler(final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository,
final SavingsAccountAssembler savingsAccountAssembler, final FromJsonHelper fromApiJsonHelper) {
this.clientRepository = clientRepository;
this.officeRepository = officeRepository;
this.savingsAccountAssembler = savingsAccountAssembler;
this.fromApiJsonHelper = fromApiJsonHelper;
public AccountTransferAssembler(final AccountTransferDetailAssembler accountTransferDetailAssembler) {
this.accountTransferDetailAssembler = accountTransferDetailAssembler;
}
public AccountTransfer assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccountTransaction withdrawal,
final SavingsAccountTransaction deposit) {
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
final SavingsAccount toSavingsAccount, final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId);
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToSavingsTransfer(command,
fromSavingsAccount, toSavingsAccount);
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), transactionAmount);
final String description = command.stringValueOfParameterNamed(transferDescriptionParamName);
return AccountTransfer.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toSavingsAccount,
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.savingsToSavingsTransfer(accountTransferDetails,
withdrawal, deposit, transactionDate, transactionMonetaryAmount, description);
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
public AccountTransfer assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
final Loan toLoanAccount, final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToLoanTransfer(command,
fromSavingsAccount, toLoanAccount);
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), transactionAmount);
final String description = command.stringValueOfParameterNamed(transferDescriptionParamName);
return AccountTransfer.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.savingsToLoanTransfer(accountTransferDetails,
withdrawal, loanRepaymentTransaction, transactionDate, transactionMonetaryAmount, description);
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
public AccountTransfer assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount,
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount,
final SavingsAccount toSavingsAccount, final SavingsAccountTransaction deposit, final LoanTransaction loanRefundTransaction) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleLoanToSavingsTransfer(command,
fromLoanAccount, toSavingsAccount);
final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName);
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName);
@@ -136,22 +78,58 @@ public class AccountTransferAssembler {
final String description = command.stringValueOfParameterNamed(transferDescriptionParamName);
return AccountTransfer.LoanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.LoanTosavingsTransfer(accountTransferDetails,
deposit, loanRefundTransaction, transactionDate, transactionMonetaryAmount, description);
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
public AccountTransfer assembleSavingsToLoanTransfer(final AccountTransferDTO accountTransferDTO,
public AccountTransferDetails assembleSavingsToLoanTransfer(final AccountTransferDTO accountTransferDTO,
final SavingsAccount fromSavingsAccount, final Loan toLoanAccount, final SavingsAccountTransaction savingsAccountTransaction,
final LoanTransaction loanTransaction) {
final Office fromOffice = fromSavingsAccount.office();
final Client fromClient = fromSavingsAccount.getClient();
final Office toOffice = toLoanAccount.getOffice();
final Client toClient = toLoanAccount.client();
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), accountTransferDTO.getTransactionAmount());
return AccountTransfer.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
if (accountTransferDetails == null) {
accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToLoanTransfer(fromSavingsAccount, toLoanAccount,
accountTransferDTO.getTransferType());
}
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.savingsToLoanTransfer(accountTransferDetails,
savingsAccountTransaction, loanTransaction, accountTransferDTO.getTransactionDate(), transactionMonetaryAmount,
accountTransferDTO.getDescription());
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
public AccountTransferDetails assembleSavingsToSavingsTransfer(final AccountTransferDTO accountTransferDTO,
final SavingsAccount fromSavingsAccount, final SavingsAccount toSavingsAccount, final SavingsAccountTransaction withdrawal,
final SavingsAccountTransaction deposit) {
final Money transactionMonetaryAmount = Money.of(fromSavingsAccount.getCurrency(), accountTransferDTO.getTransactionAmount());
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
if (accountTransferDetails == null) {
accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToSavingsTransfer(fromSavingsAccount,
toSavingsAccount, accountTransferDTO.getTransferType());
}
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.savingsToSavingsTransfer(accountTransferDetails,
withdrawal, deposit, accountTransferDTO.getTransactionDate(), transactionMonetaryAmount,
accountTransferDTO.getDescription());
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
public AccountTransferDetails assembleLoanToSavingsTransfer(final AccountTransferDTO accountTransferDTO, final Loan fromLoanAccount,
final SavingsAccount toSavingsAccount, final SavingsAccountTransaction deposit, final LoanTransaction loanRefundTransaction) {
final Money transactionMonetaryAmount = Money.of(fromLoanAccount.getCurrency(), accountTransferDTO.getTransactionAmount());
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
if (accountTransferDetails == null) {
accountTransferDetails = this.accountTransferDetailAssembler.assembleLoanToSavingsTransfer(fromLoanAccount, toSavingsAccount,
accountTransferDTO.getTransferType());
}
AccountTransferTransaction accountTransferTransaction = AccountTransferTransaction.LoanTosavingsTransfer(accountTransferDetails,
deposit, loanRefundTransaction, accountTransferDTO.getTransactionDate(), transactionMonetaryAmount,
accountTransferDTO.getDescription());
accountTransferDetails.addAccountTransferTransaction(accountTransferTransaction);
return accountTransferDetails;
}
}
@@ -0,0 +1,191 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toOfficeIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.transferTypeParamName;
import java.util.Locale;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.service.LoanAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
@Service
public class AccountTransferDetailAssembler {
private final ClientRepositoryWrapper clientRepository;
private final OfficeRepository officeRepository;
private final SavingsAccountAssembler savingsAccountAssembler;
private final FromJsonHelper fromApiJsonHelper;
private final LoanAssembler loanAccountAssembler;
@Autowired
public AccountTransferDetailAssembler(final ClientRepositoryWrapper clientRepository, final OfficeRepository officeRepository,
final SavingsAccountAssembler savingsAccountAssembler, final FromJsonHelper fromApiJsonHelper,
final LoanAssembler loanAccountAssembler) {
this.clientRepository = clientRepository;
this.officeRepository = officeRepository;
this.savingsAccountAssembler = savingsAccountAssembler;
this.fromApiJsonHelper = fromApiJsonHelper;
this.loanAccountAssembler = loanAccountAssembler;
}
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId);
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId);
return assembleSavingsToSavingsTransfer(command, fromSavingsAccount, toSavingsAccount);
}
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
final Long fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId);
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
return assembleSavingsToLoanTransfer(command, fromSavingsAccount, toLoanAccount);
}
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId);
final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId);
return assembleLoanToSavingsTransfer(command, fromLoanAccount, toSavingsAccount);
}
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
final SavingsAccount toSavingsAccount) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
toSavingsAccount, transfertype);
}
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
final Loan toLoanAccount) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
transfertype);
}
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount,
final SavingsAccount toSavingsAccount) {
final JsonElement element = command.parsedJson();
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
final Office fromOffice = this.officeRepository.findOne(fromOfficeId);
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
final Office toOffice = this.officeRepository.findOne(toOfficeId);
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
return AccountTransferDetails.LoanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
transfertype);
}
public AccountTransferDetails assembleSavingsToLoanTransfer(final SavingsAccount fromSavingsAccount, final Loan toLoanAccount,
Integer transferType) {
final Office fromOffice = fromSavingsAccount.office();
final Client fromClient = fromSavingsAccount.getClient();
final Office toOffice = toLoanAccount.getOffice();
final Client toClient = toLoanAccount.client();
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
transferType);
}
public AccountTransferDetails assembleSavingsToSavingsTransfer(final SavingsAccount fromSavingsAccount,
final SavingsAccount toSavingsAccount, Integer transferType) {
final Office fromOffice = fromSavingsAccount.office();
final Client fromClient = fromSavingsAccount.getClient();
final Office toOffice = toSavingsAccount.office();
final Client toClient = toSavingsAccount.getClient();
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
toSavingsAccount, transferType);
}
public AccountTransferDetails assembleLoanToSavingsTransfer(final Loan fromLoanAccount, final SavingsAccount toSavingsAccount,
Integer transferType) {
final Office fromOffice = fromLoanAccount.getOffice();
final Client fromClient = fromLoanAccount.client();
final Office toOffice = toSavingsAccount.office();
final Client toClient = toSavingsAccount.getClient();
return AccountTransferDetails.LoanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
transferType);
}
}
@@ -0,0 +1,12 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface AccountTransferDetailRepository extends JpaRepository<AccountTransferDetails, Long>,
JpaSpecificationExecutor<AccountTransferDetails> {}
@@ -0,0 +1,153 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_account_transfer_details")
public class AccountTransferDetails extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "from_office_id", nullable = false)
private Office fromOffice;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "from_client_id", nullable = false)
private Client fromClient;
@ManyToOne
@JoinColumn(name = "from_savings_account_id", nullable = true)
private SavingsAccount fromSavingsAccount;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "to_office_id", nullable = false)
private Office toOffice;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "to_client_id", nullable = false)
private Client toClient;
@ManyToOne
@JoinColumn(name = "to_savings_account_id", nullable = true)
private SavingsAccount toSavingsAccount;
@ManyToOne
@JoinColumn(name = "to_loan_account_id", nullable = true)
private Loan toLoanAccount;
@ManyToOne
@JoinColumn(name = "from_loan_account_id", nullable = true)
private Loan fromLoanAccount;
@Column(name = "transfer_type")
private Integer transferType;
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "accountTransferDetails", orphanRemoval = true)
private final List<AccountTransferTransaction> accountTransferTransactions = new ArrayList<AccountTransferTransaction>();
@OneToOne(mappedBy = "accountTransferDetails", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.LAZY)
private AccountTransferStandingInstruction accountTransferStandingInstruction;
public static AccountTransferDetails savingsToSavingsTransfer(final Office fromOffice, final Client fromClient,
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
Integer transferType) {
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, toSavingsAccount, null,
transferType, null);
}
public static AccountTransferDetails savingsToLoanTransfer(final Office fromOffice, final Client fromClient,
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount,
Integer transferType) {
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, null, toLoanAccount,
transferType, null);
}
public static AccountTransferDetails LoanTosavingsTransfer(final Office fromOffice, final Client fromClient,
final Loan fromLoanAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
Integer transferType) {
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, toSavingsAccount, null,
transferType, null);
}
protected AccountTransferDetails() {
//
}
private AccountTransferDetails(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount,
final Loan fromLoanAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
final Loan toLoanAccount, final Integer transferType,
final AccountTransferStandingInstruction accountTransferStandingInstruction) {
this.fromOffice = fromOffice;
this.fromClient = fromClient;
this.fromSavingsAccount = fromSavingsAccount;
this.fromLoanAccount = fromLoanAccount;
this.toOffice = toOffice;
this.toClient = toClient;
this.toSavingsAccount = toSavingsAccount;
this.toLoanAccount = toLoanAccount;
this.transferType = transferType;
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
}
public SavingsAccount toSavingsAccount() {
return this.toSavingsAccount;
}
public SavingsAccount fromSavingsAccount() {
return this.fromSavingsAccount;
}
public void addAccountTransferTransaction(AccountTransferTransaction accountTransferTransaction) {
this.accountTransferTransactions.add(accountTransferTransaction);
}
public void updateAccountTransferStandingInstruction(final AccountTransferStandingInstruction accountTransferStandingInstruction) {
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
}
public Loan toLoanAccount() {
return this.toLoanAccount;
}
public Loan fromLoanAccount() {
return this.fromLoanAccount;
}
public AccountTransferStandingInstruction accountTransferStandingInstruction() {
return this.accountTransferStandingInstruction;
}
public AccountTransferType transferType() {
return AccountTransferType.fromInt(this.transferType);
}
}
@@ -0,0 +1,59 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
/**
* Enum representation of loan status states.
*/
public enum AccountTransferRecurrenceType {
INVALID(0, "accountTransferRecurrenceType.invalid"), //
PERIODIC(1, "accountTransferRecurrenceType.periodic"), //
AS_PER_DUES(2, "accountTransferRecurrenceType.as.per.dues"); //
private final Integer value;
private final String code;
public static AccountTransferRecurrenceType fromInt(final Integer statusValue) {
AccountTransferRecurrenceType enumeration = AccountTransferRecurrenceType.INVALID;
switch (statusValue) {
case 1:
enumeration = AccountTransferRecurrenceType.PERIODIC;
break;
case 2:
enumeration = AccountTransferRecurrenceType.AS_PER_DUES;
break;
}
return enumeration;
}
private AccountTransferRecurrenceType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final AccountTransferRecurrenceType state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isPeriodicRecurrence() {
return this.value.equals(AccountTransferRecurrenceType.PERIODIC.getValue());
}
public boolean isDuesRecurrence() {
return this.value.equals(AccountTransferRecurrenceType.AS_PER_DUES.getValue());
}
}
@@ -12,14 +12,14 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface AccountTransferRepository extends JpaRepository<AccountTransfer, Long>, JpaSpecificationExecutor<AccountTransfer> {
public interface AccountTransferRepository extends JpaRepository<AccountTransferTransaction, Long>, JpaSpecificationExecutor<AccountTransferTransaction> {
@Query("from AccountTransfer at where at.fromLoanAccount.id= :accountNumber and at.reversed=false")
List<AccountTransfer> findByFromLoanId(@Param("accountNumber") Long accountNumber);
@Query("from AccountTransferTransaction att where att.accountTransferDetails.fromLoanAccount.id= :accountNumber and att.reversed=false")
List<AccountTransferTransaction> findByFromLoanId(@Param("accountNumber") Long accountNumber);
@Query("from AccountTransfer at where (at.fromLoanAccount.id= :accountNumber or at.toLoanAccount.id=:accountNumber) and at.reversed=false")
List<AccountTransfer> findAllByLoanId(@Param("accountNumber") Long accountNumber);
@Query("from AccountTransferTransaction att where (att.accountTransferDetails.fromLoanAccount.id= :accountNumber or att.accountTransferDetails.toLoanAccount.id=:accountNumber) and att.reversed=false")
List<AccountTransferTransaction> findAllByLoanId(@Param("accountNumber") Long accountNumber);
@Query("from AccountTransfer at where at.toLoanTransaction.id= :loanTransactionId and at.reversed=false")
AccountTransfer findByToLoanTransactionId(@Param("loanTransactionId") Long loanTransactionId);
@Query("from AccountTransferTransaction att where att.toLoanTransaction.id= :loanTransactionId and att.reversed=false")
AccountTransferTransaction findByToLoanTransactionId(@Param("loanTransactionId") Long loanTransactionId);
}
@@ -0,0 +1,278 @@
package org.mifosplatform.portfolio.account.domain;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.transferTypeParamName;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import org.joda.time.LocalDate;
import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_account_transfer_standing_instructions", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name") })
public class AccountTransferStandingInstruction extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "account_transfer_details_id", nullable = true)
private AccountTransferDetails accountTransferDetails;
@SuppressWarnings("unused")
@Column(name = "name")
private String name;
@Column(name = "priority")
private Integer priority;
@Column(name = "instruction_type")
private Integer instructionType;
@Column(name = "status")
private Integer status;
@Column(name = "amount", scale = 6, precision = 19, nullable = true)
private BigDecimal amount;
@Temporal(TemporalType.DATE)
@Column(name = "valid_from")
private Date validFrom;
@Temporal(TemporalType.DATE)
@Column(name = "valid_till")
private Date validTill;
@Column(name = "recurrence_type")
private Integer recurrenceType;
@Column(name = "recurrence_frequency")
private Integer recurrenceFrequency;
@Column(name = "recurrence_interval")
private Integer recurrenceInterval;
@Column(name = "recurrence_on_day")
private Integer recurrenceOnDay;
@Column(name = "recurrence_on_month")
private Integer recurrenceOnMonth;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "last_run_date")
private Date latsRunDate;
protected AccountTransferStandingInstruction() {
}
public static AccountTransferStandingInstruction create(final AccountTransferDetails accountTransferDetails, final String name,
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount,
final LocalDate validFrom, final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency,
final Integer recurrenceInterval, final MonthDay recurrenceOnMonthDay) {
Integer recurrenceOnDay = null;
Integer recurrenceOnMonth = null;
if (recurrenceOnMonthDay != null) {
recurrenceOnDay = recurrenceOnMonthDay.getDayOfMonth();
recurrenceOnMonth = recurrenceOnMonthDay.getMonthOfYear();
}
return new AccountTransferStandingInstruction(accountTransferDetails, name, priority, instructionType, status, amount, validFrom,
validTill, recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnDay, recurrenceOnMonth);
}
private AccountTransferStandingInstruction(final AccountTransferDetails accountTransferDetails, final String name,
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount,
final LocalDate validFrom, final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency,
final Integer recurrenceInterval, final Integer recurrenceOnDay, final Integer recurrenceOnMonth) {
this.accountTransferDetails = accountTransferDetails;
this.name = name;
this.priority = priority;
this.instructionType = instructionType;
this.status = status;
this.amount = amount;
if (validFrom != null) {
this.validFrom = validFrom.toDate();
}
if (validTill == null) {
this.validTill = null;
} else {
this.validTill = validTill.toDate();
}
this.recurrenceType = recurrenceType;
this.recurrenceFrequency = recurrenceFrequency;
this.recurrenceInterval = recurrenceInterval;
this.recurrenceOnDay = recurrenceOnDay;
this.recurrenceOnMonth = recurrenceOnMonth;
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
validateDependencies(baseDataValidator);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
public Map<String, Object> update(JsonCommand command) {
final Map<String, Object> actualChanges = new HashMap<String, Object>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
if (StandingInstructionStatus.fromInt(this.status).isDeleted()) {
baseDataValidator.reset().parameter(statusParamName).failWithCode("can.not.modify.once.deleted");
}
if (command.isChangeInDateParameterNamed(validFromParamName, this.validFrom)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(validFromParamName);
actualChanges.put(validFromParamName, newValue);
this.validFrom = newValue.toDate();
}
if (command.isChangeInDateParameterNamed(validTillParamName, this.validTill)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(validTillParamName);
actualChanges.put(validTillParamName, newValue);
this.validTill = newValue.toDate();
}
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName);
actualChanges.put(amountParamName, newValue);
this.amount = newValue;
}
if (command.isChangeInIntegerParameterNamed(statusParamName, this.status)) {
final Integer newValue = command.integerValueOfParameterNamed(statusParamName);
actualChanges.put(statusParamName, newValue);
this.status = newValue;
}
if (command.isChangeInIntegerParameterNamed(priorityParamName, this.priority)) {
final Integer newValue = command.integerValueOfParameterNamed(priorityParamName);
actualChanges.put(priorityParamName, newValue);
this.priority = newValue;
}
if (command.isChangeInIntegerParameterNamed(instructionTypeParamName, this.instructionType)) {
final Integer newValue = command.integerValueOfParameterNamed(instructionTypeParamName);
actualChanges.put(instructionTypeParamName, newValue);
this.instructionType = newValue;
}
if (command.isChangeInIntegerParameterNamed(recurrenceTypeParamName, this.recurrenceType)) {
final Integer newValue = command.integerValueOfParameterNamed(recurrenceTypeParamName);
actualChanges.put(recurrenceTypeParamName, newValue);
this.recurrenceType = newValue;
}
if (command.isChangeInIntegerParameterNamed(recurrenceFrequencyParamName, this.recurrenceFrequency)) {
final Integer newValue = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
actualChanges.put(recurrenceFrequencyParamName, newValue);
this.recurrenceFrequency = newValue;
}
if (command.hasParameter(recurrenceOnMonthDayParamName)) {
final MonthDay monthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
final String actualValueEntered = command.stringValueOfParameterNamed(recurrenceOnMonthDayParamName);
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
if (this.recurrenceOnDay != dayOfMonthValue) {
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
this.recurrenceOnDay = dayOfMonthValue;
}
final Integer monthOfYear = monthDay.getMonthOfYear();
if (this.recurrenceOnMonth != monthOfYear) {
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
this.recurrenceOnMonth = monthOfYear;
}
}
if (command.isChangeInIntegerParameterNamed(recurrenceIntervalParamName, this.recurrenceInterval)) {
final Integer newValue = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
actualChanges.put(recurrenceIntervalParamName, newValue);
this.recurrenceInterval = newValue;
}
validateDependencies(baseDataValidator);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
return actualChanges;
}
private void validateDependencies(final DataValidatorBuilder baseDataValidator) {
if (this.validTill != null && this.validFrom != null) {
baseDataValidator.reset().parameter(validTillParamName).value(LocalDate.fromDateFields(this.validTill))
.validateDateAfter(LocalDate.fromDateFields(this.validFrom));
}
if (AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence()) {
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(this.recurrenceFrequency).notNull();
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(this.recurrenceInterval).notNull();
if (this.recurrenceFrequency != null) {
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(this.recurrenceFrequency);
if (frequencyType.isMonthly()) {
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
} else if (frequencyType.isYearly()) {
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnMonth).notNull();
}
}
}
if (this.accountTransferDetails.toSavingsAccount() != null) {
baseDataValidator.reset().parameter(instructionTypeParamName).value(this.instructionType).notNull().inMinMaxRange(1, 1);
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(this.recurrenceType).notNull().inMinMaxRange(1, 1);
}
if (StandingInstructionType.fromInt(this.instructionType).isFixedAmoutTransfer()) {
baseDataValidator.reset().parameter(amountParamName).value(this.amount).notNull();
}
String errorCode = null;
if (this.accountTransferDetails.transferType().isAccountTransfer()
&& (this.accountTransferDetails.fromSavingsAccount() == null || this.accountTransferDetails.toSavingsAccount() == null)) {
errorCode = "not.account.transfer";
} else if (this.accountTransferDetails.transferType().isLoanRepayment()
&& (this.accountTransferDetails.fromSavingsAccount() == null || this.accountTransferDetails.toLoanAccount() == null)) {
errorCode = "not.loan.repayment";
}
if (errorCode != null) {
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
}
}
public void updateLatsRunDate(Date latsRunDate) {
this.latsRunDate = latsRunDate;
}
public void updateStatus(Integer status){
this.status = status;
}
}
@@ -0,0 +1,140 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.joda.time.LocalDate;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@Table(name = "m_account_transfer_transaction")
public class AccountTransferTransaction extends AbstractPersistable<Long> {
@ManyToOne
@JoinColumn(name = "account_transfer_details_id", nullable = true)
private AccountTransferDetails accountTransferDetails;
@ManyToOne
@JoinColumn(name = "from_savings_transaction_id", nullable = true)
private SavingsAccountTransaction fromSavingsTransaction;
@ManyToOne
@JoinColumn(name = "to_savings_transaction_id", nullable = true)
private SavingsAccountTransaction toSavingsTransaction;
@ManyToOne
@JoinColumn(name = "to_loan_transaction_id", nullable = true)
private LoanTransaction toLoanTransaction;
@ManyToOne
@JoinColumn(name = "from_loan_transaction_id", nullable = true)
private LoanTransaction fromLoanTransaction;
@SuppressWarnings("unused")
@Column(name = "is_reversed", nullable = false)
private boolean reversed = false;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date")
private Date date;
@SuppressWarnings("unused")
@Embedded
private MonetaryCurrency currency;
@SuppressWarnings("unused")
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@SuppressWarnings("unused")
@Column(name = "description", length = 100)
private String description;
public static AccountTransferTransaction savingsToSavingsTransfer(final AccountTransferDetails accountTransferDetails,
final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
return new AccountTransferTransaction(accountTransferDetails, withdrawal, deposit, null, null, transactionDate, transactionAmount,
description);
}
public static AccountTransferTransaction savingsToLoanTransfer(final AccountTransferDetails accountTransferDetails,
final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
return new AccountTransferTransaction(accountTransferDetails, withdrawal, null, loanRepaymentTransaction, null, transactionDate,
transactionAmount, description);
}
public static AccountTransferTransaction LoanTosavingsTransfer(final AccountTransferDetails accountTransferDetails,
final SavingsAccountTransaction deposit, final LoanTransaction loanRefundTransaction, final LocalDate transactionDate,
final Money transactionAmount, final String description) {
return new AccountTransferTransaction(accountTransferDetails, null, deposit, null, loanRefundTransaction, transactionDate,
transactionAmount, description);
}
protected AccountTransferTransaction() {
//
}
private AccountTransferTransaction(final AccountTransferDetails accountTransferDetails, final SavingsAccountTransaction withdrawal,
final SavingsAccountTransaction deposit, final LoanTransaction loanRepaymentTransaction,
final LoanTransaction loanRefundTransaction, final LocalDate transactionDate, final Money transactionAmount,
final String description) {
this.accountTransferDetails = accountTransferDetails;
this.fromLoanTransaction = loanRefundTransaction;
this.fromSavingsTransaction = withdrawal;
this.toSavingsTransaction = deposit;
this.toLoanTransaction = loanRepaymentTransaction;
this.date = transactionDate.toDate();
this.currency = transactionAmount.getCurrency();
this.amount = transactionAmount.getAmountDefaultedToNullIfZero();
this.description = description;
}
public LoanTransaction getFromLoanTransaction() {
return this.fromLoanTransaction;
}
public SavingsAccountTransaction getFromTransaction() {
return this.fromSavingsTransaction;
}
public LoanTransaction getToLoanTransaction() {
return this.toLoanTransaction;
}
public SavingsAccountTransaction getToSavingsTransaction() {
return this.toSavingsTransaction;
}
public void reverse() {
this.reversed = true;
}
public void updateToLoanTransaction(LoanTransaction toLoanTransaction) {
this.toLoanTransaction = toLoanTransaction;
}
public AccountTransferDetails accountTransferDetails() {
return this.accountTransferDetails;
}
}
@@ -0,0 +1,66 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
/**
* Enum representation of loan status states.
*/
public enum AccountTransferType {
INVALID(0, "accountTransferType.invalid"), //
ACCOUNT_TRANSFER(1, "accountTransferType.account.transfer"), //
LOAN_REPAYMENT(2, "accountTransferType.loan.repayment"), //
CHARGE_PAYMENT(3, "accountTransferType.charge.payment"); //
private final Integer value;
private final String code;
public static AccountTransferType fromInt(final Integer statusValue) {
AccountTransferType enumeration = AccountTransferType.INVALID;
switch (statusValue) {
case 1:
enumeration = AccountTransferType.ACCOUNT_TRANSFER;
break;
case 2:
enumeration = AccountTransferType.LOAN_REPAYMENT;
break;
case 3:
enumeration = AccountTransferType.CHARGE_PAYMENT;
break;
}
return enumeration;
}
private AccountTransferType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final AccountTransferType state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isAccountTransfer() {
return this.value.equals(AccountTransferType.ACCOUNT_TRANSFER.getValue());
}
public boolean isLoanRepayment() {
return this.value.equals(AccountTransferType.LOAN_REPAYMENT.getValue());
}
public boolean isChargePayment() {
return this.value.equals(AccountTransferType.CHARGE_PAYMENT.getValue());
}
}
@@ -0,0 +1,81 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.nameParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StandingInstructionAssembler {
private final AccountTransferDetailAssembler accountTransferDetailAssembler;
@Autowired
public StandingInstructionAssembler(final AccountTransferDetailAssembler accountTransferDetailAssembler) {
this.accountTransferDetailAssembler = accountTransferDetailAssembler;
}
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToSavingsTransfer(command);
assembleStandingInstruction(command, accountTransferDetails);
return accountTransferDetails;
}
public void assembleStandingInstruction(final JsonCommand command, final AccountTransferDetails accountTransferDetails) {
final LocalDate validFrom = command.localDateValueOfParameterNamed(validFromParamName);
final LocalDate validTill = command.localDateValueOfParameterNamed(validTillParamName);
BigDecimal amount = null;
final BigDecimal transferAmount = command.bigDecimalValueOfParameterNamed(amountParamName);
if (transferAmount != null) {
final Money monetaryAmount = Money.of(accountTransferDetails.fromSavingsAccount().getCurrency(), transferAmount);
amount = monetaryAmount.getAmount();
}
final Integer status = command.integerValueOfParameterNamed(statusParamName);
final Integer priority = command.integerValueOfParameterNamed(priorityParamName);
final Integer standingInstructionType = command.integerValueOfParameterNamed(instructionTypeParamName);
final Integer recurrenceType = command.integerValueOfParameterNamed(recurrenceTypeParamName);
final Integer recurrenceFrequency = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
final MonthDay recurrenceOnMonthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
final Integer recurrenceInterval = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
final String name = command.stringValueOfParameterNamed(nameParamName);
AccountTransferStandingInstruction accountTransferStandingInstruction = AccountTransferStandingInstruction.create(
accountTransferDetails, name, priority, standingInstructionType, status, amount, validFrom, validTill, recurrenceType,
recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay);
accountTransferDetails.updateAccountTransferStandingInstruction(accountTransferStandingInstruction);
}
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToLoanTransfer(command);
assembleStandingInstruction(command, accountTransferDetails);
return accountTransferDetails;
}
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleLoanToSavingsTransfer(command);
assembleStandingInstruction(command, accountTransferDetails);
return accountTransferDetails;
}
}
@@ -0,0 +1,74 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
/**
* Enum representation of loan status states.
*/
public enum StandingInstructionPriority {
INVALID(0, "standingInstructionPriority.invalid"), //
URGENT(1, "standingInstructionPriority.urgent"), //
HIGH(2, "standingInstructionPriority.high"), //
MEDIUM(3, "standingInstructionPriority.medium"), //
LOW(4, "standingInstructionPriority.low");
private final Integer value;
private final String code;
public static StandingInstructionPriority fromInt(final Integer statusValue) {
StandingInstructionPriority enumeration = StandingInstructionPriority.INVALID;
switch (statusValue) {
case 1:
enumeration = StandingInstructionPriority.URGENT;
break;
case 2:
enumeration = StandingInstructionPriority.HIGH;
break;
case 3:
enumeration = StandingInstructionPriority.MEDIUM;
break;
case 4:
enumeration = StandingInstructionPriority.LOW;
break;
}
return enumeration;
}
private StandingInstructionPriority(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final StandingInstructionPriority state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isHighPriority() {
return this.value.equals(StandingInstructionPriority.HIGH.getValue());
}
public boolean isLowPriority() {
return this.value.equals(StandingInstructionPriority.LOW.getValue());
}
public boolean isUrgentPriority() {
return this.value.equals(StandingInstructionPriority.URGENT.getValue());
}
public boolean isMediumPriority() {
return this.value.equals(StandingInstructionPriority.MEDIUM.getValue());
}
}
@@ -0,0 +1,12 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface StandingInstructionRepository extends JpaRepository<AccountTransferStandingInstruction, Long>,
JpaSpecificationExecutor<AccountTransferStandingInstruction> {}
@@ -0,0 +1,67 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
/**
* Enum representation of loan status states.
*/
public enum StandingInstructionStatus {
INVALID(0, "standingInstructionStatus.invalid"), //
ACTIVE(1, "standingInstructionStatus.active"), //
DISABLED(2, "standingInstructionStatus.disabled"), //
DELETED(3, "standingInstructionStatus.deleted");
private final Integer value;
private final String code;
public static StandingInstructionStatus fromInt(final Integer statusValue) {
StandingInstructionStatus enumeration = StandingInstructionStatus.INVALID;
switch (statusValue) {
case 1:
enumeration = StandingInstructionStatus.ACTIVE;
break;
case 2:
enumeration = StandingInstructionStatus.DISABLED;
break;
case 3:
enumeration = StandingInstructionStatus.DELETED;
break;
}
return enumeration;
}
private StandingInstructionStatus(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final StandingInstructionStatus state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isDisabled() {
return this.value.equals(StandingInstructionStatus.DISABLED.getValue());
}
public boolean isDeleted() {
return this.value.equals(StandingInstructionStatus.DELETED.getValue());
}
public boolean isActive() {
return this.value.equals(StandingInstructionStatus.ACTIVE.getValue());
}
}
@@ -0,0 +1,59 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.domain;
/**
* Enum representation of loan status states.
*/
public enum StandingInstructionType {
INVALID(0, "standingInstructionType.invalid"), //
FIXED(1, "standingInstructionType.fixed"), //
DUES(2, "standingInstructionType.dues"); //
private final Integer value;
private final String code;
public static StandingInstructionType fromInt(final Integer statusValue) {
StandingInstructionType enumeration = StandingInstructionType.INVALID;
switch (statusValue) {
case 1:
enumeration = StandingInstructionType.FIXED;
break;
case 2:
enumeration = StandingInstructionType.DUES;
break;
}
return enumeration;
}
private StandingInstructionType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public boolean hasStateOf(final StandingInstructionType state) {
return this.value.equals(state.getValue());
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isFixedAmoutTransfer() {
return this.value.equals(StandingInstructionType.FIXED.getValue());
}
public boolean isDuesAmoutTransfer() {
return this.value.equals(StandingInstructionType.DUES.getValue());
}
}
@@ -0,0 +1,19 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
/**
* A {@link RuntimeException} thrown when loan resources are not found.
*/
public class StandingInstructionNotFoundException extends AbstractPlatformResourceNotFoundException {
public StandingInstructionNotFoundException(final Long id) {
super("error.msg.standinginstruction.id.invalid", "AccountTransferStandingInstruction with identifier " + id + " does not exist",
id);
}
}
@@ -0,0 +1,25 @@
package org.mifosplatform.portfolio.account.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.account.service.StandingInstructionWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CreateStandingInstructionCommandHandler implements NewCommandSourceHandler {
private StandingInstructionWritePlatformService standingInstructionWritePlatformService;
@Autowired
public CreateStandingInstructionCommandHandler(StandingInstructionWritePlatformService standingInstructionWritePlatformService) {
this.standingInstructionWritePlatformService = standingInstructionWritePlatformService;
}
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.standingInstructionWritePlatformService.create(command);
}
}
@@ -0,0 +1,25 @@
package org.mifosplatform.portfolio.account.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.account.service.StandingInstructionWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DeleteStandingInstructionCommandHandler implements NewCommandSourceHandler {
private StandingInstructionWritePlatformService standingInstructionWritePlatformService;
@Autowired
public DeleteStandingInstructionCommandHandler(StandingInstructionWritePlatformService standingInstructionWritePlatformService) {
this.standingInstructionWritePlatformService = standingInstructionWritePlatformService;
}
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.standingInstructionWritePlatformService.delete(command.entityId());
}
}
@@ -0,0 +1,25 @@
package org.mifosplatform.portfolio.account.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.portfolio.account.service.StandingInstructionWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UpdateStandingInstructionCommandHandler implements NewCommandSourceHandler {
private StandingInstructionWritePlatformService standingInstructionWritePlatformService;
@Autowired
public UpdateStandingInstructionCommandHandler(StandingInstructionWritePlatformService standingInstructionWritePlatformService) {
this.standingInstructionWritePlatformService = standingInstructionWritePlatformService;
}
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.standingInstructionWritePlatformService.update(command.entityId(), command);
}
}
@@ -7,6 +7,11 @@ package org.mifosplatform.portfolio.account.service;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.domain.StandingInstructionPriority;
import org.mifosplatform.portfolio.account.domain.StandingInstructionStatus;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
public class AccountTransferEnumerations {
@@ -35,4 +40,137 @@ public class AccountTransferEnumerations {
return optionData;
}
public static EnumOptionData recurrenceType(final Integer type) {
return recurrenceType(AccountTransferRecurrenceType.fromInt(type));
}
public static EnumOptionData recurrenceType(final AccountTransferRecurrenceType type) {
EnumOptionData optionData = null;
if (type != null) {
switch (type) {
case INVALID:
break;
case PERIODIC:
optionData = new EnumOptionData(AccountTransferRecurrenceType.PERIODIC.getValue().longValue(),
AccountTransferRecurrenceType.PERIODIC.getCode(), "Periodic Recurrence");
break;
case AS_PER_DUES:
optionData = new EnumOptionData(AccountTransferRecurrenceType.AS_PER_DUES.getValue().longValue(),
AccountTransferRecurrenceType.AS_PER_DUES.getCode(), "As Per Dues Recurrence");
break;
}
}
return optionData;
}
public static EnumOptionData transferType(final Integer type) {
return transferType(AccountTransferType.fromInt(type));
}
public static EnumOptionData transferType(final AccountTransferType type) {
EnumOptionData optionData = null;
if (type != null) {
switch (type) {
case INVALID:
break;
case ACCOUNT_TRANSFER:
optionData = new EnumOptionData(AccountTransferType.ACCOUNT_TRANSFER.getValue().longValue(),
AccountTransferType.ACCOUNT_TRANSFER.getCode(), "Account Transfer");
break;
case LOAN_REPAYMENT:
optionData = new EnumOptionData(AccountTransferType.LOAN_REPAYMENT.getValue().longValue(),
AccountTransferType.LOAN_REPAYMENT.getCode(), "Loan Repayment");
break;
case CHARGE_PAYMENT:
optionData = new EnumOptionData(AccountTransferType.CHARGE_PAYMENT.getValue().longValue(),
AccountTransferType.CHARGE_PAYMENT.getCode(), "Charge Payment");
break;
}
}
return optionData;
}
public static EnumOptionData standingInstructionPriority(final Integer type) {
return standingInstructionPriority(StandingInstructionPriority.fromInt(type));
}
public static EnumOptionData standingInstructionPriority(final StandingInstructionPriority type) {
EnumOptionData optionData = null;
if (type != null) {
switch (type) {
case INVALID:
break;
case HIGH:
optionData = new EnumOptionData(StandingInstructionPriority.HIGH.getValue().longValue(),
StandingInstructionPriority.HIGH.getCode(), "High Priority");
break;
case LOW:
optionData = new EnumOptionData(StandingInstructionPriority.LOW.getValue().longValue(),
StandingInstructionPriority.LOW.getCode(), "Low Priority");
break;
case MEDIUM:
optionData = new EnumOptionData(StandingInstructionPriority.MEDIUM.getValue().longValue(),
StandingInstructionPriority.MEDIUM.getCode(), "Medium Priority");
break;
case URGENT:
optionData = new EnumOptionData(StandingInstructionPriority.URGENT.getValue().longValue(),
StandingInstructionPriority.URGENT.getCode(), "Urgent Priority");
break;
}
}
return optionData;
}
public static EnumOptionData standingInstructionStatus(final Integer type) {
return standingInstructionStatus(StandingInstructionStatus.fromInt(type));
}
public static EnumOptionData standingInstructionStatus(final StandingInstructionStatus type) {
EnumOptionData optionData = null;
if (type != null) {
switch (type) {
case INVALID:
break;
case ACTIVE:
optionData = new EnumOptionData(StandingInstructionStatus.ACTIVE.getValue().longValue(),
StandingInstructionStatus.ACTIVE.getCode(), "Active");
break;
case DELETED:
optionData = new EnumOptionData(StandingInstructionStatus.DELETED.getValue().longValue(),
StandingInstructionStatus.DELETED.getCode(), "Deleted");
break;
case DISABLED:
optionData = new EnumOptionData(StandingInstructionStatus.DISABLED.getValue().longValue(),
StandingInstructionStatus.DISABLED.getCode(), "Disabled");
break;
}
}
return optionData;
}
public static EnumOptionData standingInstructionType(final Integer type) {
return standingInstructionType(StandingInstructionType.fromInt(type));
}
public static EnumOptionData standingInstructionType(final StandingInstructionType type) {
EnumOptionData optionData = null;
if (type != null) {
switch (type) {
case INVALID:
break;
case DUES:
optionData = new EnumOptionData(StandingInstructionType.DUES.getValue().longValue(),
StandingInstructionType.DUES.getCode(), "Dues");
break;
case FIXED:
optionData = new EnumOptionData(StandingInstructionType.FIXED.getValue().longValue(),
StandingInstructionType.FIXED.getCode(), "Fixed");
break;
}
}
return optionData;
}
}
@@ -15,9 +15,11 @@ public interface AccountTransfersReadPlatformService {
AccountTransferData retrieveTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType);
Page<AccountTransferData> retrieveAll(SearchParameters searchParameters);
Page<AccountTransferData> retrieveAll(SearchParameters searchParameters, Long accountDetailId);
AccountTransferData retrieveOne(Long transferId);
boolean isAccountTransfer(Long transactionId, PortfolioAccountType accountType);
Page<AccountTransferData> retrieveByStandingInstruction(Long id, SearchParameters searchParameters);
}
@@ -188,11 +188,16 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
}
@Override
public Page<AccountTransferData> retrieveAll(final SearchParameters searchParameters) {
public Page<AccountTransferData> retrieveAll(final SearchParameters searchParameters,final Long accountDetailId) {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlBuilder.append(this.accountTransfersMapper.schema());
Object[] finalObjectArray = {};
if(accountDetailId != null){
sqlBuilder.append(" where att.account_transfer_details_id=?");
finalObjectArray = new Object[]{ accountDetailId };
}
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
@@ -209,9 +214,6 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
}
}
final Object[] objectArray = new Object[2];
final int arrayPos = 0;
final Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos);
final String sqlCountRows = "SELECT FOUND_ROWS()";
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
this.accountTransfersMapper);
@@ -221,7 +223,7 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
public AccountTransferData retrieveOne(final Long transferId) {
try {
final String sql = "select " + this.accountTransfersMapper.schema() + " where sat.id = ?";
final String sql = "select " + this.accountTransfersMapper.schema() + " where att.id = ?";
return this.jdbcTemplate.queryForObject(sql, this.accountTransfersMapper, new Object[] { transferId });
} catch (final EmptyResultDataAccessException e) {
@@ -235,11 +237,11 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
public AccountTransfersMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("sat.id as id, sat.is_reversed as isReversed,");
sqlBuilder.append("sat.transaction_date as transferDate, sat.amount as transferAmount,");
sqlBuilder.append("sat.description as transferDescription,");
sqlBuilder.append("sat.currency_code as currencyCode, sat.currency_digits as currencyDigits,");
sqlBuilder.append("sat.currency_multiplesof as inMultiplesOf, ");
sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
sqlBuilder.append("att.transaction_date as transferDate, att.amount as transferAmount,");
sqlBuilder.append("att.description as transferDescription,");
sqlBuilder.append("att.currency_code as currencyCode, att.currency_digits as currencyDigits,");
sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
@@ -254,18 +256,21 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
sqlBuilder.append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
sqlBuilder.append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
sqlBuilder.append(" FROM m_savings_account_transfer sat ");
sqlBuilder.append("join m_currency curr on curr.code = sat.currency_code ");
sqlBuilder.append("join m_office fromoff on fromoff.id = sat.from_office_id ");
sqlBuilder.append("join m_office tooff on tooff.id = sat.to_office_id ");
sqlBuilder.append("join m_client fromclient on fromclient.id = sat.from_client_id ");
sqlBuilder.append("join m_client toclient on toclient.id = sat.to_client_id ");
sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = sat.from_savings_account_id ");
sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id = sat.from_loan_account_id ");
sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = sat.to_savings_account_id ");
sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = sat.to_loan_account_id ");
sqlBuilder.append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = sat.from_savings_transaction_id ");
sqlBuilder.append("left join m_savings_account_transaction tosavtran on tosavtran.id = sat.to_savings_transaction_id ");
sqlBuilder.append(" FROM m_account_transfer_transaction att ");
sqlBuilder.append("left join m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
sqlBuilder.append("join m_currency curr on curr.code = att.currency_code ");
sqlBuilder.append("join m_office fromoff on fromoff.id = atd.from_office_id ");
sqlBuilder.append("join m_office tooff on tooff.id = atd.to_office_id ");
sqlBuilder.append("join m_client fromclient on fromclient.id = atd.from_client_id ");
sqlBuilder.append("join m_client toclient on toclient.id = atd.to_client_id ");
sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
sqlBuilder.append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
sqlBuilder.append("left join m_savings_account_transaction tosavtran on tosavtran.id = att.to_savings_transaction_id ");
sqlBuilder.append("left join m_loan_transaction fromloantran on fromloantran.id = att.from_savings_transaction_id ");
sqlBuilder.append("left join m_loan_transaction toloantran on toloantran.id = att.to_savings_transaction_id ");
this.schemaSql = sqlBuilder.toString();
}
@@ -345,7 +350,7 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
@Override
public boolean isAccountTransfer(final Long transactionId, final PortfolioAccountType accountType) {
final StringBuilder sql = new StringBuilder("select count(*) from m_savings_account_transfer at where ");
final StringBuilder sql = new StringBuilder("select count(*) from m_account_transfer_transaction at where ");
if (accountType.isLoanAccount()) {
sql.append("at.from_loan_transaction_id=").append(transactionId).append(" or at.to_loan_transaction_id=").append(transactionId);
} else {
@@ -357,4 +362,37 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
return count > 0;
}
@Override
public Page<AccountTransferData> retrieveByStandingInstruction(final Long id, final SearchParameters searchParameters) {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlBuilder
.append(this.accountTransfersMapper.schema())
.append(" join m_account_transfer_standing_instructions atsi on atsi.account_transfer_details_id = att.account_transfer_details_id ");
sqlBuilder.append(" where atsi.id = ?");
if (searchParameters != null) {
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
}
final Object[] finalObjectArray = { id };
final String sqlCountRows = "SELECT FOUND_ROWS()";
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
this.accountTransfersMapper);
}
}
@@ -5,12 +5,12 @@
*/
package org.mifosplatform.portfolio.account.service;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName;
import static org.mifosplatform.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName;
import java.math.BigDecimal;
import java.util.List;
@@ -25,9 +25,12 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.account.data.AccountTransfersDataValidator;
import org.mifosplatform.portfolio.account.domain.AccountTransfer;
import org.mifosplatform.portfolio.account.domain.AccountTransferAssembler;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetailRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.account.domain.AccountTransferRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferTransaction;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanAccountDomainService;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
@@ -53,13 +56,15 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
private final LoanAssembler loanAccountAssembler;
private final LoanAccountDomainService loanAccountDomainService;
private final SavingsAccountWritePlatformService savingsAccountWritePlatformService;
private final AccountTransferDetailRepository accountTransferDetailRepository;
@Autowired
public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValidator accountTransfersDataValidator,
final AccountTransferAssembler accountTransferAssembler, final AccountTransferRepository accountTransferRepository,
final SavingsAccountAssembler savingsAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService,
final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService,
final SavingsAccountWritePlatformService savingsAccountWritePlatformService) {
final SavingsAccountWritePlatformService savingsAccountWritePlatformService,
final AccountTransferDetailRepository accountTransferDetailRepository) {
this.accountTransfersDataValidator = accountTransfersDataValidator;
this.accountTransferAssembler = accountTransferAssembler;
this.accountTransferRepository = accountTransferRepository;
@@ -68,6 +73,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
this.loanAccountAssembler = loanAssembler;
this.loanAccountDomainService = loanAccountDomainService;
this.savingsAccountWritePlatformService = savingsAccountWritePlatformService;
this.accountTransferDetailRepository = accountTransferDetailRepository;
}
@Transactional
@@ -90,7 +96,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final PaymentDetail paymentDetail = null;
Long fromSavingsAccountId = null;
Long transferTransactionId = null;
Long transferDetailId = null;
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
@@ -105,10 +111,10 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail);
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(command, withdrawal,
deposit);
this.accountTransferRepository.saveAndFlush(transferTransaction);
transferTransactionId = transferTransaction.getId();
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(command,
fromSavingsAccount, toSavingsAccount, withdrawal, deposit);
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferDetailId = accountTransferDetails.getId();
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
//
@@ -124,10 +130,10 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeRepayment(toLoanAccount,
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null);
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToLoanTransfer(command,
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(command,
fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
this.accountTransferRepository.saveAndFlush(transferTransaction);
transferTransactionId = transferTransaction.getId();
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferDetailId = accountTransferDetails.getId();
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
// FIXME - kw - ADD overpaid loan to savings account transfer
@@ -146,16 +152,16 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt,
transactionDate, transactionAmount, paymentDetail);
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleLoanToSavingsTransfer(command,
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleLoanToSavingsTransfer(command,
fromLoanAccount, toSavingsAccount, deposit, loanRefundTransaction);
this.accountTransferRepository.saveAndFlush(transferTransaction);
transferTransactionId = transferTransaction.getId();
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferDetailId = accountTransferDetails.getId();
} else {
}
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(transferTransactionId);
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(transferDetailId);
if (fromAccountType.isSavingsAccount()) {
@@ -168,7 +174,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Override
@Transactional
public void reverseTransfersWithFromAccountType(final Long accountNumber, final PortfolioAccountType accountTypeId) {
List<AccountTransfer> acccountTransfers = null;
List<AccountTransferTransaction> acccountTransfers = null;
if (accountTypeId.isLoanAccount()) {
acccountTransfers = this.accountTransferRepository.findByFromLoanId(accountNumber);
}
@@ -181,7 +187,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Override
@Transactional
public void reverseAllTransactions(final Long accountId, final PortfolioAccountType accountTypeId) {
List<AccountTransfer> acccountTransfers = null;
List<AccountTransferTransaction> acccountTransfers = null;
if (accountTypeId.isLoanAccount()) {
acccountTransfers = this.accountTransferRepository.findAllByLoanId(accountId);
}
@@ -193,20 +199,21 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
/**
* @param acccountTransfers
*/
private void undoTransactions(final List<AccountTransfer> acccountTransfers) {
for (final AccountTransfer accountTransfer : acccountTransfers) {
private void undoTransactions(final List<AccountTransferTransaction> acccountTransfers) {
for (final AccountTransferTransaction accountTransfer : acccountTransfers) {
if (accountTransfer.getFromLoanTransaction() != null) {
this.loanAccountDomainService.reverseTransfer(accountTransfer.getFromLoanTransaction());
} else if (accountTransfer.getToLoanTransaction() != null) {
this.loanAccountDomainService.reverseTransfer(accountTransfer.getToLoanTransaction());
}
if (accountTransfer.getFromTransaction() != null) {
this.savingsAccountWritePlatformService.undoTransaction(accountTransfer.getFromAccount().getId(), accountTransfer
.getFromTransaction().getId(), true);
this.savingsAccountWritePlatformService.undoTransaction(accountTransfer.accountTransferDetails().fromSavingsAccount()
.getId(), accountTransfer.getFromTransaction().getId(), true);
}
if (accountTransfer.getToSavingsTransaction() != null) {
this.savingsAccountWritePlatformService.undoTransaction(accountTransfer.getToSavingsAccount().getId(), accountTransfer
.getToSavingsTransaction().getId(), true);
this.savingsAccountWritePlatformService.undoTransaction(
accountTransfer.accountTransferDetails().toSavingsAccount().getId(), accountTransfer.getToSavingsTransaction()
.getId(), true);
}
accountTransfer.reverse();
this.accountTransferRepository.save(accountTransfer);
@@ -217,25 +224,93 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Transactional
public Long transferFunds(final AccountTransferDTO accountTransferDTO) {
Long transferTransactionId = null;
AccountTransferDetails accountTransferDetails = accountTransferDTO.getAccountTransferDetails();
if (isSavingsToLoanAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
//
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
SavingsAccount fromSavingsAccount = null;
Loan toLoanAccount = null;
if (accountTransferDetails == null) {
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
toLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
} else {
fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
toLoanAccount = accountTransferDetails.toLoanAccount();
this.loanAccountAssembler.setHelpers(toLoanAccount);
}
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), fromSavingsAccount.isWithdrawalFeeApplicableForTransfer());
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
LoanTransaction loanTransaction = null;
final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeChargePayment(toLoanAccount,
accountTransferDTO.getChargeId(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), null, null, accountTransferDTO.getToTransferType(),
accountTransferDTO.getLoanInstallmentNumber());
if (AccountTransferType.fromInt(accountTransferDTO.getTransferType()).isChargePayment()) {
loanTransaction = this.loanAccountDomainService.makeChargePayment(toLoanAccount, accountTransferDTO.getChargeId(),
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), null, null, accountTransferDTO.getToTransferType(),
accountTransferDTO.getLoanInstallmentNumber());
final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToLoanTransfer(accountTransferDTO,
fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
this.accountTransferRepository.saveAndFlush(transferTransaction);
transferTransactionId = transferTransaction.getId();
} else {
loanTransaction = this.loanAccountDomainService.makeRepayment(toLoanAccount, new CommandProcessingResultBuilder(),
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), null, null);
}
accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(accountTransferDTO, fromSavingsAccount,
toLoanAccount, withdrawal, loanTransaction);
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferTransactionId = accountTransferDetails.getId();
} else if (isSavingsToSavingsAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
SavingsAccount fromSavingsAccount = null;
SavingsAccount toSavingsAccount = null;
if (accountTransferDetails == null) {
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
} else {
fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
toSavingsAccount = accountTransferDetails.toSavingsAccount();
this.savingsAccountAssembler.setHelpers(toSavingsAccount);
}
final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal(fromSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail(), fromSavingsAccount.isWithdrawalFeeApplicableForTransfer());
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail());
accountTransferDetails = this.accountTransferAssembler.assembleSavingsToSavingsTransfer(accountTransferDTO, fromSavingsAccount,
toSavingsAccount, withdrawal, deposit);
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferTransactionId = accountTransferDetails.getId();
} else if (isLoanToSavingsAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
Loan fromLoanAccount = null;
SavingsAccount toSavingsAccount = null;
if (accountTransferDetails == null) {
fromLoanAccount = this.loanAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
} else {
fromLoanAccount = accountTransferDetails.fromLoanAccount();
this.loanAccountAssembler.setHelpers(fromLoanAccount);
toSavingsAccount = accountTransferDetails.toSavingsAccount();
this.savingsAccountAssembler.setHelpers(toSavingsAccount);
}
final LoanTransaction loanRefundTransaction = this.loanAccountDomainService.makeRefund(accountTransferDTO.getFromAccountId(),
new CommandProcessingResultBuilder(), accountTransferDTO.getTransactionDate(),
accountTransferDTO.getTransactionAmount(), accountTransferDTO.getPaymentDetail(), null, null);
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount,
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
accountTransferDTO.getPaymentDetail());
accountTransferDetails = this.accountTransferAssembler.assembleLoanToSavingsTransfer(accountTransferDTO, fromLoanAccount,
toSavingsAccount, deposit, loanRefundTransaction);
this.accountTransferDetailRepository.saveAndFlush(accountTransferDetails);
transferTransactionId = accountTransferDetails.getId();
}
return transferTransactionId;
@@ -244,7 +319,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Override
@Transactional
public void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
final AccountTransfer transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
if (transferTransaction != null) {
transferTransaction.updateToLoanTransaction(newLoanTransaction);
this.accountTransferRepository.save(transferTransaction);
@@ -0,0 +1,28 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.service;
import java.util.Collection;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.portfolio.account.data.StandingInstructionDTO;
import org.mifosplatform.portfolio.account.data.StandingInstructionData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDuesData;
public interface StandingInstructionReadPlatformService {
StandingInstructionData retrieveTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType, Integer transferType);
Page<StandingInstructionData> retrieveAll(StandingInstructionDTO standingInstructionDTO);
StandingInstructionData retrieveOne(Long instructionId);
Collection<StandingInstructionData> retrieveAll(Integer status);
StandingInstructionDuesData retriveLoanDuesData(Long loanId);
}
@@ -0,0 +1,575 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.service;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.accountType;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.recurrenceType;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.standingInstructionPriority;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.standingInstructionStatus;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.standingInstructionType;
import static org.mifosplatform.portfolio.account.service.AccountTransferEnumerations.transferType;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate;
import org.joda.time.MonthDay;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.organisation.office.data.OfficeData;
import org.mifosplatform.organisation.office.service.OfficeReadPlatformService;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDTO;
import org.mifosplatform.portfolio.account.data.StandingInstructionData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDuesData;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.domain.StandingInstructionPriority;
import org.mifosplatform.portfolio.account.domain.StandingInstructionStatus;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
import org.mifosplatform.portfolio.account.exception.AccountTransferNotFoundException;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.common.service.CommonEnumerations;
import org.mifosplatform.portfolio.common.service.DropdownReadPlatformService;
import org.mifosplatform.portfolio.group.service.SearchParameters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
public class StandingInstructionReadPlatformServiceImpl implements StandingInstructionReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final ClientReadPlatformService clientReadPlatformService;
private final OfficeReadPlatformService officeReadPlatformService;
private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
private final DropdownReadPlatformService dropdownReadPlatformService;
// mapper
private final StandingInstructionMapper standingInstructionMapper;
// pagination
private final PaginationHelper<StandingInstructionData> paginationHelper = new PaginationHelper<StandingInstructionData>();
@Autowired
public StandingInstructionReadPlatformServiceImpl(final RoutingDataSource dataSource,
final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService,
final DropdownReadPlatformService dropdownReadPlatformService) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.clientReadPlatformService = clientReadPlatformService;
this.officeReadPlatformService = officeReadPlatformService;
this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
this.dropdownReadPlatformService = dropdownReadPlatformService;
this.standingInstructionMapper = new StandingInstructionMapper();
}
@Override
public StandingInstructionData retrieveTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId,
final Integer toAccountType, Integer transferType) {
AccountTransferType accountTransferType = AccountTransferType.INVALID;
if (transferType != null) {
accountTransferType = AccountTransferType.fromInt(transferType);
}
final EnumOptionData loanAccountType = accountType(PortfolioAccountType.LOAN);
final EnumOptionData savingsAccountType = accountType(PortfolioAccountType.SAVINGS);
final Integer mostRelevantFromAccountType = fromAccountType;
Collection<EnumOptionData> fromAccountTypeOptions = null;
Collection<EnumOptionData> toAccountTypeOptions = null;
if (accountTransferType.isAccountTransfer()) {
fromAccountTypeOptions = Arrays.asList(savingsAccountType);
toAccountTypeOptions = Arrays.asList(savingsAccountType);
} else if (accountTransferType.isLoanRepayment()) {
fromAccountTypeOptions = Arrays.asList(savingsAccountType);
toAccountTypeOptions = Arrays.asList(loanAccountType);
} else {
fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType);
toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
}
final Integer mostRelevantToAccountType = toAccountType;
final EnumOptionData fromAccountTypeData = accountType(mostRelevantFromAccountType);
final EnumOptionData toAccountTypeData = accountType(mostRelevantToAccountType);
// from settings
OfficeData fromOffice = null;
ClientData fromClient = null;
PortfolioAccountData fromAccount = null;
OfficeData toOffice = null;
ClientData toClient = null;
PortfolioAccountData toAccount = null;
// template
Collection<PortfolioAccountData> fromAccountOptions = null;
Collection<PortfolioAccountData> toAccountOptions = null;
Long mostRelevantFromOfficeId = fromOfficeId;
Long mostRelevantFromClientId = fromClientId;
Long mostRelevantToOfficeId = toOfficeId;
Long mostRelevantToClientId = toClientId;
if (fromAccountId != null) {
Integer accountType;
if (mostRelevantFromAccountType == 1) {
accountType = PortfolioAccountType.LOAN.getValue();
} else {
accountType = PortfolioAccountType.SAVINGS.getValue();
}
fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, accountType);
// override provided fromClient with client of account
mostRelevantFromClientId = fromAccount.clientId();
}
if (mostRelevantFromClientId != null) {
fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
mostRelevantFromOfficeId = fromClient.officeId();
long[] loanStatus = null;
if (mostRelevantFromAccountType == 1) {
loanStatus = new long[] { 300, 700 };
}
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(mostRelevantFromAccountType,
mostRelevantFromClientId, loanStatus);
}
Collection<OfficeData> fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
Collection<ClientData> fromClientOptions = null;
if (mostRelevantFromOfficeId != null) {
fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
}
// defaults
final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
Collection<ClientData> toClientOptions = null;
if (toAccountId != null && fromAccount != null) {
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
fromAccount.currencyCode());
mostRelevantToClientId = toAccount.clientId();
}
if (mostRelevantToClientId != null) {
toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
mostRelevantToOfficeId = toClient.officeId();
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
}
if (mostRelevantToOfficeId != null) {
toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
if (toClientOptions != null && toClientOptions.size() == 1) {
toClient = new ArrayList<ClientData>(toClientOptions).get(0);
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
}
}
final Collection<EnumOptionData> transferTypeOptions = Arrays.asList(transferType(AccountTransferType.ACCOUNT_TRANSFER),
transferType(AccountTransferType.LOAN_REPAYMENT)/*
* ,
* transferType(
* AccountTransferType
* .
* CHARGE_PAYMENT
* )
*/);
final Collection<EnumOptionData> statusOptions = Arrays.asList(standingInstructionStatus(StandingInstructionStatus.ACTIVE),
standingInstructionStatus(StandingInstructionStatus.DISABLED));
final Collection<EnumOptionData> instructionTypeOptions = Arrays.asList(standingInstructionType(StandingInstructionType.FIXED),
standingInstructionType(StandingInstructionType.DUES));
final Collection<EnumOptionData> priorityOptions = Arrays.asList(standingInstructionPriority(StandingInstructionPriority.URGENT),
standingInstructionPriority(StandingInstructionPriority.HIGH),
standingInstructionPriority(StandingInstructionPriority.MEDIUM),
standingInstructionPriority(StandingInstructionPriority.LOW));
final Collection<EnumOptionData> recurrenceTypeOptions = Arrays.asList(recurrenceType(AccountTransferRecurrenceType.PERIODIC),
recurrenceType(AccountTransferRecurrenceType.AS_PER_DUES));
final Collection<EnumOptionData> recurrenceFrequencyOptions = this.dropdownReadPlatformService.retrievePeriodFrequencyTypeOptions();
return StandingInstructionData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions, transferTypeOptions, statusOptions,
instructionTypeOptions, priorityOptions, recurrenceTypeOptions, recurrenceFrequencyOptions);
}
private Collection<PortfolioAccountData> retrieveToAccounts(final PortfolioAccountData excludeThisAccountFromOptions,
final Integer toAccountType, final Long toClientId) {
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null);
if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions);
} else {
accountOptions = null;
}
return accountOptions;
}
@Override
public Page<StandingInstructionData> retrieveAll(final StandingInstructionDTO standingInstructionDTO) {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlBuilder.append(this.standingInstructionMapper.schema());
if (standingInstructionDTO.transferType() != null || standingInstructionDTO.clientId() != null
|| standingInstructionDTO.clientName() != null) {
sqlBuilder.append(" where ");
}
boolean addAndCaluse = false;
List<Object> paramObj = new ArrayList<Object>();
if (standingInstructionDTO.transferType() != null) {
if (addAndCaluse) {
sqlBuilder.append(" and ");
}
sqlBuilder.append(" atd.transfer_type=? ");
paramObj.add(standingInstructionDTO.transferType());
addAndCaluse = true;
}
if (standingInstructionDTO.clientId() != null) {
if (addAndCaluse) {
sqlBuilder.append(" and ");
}
sqlBuilder.append(" fromclient.id=? ");
paramObj.add(standingInstructionDTO.clientId());
addAndCaluse = true;
} else if (standingInstructionDTO.clientName() != null) {
if (addAndCaluse) {
sqlBuilder.append(" and ");
}
sqlBuilder.append(" fromclient.display_name=? ");
paramObj.add(standingInstructionDTO.clientName());
addAndCaluse = true;
}
if (standingInstructionDTO.fromAccountType() != null && standingInstructionDTO.fromAccount() != null) {
PortfolioAccountType accountType = PortfolioAccountType.fromInt(standingInstructionDTO.fromAccountType());
if (addAndCaluse) {
sqlBuilder.append(" and ");
}
if (accountType.isSavingsAccount()) {
sqlBuilder.append(" fromsavacc.id=? ");
paramObj.add(standingInstructionDTO.fromAccount());
} else if (accountType.isLoanAccount()) {
sqlBuilder.append(" fromloanacc.id=? ");
paramObj.add(standingInstructionDTO.fromAccount());
}
addAndCaluse = true;
}
final SearchParameters searchParameters = standingInstructionDTO.searchParameters();
if (searchParameters.isOrderByRequested()) {
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
if (searchParameters.isSortOrderProvided()) {
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
}
}
if (searchParameters.isLimited()) {
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
if (searchParameters.isOffset()) {
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
}
}
final Object[] finalObjectArray = paramObj.toArray();
final String sqlCountRows = "SELECT FOUND_ROWS()";
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
this.standingInstructionMapper);
}
@Override
public Collection<StandingInstructionData> retrieveAll(final Integer status) {
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select ");
sqlBuilder.append(this.standingInstructionMapper.schema());
sqlBuilder
.append(" where atsi.status=? and CURRENT_DATE() >= atsi.valid_from and (atsi.valid_till IS NULL or CURRENT_DATE() < atsi.valid_till) ")
.append(" and (atsi.last_run_date <> CURRENT_DATE() or atsi.last_run_date IS NULL)")
.append(" ORDER BY atsi.priority DESC");
return this.jdbcTemplate.query(sqlBuilder.toString(), this.standingInstructionMapper, status);
}
@Override
public StandingInstructionData retrieveOne(final Long instructionId) {
try {
final String sql = "select " + this.standingInstructionMapper.schema() + " where atsi.id = ?";
return this.jdbcTemplate.queryForObject(sql, this.standingInstructionMapper, new Object[] { instructionId });
} catch (final EmptyResultDataAccessException e) {
throw new AccountTransferNotFoundException(instructionId);
}
}
@Override
public StandingInstructionDuesData retriveLoanDuesData(final Long loanId) {
final StandingInstructionLoanDuesMapper rm = new StandingInstructionLoanDuesMapper();
final String sql = "select " + rm.schema() + " where ml.id= ? and ls.duedate <= CURRENT_DATE() and ls.completed_derived <> 1";
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { loanId });
}
private static final class StandingInstructionMapper implements RowMapper<StandingInstructionData> {
private final String schemaSql;
public StandingInstructionMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("atsi.id as id,atsi.name as name, atsi.priority as priority,");
sqlBuilder.append("atsi.status as status, atsi.instruction_type as instructionType,");
sqlBuilder.append("atsi.amount as amount,");
sqlBuilder.append("atsi.valid_from as validFrom, atsi.valid_till as validTill,");
sqlBuilder.append("atsi.recurrence_type as recurrenceType, atsi.recurrence_frequency as recurrenceFrequency,");
sqlBuilder.append("atsi.recurrence_interval as recurrenceInterval, atsi.recurrence_on_day as recurrenceOnDay,");
sqlBuilder.append("atsi.recurrence_on_month as recurrenceOnMonth,");
sqlBuilder.append("atd.id as accountDetailId,atd.transfer_type as transferType,");
sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
sqlBuilder.append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
sqlBuilder.append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
sqlBuilder.append("toclient.id as toClientId, toclient.display_name as toClientName,");
sqlBuilder.append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
sqlBuilder.append("fromsp.id as fromProductId, fromsp.name as fromProductName, ");
sqlBuilder.append("fromloanacc.id as fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
sqlBuilder.append("fromlp.id as fromLoanProductId, fromlp.name as fromLoanProductName,");
sqlBuilder.append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
sqlBuilder.append("tosp.id as toProductId, tosp.name as toProductName, ");
sqlBuilder.append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo, ");
sqlBuilder.append("tolp.id as toLoanProductId, tolp.name as toLoanProductName ");
sqlBuilder.append(" FROM m_account_transfer_standing_instructions atsi ");
sqlBuilder.append("join m_account_transfer_details atd on atd.id = atsi.account_transfer_details_id ");
sqlBuilder.append("join m_office fromoff on fromoff.id = atd.from_office_id ");
sqlBuilder.append("join m_office tooff on tooff.id = atd.to_office_id ");
sqlBuilder.append("join m_client fromclient on fromclient.id = atd.from_client_id ");
sqlBuilder.append("join m_client toclient on toclient.id = atd.to_client_id ");
sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
sqlBuilder.append("left join m_savings_product fromsp ON fromsavacc.product_id = fromsp.id ");
sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
sqlBuilder.append("left join m_product_loan fromlp ON fromloanacc.product_id = fromlp.id ");
sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
sqlBuilder.append("left join m_savings_product tosp ON tosavacc.product_id = tosp.id ");
sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
sqlBuilder.append("left join m_product_loan tolp ON toloanacc.product_id = tolp.id ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public StandingInstructionData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long accountDetailId = rs.getLong("accountDetailId");
final String name = rs.getString("name");
final Integer priority = JdbcSupport.getInteger(rs, "priority");
EnumOptionData priorityEnum = AccountTransferEnumerations.standingInstructionPriority(priority);
final Integer status = JdbcSupport.getInteger(rs, "status");
EnumOptionData statusEnum = AccountTransferEnumerations.standingInstructionStatus(status);
final Integer instructionType = JdbcSupport.getInteger(rs, "instructionType");
EnumOptionData instructionTypeEnum = AccountTransferEnumerations.standingInstructionType(instructionType);
final LocalDate validFrom = JdbcSupport.getLocalDate(rs, "validFrom");
final LocalDate validTill = JdbcSupport.getLocalDate(rs, "validTill");
final BigDecimal transferAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "amount");
final Integer recurrenceType = JdbcSupport.getInteger(rs, "recurrenceType");
EnumOptionData recurrenceTypeEnum = AccountTransferEnumerations.recurrenceType(recurrenceType);
final Integer recurrenceFrequency = JdbcSupport.getInteger(rs, "recurrenceFrequency");
EnumOptionData recurrenceFrequencyEnum = null;
if (recurrenceFrequency != null) {
recurrenceFrequencyEnum = CommonEnumerations.termFrequencyType(recurrenceFrequency, "recurrence");
}
final Integer recurrenceInterval = JdbcSupport.getInteger(rs, "recurrenceInterval");
MonthDay recurrenceOnMonthDay = null;
final Integer recurrenceOnDay = JdbcSupport.getInteger(rs, "recurrenceOnDay");
final Integer recurrenceOnMonth = JdbcSupport.getInteger(rs, "recurrenceOnMonth");
if (recurrenceOnDay != null) {
recurrenceOnMonthDay = new MonthDay(recurrenceOnMonth, recurrenceOnDay);
}
final Integer transferType = rs.getInt("transferType");
EnumOptionData transferTypeEnum = AccountTransferEnumerations.transferType(transferType);
/*
* final String currencyCode = rs.getString("currencyCode"); final
* String currencyName = rs.getString("currencyName"); final String
* currencyNameCode = rs.getString("currencyNameCode"); final String
* currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
* final Integer currencyDigits = JdbcSupport.getInteger(rs,
* "currencyDigits"); final Integer inMultiplesOf =
* JdbcSupport.getInteger(rs, "inMultiplesOf"); final CurrencyData
* currency = new CurrencyData(currencyCode, currencyName,
* currencyDigits, inMultiplesOf, currencyDisplaySymbol,
* currencyNameCode);
*/
final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
final String fromOfficeName = rs.getString("fromOfficeName");
final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, fromOfficeName, null);
final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
final String toOfficeName = rs.getString("toOfficeName");
final OfficeData toOffice = OfficeData.dropdown(toOfficeId, toOfficeName, null);
final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
final String fromClientName = rs.getString("fromClientName");
final ClientData fromClient = ClientData.lookup(fromClientId, fromClientName, fromOfficeId, fromOfficeName);
final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
final String toClientName = rs.getString("toClientName");
final ClientData toClient = ClientData.lookup(toClientId, toClientName, toOfficeId, toOfficeName);
final Long fromSavingsAccountId = JdbcSupport.getLong(rs, "fromSavingsAccountId");
final String fromSavingsAccountNo = rs.getString("fromSavingsAccountNo");
final Long fromProductId = JdbcSupport.getLong(rs, "fromProductId");
final String fromProductName = rs.getString("fromProductName");
final Long fromLoanAccountId = JdbcSupport.getLong(rs, "fromLoanAccountId");
final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
final Long fromLoanProductId = JdbcSupport.getLong(rs, "fromLoanProductId");
final String fromLoanProductName = rs.getString("fromLoanProductName");
PortfolioAccountData fromAccount = null;
EnumOptionData fromAccountType = null;
if (fromSavingsAccountId != null) {
fromAccount = new PortfolioAccountData(fromSavingsAccountId, fromSavingsAccountNo, null, null, null, null, null,
fromProductId, fromProductName, null, null, null);
fromAccountType = accountType(PortfolioAccountType.SAVINGS);
} else if (fromLoanAccountId != null) {
fromAccount = new PortfolioAccountData(fromLoanAccountId, fromLoanAccountNo, null, null, null, null, null,
fromLoanProductId, fromLoanProductName, null, null, null);
fromAccountType = accountType(PortfolioAccountType.LOAN);
}
PortfolioAccountData toAccount = null;
EnumOptionData toAccountType = null;
final Long toSavingsAccountId = JdbcSupport.getLong(rs, "toSavingsAccountId");
final String toSavingsAccountNo = rs.getString("toSavingsAccountNo");
final Long toProductId = JdbcSupport.getLong(rs, "toProductId");
final String toProductName = rs.getString("toProductName");
final Long toLoanAccountId = JdbcSupport.getLong(rs, "toLoanAccountId");
final String toLoanAccountNo = rs.getString("toLoanAccountNo");
final Long toLoanProductId = JdbcSupport.getLong(rs, "toLoanProductId");
final String toLoanProductName = rs.getString("toLoanProductName");
if (toSavingsAccountId != null) {
toAccount = new PortfolioAccountData(toSavingsAccountId, toSavingsAccountNo, null, null, null, null, null, toProductId,
toProductName, null, null, null);
toAccountType = accountType(PortfolioAccountType.SAVINGS);
} else if (toLoanAccountId != null) {
toAccount = new PortfolioAccountData(toLoanAccountId, toLoanAccountNo, null, null, null, null, null, toLoanProductId,
toLoanProductName, null, null, null);
toAccountType = accountType(PortfolioAccountType.LOAN);
}
return StandingInstructionData.instance(id, accountDetailId, name, fromOffice, toOffice, fromClient, toClient, fromAccountType,
fromAccount, toAccountType, toAccount, transferTypeEnum, priorityEnum, instructionTypeEnum, statusEnum, transferAmount,
validFrom, validTill, recurrenceTypeEnum, recurrenceFrequencyEnum, recurrenceInterval, recurrenceOnMonthDay);
}
}
private static final class StandingInstructionLoanDuesMapper implements RowMapper<StandingInstructionDuesData> {
private final String schemaSql;
public StandingInstructionLoanDuesMapper() {
final StringBuilder sqlBuilder = new StringBuilder(400);
sqlBuilder.append("max(ls.duedate) as dueDate,sum(ls.principal_amount) as principalAmount,");
sqlBuilder.append("sum(ls.principal_completed_derived) as principalCompleted,");
sqlBuilder.append("sum(ls.principal_writtenoff_derived) as principalWrittenOff,");
sqlBuilder.append("sum(ls.interest_amount) as interestAmount,");
sqlBuilder.append("sum(ls.interest_completed_derived) as interestCompleted,");
sqlBuilder.append("sum(ls.interest_writtenoff_derived) as interestWrittenOff,");
sqlBuilder.append("sum(ls.interest_waived_derived) as interestWaived,");
sqlBuilder.append("sum(ls.penalty_charges_amount) as penalityAmount,");
sqlBuilder.append("sum(ls.penalty_charges_completed_derived) as penalityCompleted,");
sqlBuilder.append("sum(ls.penalty_charges_writtenoff_derived)as penaltyWrittenOff,");
sqlBuilder.append("sum(ls.penalty_charges_waived_derived) as penaltyWaived,");
sqlBuilder.append("sum(ls.fee_charges_amount) as feeAmount,");
sqlBuilder.append("sum(ls.fee_charges_completed_derived) as feecompleted,");
sqlBuilder.append("sum(ls.fee_charges_writtenoff_derived) as feeWrittenOff,");
sqlBuilder.append("sum(ls.fee_charges_waived_derived) as feeWaived ");
sqlBuilder.append("from m_loan_repayment_schedule ls ");
sqlBuilder.append(" join m_loan ml on ml.id = ls.loan_id ");
this.schemaSql = sqlBuilder.toString();
}
public String schema() {
return this.schemaSql;
}
@Override
public StandingInstructionDuesData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
final BigDecimal principalDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalAmount");
final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalCompleted");
final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff");
final BigDecimal principalOutstanding = principalDue.subtract(principalPaid).subtract(principalWrittenOff);
final BigDecimal interestExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestAmount");
final BigDecimal interestPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestCompleted");
final BigDecimal interestWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWrittenOff");
final BigDecimal interestWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWaived");
final BigDecimal interestActualDue = interestExpectedDue.subtract(interestWaived).subtract(interestWrittenOff);
final BigDecimal interestOutstanding = interestActualDue.subtract(interestPaid);
final BigDecimal penaltyChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penalityAmount");
final BigDecimal penaltyChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penalityCompleted");
final BigDecimal penaltyChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyWrittenOff");
final BigDecimal penaltyChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyWaived");
final BigDecimal penaltyChargesActualDue = penaltyChargesExpectedDue.subtract(penaltyChargesWaived).subtract(
penaltyChargesWrittenOff);
final BigDecimal penaltyChargesOutstanding = penaltyChargesActualDue.subtract(penaltyChargesPaid);
final BigDecimal feeChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeAmount");
final BigDecimal feeChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feecompleted");
final BigDecimal feeChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeWrittenOff");
final BigDecimal feeChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeWaived");
final BigDecimal feeChargesActualDue = feeChargesExpectedDue.subtract(feeChargesWaived).subtract(feeChargesWrittenOff);
final BigDecimal feeChargesOutstanding = feeChargesActualDue.subtract(feeChargesPaid);
final BigDecimal totalOutstanding = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding)
.add(penaltyChargesOutstanding);
return new StandingInstructionDuesData(dueDate, totalOutstanding);
}
}
}
@@ -0,0 +1,22 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
public interface StandingInstructionWritePlatformService {
CommandProcessingResult create(JsonCommand command);
CommandProcessingResult update(Long id, JsonCommand command);
void executeStandingInstructions() throws JobExecutionException;
CommandProcessingResult delete(Long id);
}
@@ -0,0 +1,245 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.account.service;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.fromClientIdParamName;
import static org.mifosplatform.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
import static org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.joda.time.LocalDate;
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.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.jobs.annotation.CronTarget;
import org.mifosplatform.infrastructure.jobs.exception.JobExecutionException;
import org.mifosplatform.infrastructure.jobs.service.JobName;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.api.StandingInstructionApiConstants;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.account.data.StandingInstructionData;
import org.mifosplatform.portfolio.account.data.StandingInstructionDataValidator;
import org.mifosplatform.portfolio.account.data.StandingInstructionDuesData;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetailRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferStandingInstruction;
import org.mifosplatform.portfolio.account.domain.StandingInstructionAssembler;
import org.mifosplatform.portfolio.account.domain.StandingInstructionRepository;
import org.mifosplatform.portfolio.account.domain.StandingInstructionStatus;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
import org.mifosplatform.portfolio.account.exception.StandingInstructionNotFoundException;
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
import org.mifosplatform.portfolio.savings.exception.InsufficientAccountBalanceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StandingInstructionWritePlatformServiceImpl implements StandingInstructionWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(StandingInstructionWritePlatformServiceImpl.class);
private final StandingInstructionDataValidator standingInstructionDataValidator;
private final StandingInstructionAssembler standingInstructionAssembler;
private final AccountTransferDetailRepository accountTransferDetailRepository;
private final StandingInstructionRepository standingInstructionRepository;
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
@Autowired
public StandingInstructionWritePlatformServiceImpl(final StandingInstructionDataValidator standingInstructionDataValidator,
final StandingInstructionAssembler standingInstructionAssembler,
final AccountTransferDetailRepository accountTransferDetailRepository,
final StandingInstructionRepository standingInstructionRepository,
final StandingInstructionReadPlatformService standingInstructionReadPlatformService,
final AccountTransfersWritePlatformService accountTransfersWritePlatformService) {
this.standingInstructionDataValidator = standingInstructionDataValidator;
this.standingInstructionAssembler = standingInstructionAssembler;
this.accountTransferDetailRepository = accountTransferDetailRepository;
this.standingInstructionRepository = standingInstructionRepository;
this.standingInstructionReadPlatformService = standingInstructionReadPlatformService;
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult create(final JsonCommand command) {
this.standingInstructionDataValidator.validateForCreate(command);
final Integer fromAccountTypeId = command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName);
final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId);
final Integer toAccountTypeId = command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName);
final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId);
final Long fromClientId = command.longValueOfParameterNamed(fromClientIdParamName);
Long standingInstructionId = null;
try {
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler
.assembleSavingsToSavingsTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command);
this.accountTransferDetailRepository.save(standingInstruction);
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
}
} catch (final DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
}
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(standingInstructionId)
.withClientId(fromClientId);
return builder.build();
}
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
final Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("name")) {
final String name = command.stringValueOfParameterNamed(StandingInstructionApiConstants.nameParamName);
throw new PlatformDataIntegrityException("error.msg.standinginstruction.duplicate.name", "Standinginstruction with name `"
+ name + "` already exists", "name", name);
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.client.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
}
private boolean isSavingsToLoanAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
return fromAccountType.isSavingsAccount() && toAccountType.isLoanAccount();
}
private boolean isSavingsToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
return fromAccountType.isSavingsAccount() && toAccountType.isSavingsAccount();
}
@Override
public CommandProcessingResult update(final Long id, final JsonCommand command) {
this.standingInstructionDataValidator.validateForUpdate(command);
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findOne(id);
if (standingInstructionsForUpdate == null) { throw new StandingInstructionNotFoundException(id); }
final Map<String, Object> actualChanges = standingInstructionsForUpdate.update(command);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(id) //
.with(actualChanges) //
.build();
}
@Override
public CommandProcessingResult delete(final Long id) {
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findOne(id);
standingInstructionsForUpdate.updateStatus(StandingInstructionStatus.DELETED.getValue());
final Map<String, Object> actualChanges = new HashMap<String, Object>();
actualChanges.put(statusParamName, StandingInstructionStatus.DELETED.getValue());
return new CommandProcessingResultBuilder() //
.withEntityId(id) //
.with(actualChanges) //
.build();
}
@Override
@CronTarget(jobName = JobName.EXECUTE_STANDING_INSTRUCTIONS)
public void executeStandingInstructions() throws JobExecutionException {
Collection<StandingInstructionData> instructionDatas = this.standingInstructionReadPlatformService
.retrieveAll(StandingInstructionStatus.ACTIVE.getValue());
final StringBuilder sb = new StringBuilder();
for (StandingInstructionData data : instructionDatas) {
boolean isDueForTransfer = false;
AccountTransferRecurrenceType recurrenceType = data.recurrenceType();
StandingInstructionType instructionType = data.instructionType();
LocalDate transactionDate = new LocalDate();
if (recurrenceType.isPeriodicRecurrence()) {
final ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
PeriodFrequencyType frequencyType = data.recurrenceFrequency();
LocalDate startDate = data.validFrom();
if (frequencyType.isMonthly()) {
startDate = startDate.withDayOfMonth(data.recurrenceOnDay());
if (startDate.isBefore(data.validFrom())) {
startDate = startDate.plusMonths(1);
}
} else if (frequencyType.isYearly()) {
startDate = startDate.withDayOfMonth(data.recurrenceOnDay()).withMonthOfYear(data.recurrenceOnMonth());
if (startDate.isBefore(data.validFrom())) {
startDate = startDate.plusYears(1);
}
}
isDueForTransfer = scheduledDateGenerator.isDateFallsInSchedule(frequencyType, data.recurrenceInterval(), startDate,
transactionDate);
}
BigDecimal transactionAmount = data.amount();
if (data.toAccountType().isLoanAccount()
&& (recurrenceType.isDuesRecurrence() || (isDueForTransfer && instructionType.isDuesAmoutTransfer()))) {
StandingInstructionDuesData standingInstructionDuesData = this.standingInstructionReadPlatformService
.retriveLoanDuesData(data.toAccount().accountId());
if (data.instructionType().isDuesAmoutTransfer()) {
transactionAmount = standingInstructionDuesData.totalDueAmount();
}
if (recurrenceType.isDuesRecurrence()) {
isDueForTransfer = new LocalDate().equals(standingInstructionDuesData.dueDate());
}
}
if (isDueForTransfer && transactionAmount != null && transactionAmount.compareTo(BigDecimal.ZERO) > 0) {
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailRepository.findOne(data.accountDetailId());
accountTransferDetails.accountTransferStandingInstruction().updateLatsRunDate(transactionDate.toDate());
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
data.toAccountType(), data.fromAccount().accountId(), data.toAccount().accountId(), data.name()
+ " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null, data
.transferType().getValue(), accountTransferDetails);
transferAmount(sb, accountTransferDTO, data.getId());
}
}
if (sb.length() > 0) { throw new JobExecutionException(sb.toString()); }
}
/**
* @param sb
* @param accountTransferDTO
*/
private void transferAmount(final StringBuilder sb, final AccountTransferDTO accountTransferDTO, final Long instructionId) {
try {
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} catch (final PlatformApiDataValidationException e) {
sb.append("Validation exception while trasfering funds for standing Instruction id").append(instructionId).append(" from ")
.append(accountTransferDTO.getFromAccountId()).append(" to ").append(accountTransferDTO.getToAccountId())
.append("--------");
} catch (final InsufficientAccountBalanceException e) {
sb.append("InsufficientAccountBalance Exception while trasfering funds for standing Instruction id").append(instructionId)
.append(" from ").append(accountTransferDTO.getFromAccountId()).append(" to ")
.append(accountTransferDTO.getToAccountId()).append("--------");
}
}
}
@@ -5,6 +5,7 @@
*/
package org.mifosplatform.portfolio.common.domain;
public enum PeriodFrequencyType {
DAYS(0, "periodFrequencyType.days"), //
WEEKS(1, "periodFrequencyType.weeks"), //
@@ -48,4 +49,12 @@ public enum PeriodFrequencyType {
}
return repaymentFrequencyType;
}
public boolean isMonthly() {
return this.value.equals(PeriodFrequencyType.MONTHS.getValue());
}
public boolean isYearly() {
return this.value.equals(PeriodFrequencyType.MONTHS.getValue());
}
}
@@ -24,6 +24,10 @@ public class CommonEnumerations {
optionData = new EnumOptionData(PeriodFrequencyType.MONTHS.getValue().longValue(), codePrefix
+ PeriodFrequencyType.MONTHS.getCode(), "Months");
break;
case YEARS:
optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(), codePrefix
+ PeriodFrequencyType.YEARS.getCode(), "Years");
break;
default:
optionData = new EnumOptionData(PeriodFrequencyType.INVALID.getValue().longValue(), PeriodFrequencyType.INVALID.getCode(),
"Invalid");
@@ -1,6 +1,6 @@
package org.mifosplatform.portfolio.common.service;
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.loanTermFrequencyType;
import static org.mifosplatform.portfolio.common.service.CommonEnumerations.termFrequencyType;
import java.util.Arrays;
import java.util.List;
@@ -10,13 +10,13 @@ import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
import org.springframework.stereotype.Service;
@Service
public class DropdownReadPlatformServiceImpl implements DropdownReadPlatformService{
public class DropdownReadPlatformServiceImpl implements DropdownReadPlatformService {
@Override
public List<EnumOptionData> retrievePeriodFrequencyTypeOptions() {
final List<EnumOptionData> loanTermFrequencyOptions = Arrays.asList(loanTermFrequencyType(PeriodFrequencyType.DAYS),
loanTermFrequencyType(PeriodFrequencyType.WEEKS), loanTermFrequencyType(PeriodFrequencyType.MONTHS),
loanTermFrequencyType(PeriodFrequencyType.YEARS));
final List<EnumOptionData> loanTermFrequencyOptions = Arrays.asList(termFrequencyType(PeriodFrequencyType.DAYS, "frequency"),
termFrequencyType(PeriodFrequencyType.WEEKS, "frequency"), termFrequencyType(PeriodFrequencyType.MONTHS, "frequency"),
termFrequencyType(PeriodFrequencyType.YEARS, "frequency"));
return loanTermFrequencyOptions;
}
@@ -28,8 +28,8 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper;
import org.mifosplatform.portfolio.account.domain.AccountTransfer;
import org.mifosplatform.portfolio.account.domain.AccountTransferRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferTransaction;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.exception.ClientNotActiveException;
import org.mifosplatform.portfolio.group.domain.Group;
@@ -277,7 +277,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
}
private void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
final AccountTransfer transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
if (transferTransaction != null) {
transferTransaction.updateToLoanTransaction(newLoanTransaction);
this.accountTransferRepository.save(transferTransaction);
@@ -7,7 +7,11 @@ package org.mifosplatform.portfolio.loanaccount.loanschedule.domain;
import java.util.List;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.joda.time.Weeks;
import org.joda.time.Years;
import org.mifosplatform.organisation.holiday.domain.Holiday;
import org.mifosplatform.organisation.holiday.service.HolidayUtil;
import org.mifosplatform.organisation.workingdays.domain.WorkingDays;
@@ -81,6 +85,45 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
return dueRepaymentPeriodDate;
}
@Override
public Boolean isDateFallsInSchedule(final PeriodFrequencyType frequency, final int repaidEvery, final LocalDate startDate,
final LocalDate date) {
boolean isScheduledDate = false;
switch (frequency) {
case DAYS:
int diff = Days.daysBetween(startDate, date).getDays();
isScheduledDate = (diff % repaidEvery) == 0;
break;
case WEEKS:
int weekDiff =Weeks.weeksBetween(startDate, date).getWeeks();
isScheduledDate = (weekDiff % repaidEvery) == 0;
if(isScheduledDate){
LocalDate modifiedDate = startDate.plusWeeks(weekDiff);
isScheduledDate = modifiedDate.isEqual(date);
}
break;
case MONTHS:
int monthDiff =Months.monthsBetween(startDate, date).getMonths();
isScheduledDate = (monthDiff % repaidEvery) == 0;
if(isScheduledDate){
LocalDate modifiedDate = startDate.plusMonths(monthDiff);
isScheduledDate = modifiedDate.isEqual(date);
}
break;
case YEARS:
int yearDiff =Years.yearsBetween(startDate, date).getYears();
isScheduledDate = (yearDiff % repaidEvery) == 0;
if(isScheduledDate){
LocalDate modifiedDate = startDate.plusYears(yearDiff);
isScheduledDate = modifiedDate.isEqual(date);
}
break;
case INVALID:
break;
}
return isScheduledDate;
}
@Override
public LocalDate idealDisbursementDateBasedOnFirstRepaymentDate(final PeriodFrequencyType repaymentPeriodFrequencyType,
final int repaidEvery, final LocalDate firstRepaymentDate) {
@@ -27,4 +27,6 @@ public interface ScheduledDateGenerator {
LocalDate getRepaymentPeriodDate(PeriodFrequencyType frequency, int repaidEvery, LocalDate startDate);
Boolean isDateFallsInSchedule(PeriodFrequencyType frequency, int repaidEvery, LocalDate startDate, LocalDate date);
}
@@ -135,6 +135,11 @@ public class LoanAssembler {
return loanAccount;
}
public void setHelpers(final Loan loanAccount) {
loanAccount.setHelpers(defaultLoanLifecycleStateMachine(), this.loanSummaryWrapper,
this.loanRepaymentScheduleTransactionProcessorFactory);
}
public Loan assembleFrom(final JsonCommand command, final AppUser currentUser) {
final JsonElement element = command.parsedJson();
@@ -983,8 +983,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
+ " left JOIN m_payment_detail pd ON tr.payment_detail_id = pd.id"
+ " left join m_code_value cv on pd.payment_type_cv_id = cv.id"
+ " left join m_office office on office.id=tr.office_id"
+ " left join m_savings_account_transfer fromtran on fromtran.from_loan_transaction_id = tr.id "
+ " left join m_savings_account_transfer totran on totran.to_loan_transaction_id = tr.id ";
+ " left join m_account_transfer_transaction fromtran on fromtran.from_loan_transaction_id = tr.id "
+ " left join m_account_transfer_transaction totran on totran.to_loan_transaction_id = tr.id ";
}
@Override
@@ -1071,8 +1071,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
+ " totran.description as toTransferDescription "
+ " from m_loan l join m_loan_transaction tr on tr.loan_id = l.id"
+ " join m_currency rc on rc.`code` = l.currency_code "
+ " left join m_savings_account_transfer fromtran on fromtran.from_loan_transaction_id = tr.id "
+ " left join m_savings_account_transfer totran on totran.to_loan_transaction_id = tr.id ";
+ " left join m_account_transfer_transaction fromtran on fromtran.from_loan_transaction_id = tr.id "
+ " left join m_account_transfer_transaction totran on totran.to_loan_transaction_id = tr.id ";
}
@Override
@@ -47,8 +47,9 @@ import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWr
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.domain.AccountTransfer;
import org.mifosplatform.portfolio.account.domain.AccountTransferRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferTransaction;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
@@ -303,7 +304,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final PortfolioAccountData savingAccountData = this.accountAssociationsReadPlatformService.retriveLoanAssociation(loanId);
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loanId, "Loan Charge Payment",
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null);
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
@@ -460,7 +461,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loan.getId(),
"Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(),
entrySet.getKey(), null);
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
}
@@ -1206,7 +1207,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber);
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber, AccountTransferType.CHARGE_PAYMENT.getValue(), null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
return new CommandProcessingResultBuilder() //
@@ -1241,7 +1242,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
installmentChargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null,
null, LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
installmentChargeData.getInstallmentNumber());
installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null);
transferFeeCharge(sb, accountTransferDTO);
}
}
@@ -1251,7 +1252,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(new LocalDate(),
chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null);
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null);
transferFeeCharge(sb, accountTransferDTO);
}
}
@@ -1916,7 +1917,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
private void updateLoanTransaction(final Long loanTransactionId, final LoanTransaction newLoanTransaction) {
final AccountTransfer transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
final AccountTransferTransaction transferTransaction = this.accountTransferRepository.findByToLoanTransactionId(loanTransactionId);
if (transferTransaction != null) {
transferTransaction.updateToLoanTransaction(newLoanTransaction);
this.accountTransferRepository.save(transferTransaction);
@@ -230,6 +230,10 @@ public class SavingsAccountAssembler {
return account;
}
public void setHelpers(final SavingsAccount account) {
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
}
/**
* Assembles a new {@link SavingsAccount} from JSON details passed in
* request inheriting details where relevant from chosen
@@ -638,8 +638,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
sqlBuilder.append("from m_savings_account sa ");
sqlBuilder.append("join m_savings_account_transaction tr on tr.savings_account_id = sa.id ");
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
sqlBuilder.append("left join m_savings_account_transfer fromtran on fromtran.from_savings_transaction_id = tr.id ");
sqlBuilder.append("left join m_savings_account_transfer totran on totran.to_savings_transaction_id = tr.id ");
sqlBuilder.append("left join m_account_transfer_transaction fromtran on fromtran.from_savings_transaction_id = tr.id ");
sqlBuilder.append("left join m_account_transfer_transaction totran on totran.to_savings_transaction_id = tr.id ");
sqlBuilder.append("left join m_payment_detail pd on tr.payment_detail_id = pd.id ");
sqlBuilder.append("left join m_code_value cv on pd.payment_type_cv_id = cv.id ");