From 878e52c9865b2537d444e01fe7cdcce86dd4df56 Mon Sep 17 00:00:00 2001 From: Vishwas Babu A J Date: Mon, 23 Sep 2013 01:16:37 +0530 Subject: [PATCH] bug fixes for 1.10.2 release --- api-docs/apiLive.htm | 49 +++++++++++++++++-- ...rm_propose_and_accept_client_transfers.sql | 7 +++ ..._account_for_existing_savings_products.sql | 8 +++ mifosng-provider/gradle.properties | 2 +- .../commands/domain/CommandWrapper.java | 4 ++ .../service/CommandWrapperBuilder.java | 9 ++++ .../SynchronousCommandProcessingService.java | 2 + .../client/api/ClientsApiResource.java | 3 ++ .../group/domain/GroupRepositoryWrapper.java | 7 +++ .../SavingsAccountTransactionType.java | 9 ++-- .../SavingsAccountTransactionEnumData.java | 3 +- .../domain/SavingsAccountTransaction.java | 2 +- ...WritePlatformServiceJpaRepositoryImpl.java | 7 +++ .../savings/service/SavingsEnumerations.java | 6 +-- .../transfer/api/TransferApiConstants.java | 3 ++ .../transfer/data/TransfersDataValidator.java | 35 +++++++++++++ ...AndAcceptClientTransferCommandHandler.java | 31 ++++++++++++ .../transfer/service/TransferEventType.java | 4 ++ .../service/TransferWritePlatformService.java | 2 + ...WritePlatformServiceJpaRepositoryImpl.java | 33 ++++++++++++- 20 files changed, 210 insertions(+), 16 deletions(-) create mode 100644 mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql create mode 100644 mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/handler/ProposeAndAcceptClientTransferCommandHandler.java diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index fb7fc2522..80ebad7ea 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -90,7 +90,7 @@
- +

Overview

@@ -239,6 +239,14 @@ + + + clients/{clientId}?command=proposeAndAcceptTransfer + Propose and Accept a Client Transfer + + + + clients/{clientId}/accounts @@ -2286,6 +2294,37 @@ Request Body: } + +
+
+ + +   +
+
+

Propose and Accept a Client Transfer

+

Abstraction over the Propose and Accept Client Transfer API's which enable a user with Data Scope over both the Target and Destination Branches to directly + transfer a Client to the destination Office.

+
+
+ POST https://Domain Name/api/v1/clients/{clientId}?command=proposeAndAcceptTransfer + POST clients/1?command=proposeTransfer +Content-Type: application/json +Request Body: +{ + "destinationOfficeId":"2", + "destinationGroupId":"13", + "staffId":"1", + "note":"Client Relocating to Bangalore" +} + + +{ + "clientId": 2, + "resourceId": 2 +} + +
@@ -8469,7 +8508,7 @@ GET https://DomainName/api/v1/loanproducts/{productId} fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId, - writeOffAccountId + writeOffAccountId, transfersInSuspenseAccountId
Additional Mandatory Fields for Accrual(3) based accounting
@@ -8478,7 +8517,7 @@ GET https://DomainName/api/v1/loanproducts/{productId} fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId, writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId, - receivablePenaltyAccountId + receivablePenaltyAccountId, transfersInSuspenseAccountId
@@ -8543,6 +8582,7 @@ Request Body: "incomeFromFeeAccountId":"37", "incomeFromPenaltyAccountId":"35", "writeOffAccountId":"41", + "transfersInSuspenseAccountId":"4", "paymentChannelToFundSourceMappings": [ { "paymentTypeId": "11", @@ -12323,7 +12363,7 @@ Content-Type: application/json - +
Mandatory Fields for Cash based accounting (accountingRule = 2)
savingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountIdsavingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId

@@ -12384,6 +12424,7 @@ Request Body: "annualFeeOnMonthDay": "01 May", "accountingRule": "2", "savingsReferenceAccountId": "16", + "transfersInSuspenseAccountId": "16", "savingsControlAccountId": "15", "interestOnSavingsAccountId": "18", "incomeFromFeeAccountId": "4", diff --git a/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql b/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql new file mode 100644 index 000000000..215d73c8b --- /dev/null +++ b/mifosng-db/migrations/core_db/V118_3__permissions_form_propose_and_accept_client_transfers.sql @@ -0,0 +1,7 @@ +/**Permissions for proposing and accepting a transfer**/ +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) +VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0); + +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) +VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT_CHECKER', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0); + diff --git a/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql b/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql new file mode 100644 index 000000000..6fbb2e3d4 --- /dev/null +++ b/mifosng-db/migrations/core_db/V118_4__reset_default_transfers_in_suspense_account_for_existing_savings_products.sql @@ -0,0 +1,8 @@ +/***Delete previously set defaults**/ +delete from acc_product_mapping where financial_account_type=10 and product_type=2; + +/***Set the proper defaults**/ +INSERT INTO `acc_product_mapping` (`gl_account_id`,`product_id`,`product_type`,`payment_type`,`charge_id`,`financial_account_type`) +select mapping.gl_account_id,mapping.product_id,mapping.product_type,mapping.payment_type,mapping.charge_id, 10 +from acc_product_mapping mapping +where mapping.financial_account_type = 2 and mapping.product_type=2; \ No newline at end of file diff --git a/mifosng-provider/gradle.properties b/mifosng-provider/gradle.properties index 02ffe6690..9df97c7ed 100644 --- a/mifosng-provider/gradle.properties +++ b/mifosng-provider/gradle.properties @@ -1,2 +1,2 @@ -releaseVersion=1.10.1.RELEASE +releaseVersion=1.10.2.RELEASE diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java index 4975a18c5..279eb0acc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java @@ -612,6 +612,10 @@ public class CommandWrapper { return this.actionName.equalsIgnoreCase("PROPOSETRANSFER") && this.entityName.equalsIgnoreCase("CLIENT"); } + public boolean isProposeAndAcceptClientTransfer() { + return this.actionName.equalsIgnoreCase("PROPOSEANDACCEPTTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT"); + } + public boolean isWithdrawClientTransfer() { return this.actionName.equalsIgnoreCase("WITHDRAWTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT"); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index 362259eb6..650683a41 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -361,6 +361,15 @@ public class CommandWrapperBuilder { this.href = "/clientId/" + clientId + "?command=proposeTransfer"; return this; } + + public CommandWrapperBuilder proposeAndAcceptClientTransfer(final Long clientId) { + this.actionName = "PROPOSEANDACCEPTTRANSFER"; + this.entityName = "CLIENT"; + this.entityId = clientId; + this.clientId = clientId; + this.href = "/clientId/" + clientId + "?command=proposeAndAcceptTransfer"; + return this; + } public CommandWrapperBuilder withdrawClientTransferRequest(final Long clientId) { this.actionName = "WITHDRAWTRANSFER"; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java index 70ad36a57..1940a4322 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java @@ -171,6 +171,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isProposeClientTransfer()) { handler = this.applicationContext.getBean("proposeClientTransferCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isProposeAndAcceptClientTransfer()) { + handler = this.applicationContext.getBean("proposeAndAcceptClientTransferCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isWithdrawClientTransfer()) { handler = this.applicationContext.getBean("withdrawClientTransferCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isAcceptClientTransfer()) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java index 362da5993..c4e23f962 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java @@ -212,6 +212,9 @@ public class ClientsApiResource { } else if (is(commandParam, "proposeTransfer")) { commandRequest = builder.proposeClientTransfer(clientId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + } else if (is(commandParam, "proposeAndAcceptTransfer")) { + commandRequest = builder.proposeAndAcceptClientTransfer(clientId).build(); + result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); } else if (is(commandParam, "withdrawTransfer")) { commandRequest = builder.withdrawClientTransferRequest(clientId).build(); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java index e7c48f926..c45fc7215 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/group/domain/GroupRepositoryWrapper.java @@ -5,6 +5,7 @@ */ package org.mifosplatform.portfolio.group.domain; +import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -31,6 +32,12 @@ public class GroupRepositoryWrapper { return entity; } + public Group findByOfficeWithNotFoundDetection(final Long id, final Office office) { + final Group group = findOneWithNotFoundDetection(id); + if (group.getOffice().getId() != office.getId()) { throw new GroupNotFoundException(id); } + return group; + } + public void save(final Group entity) { this.repository.save(entity); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java index 42c827f72..2b57156ef 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java @@ -19,8 +19,9 @@ public enum SavingsAccountTransactionType { INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), // WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), // ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), // - WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), APPLY_CHARGES(7, "savingsAccountTransactionType.applyCharges"), INITIATE_TRANSFER( - 12, "savingsAccountTransactionType.initiateTransfer"), // + WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), // + PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), // + INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), // APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), // WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), // REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"); @@ -66,7 +67,7 @@ public enum SavingsAccountTransactionType { savingsAccountTransactionType = SavingsAccountTransactionType.WAIVE_CHARGES; break; case 7: - savingsAccountTransactionType = SavingsAccountTransactionType.APPLY_CHARGES; + savingsAccountTransactionType = SavingsAccountTransactionType.PAY_CHARGE; break; case 12: savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER; @@ -105,7 +106,7 @@ public enum SavingsAccountTransactionType { } public boolean isCharge() { - return this.value.equals(SavingsAccountTransactionType.APPLY_CHARGES.getValue()); + return this.value.equals(SavingsAccountTransactionType.PAY_CHARGE.getValue()); } public boolean isWaiveCharge() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java index f82e028e6..da9a442a6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java @@ -35,7 +35,8 @@ public class SavingsAccountTransactionEnumData { this.withdrawal = Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL.getValue()).equals(this.id); this.interestPosting = Long.valueOf(SavingsAccountTransactionType.INTEREST_POSTING.getValue()).equals(this.id); this.feeDeduction = Long.valueOf(SavingsAccountTransactionType.ANNUAL_FEE.getValue()).equals(this.id) - || Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id); + || Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id) + || Long.valueOf(SavingsAccountTransactionType.PAY_CHARGE.getValue()).equals(this.id); this.initiateTransfer = Long.valueOf(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue()).equals(this.id); this.approveTransfer = Long.valueOf(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue()).equals(this.id); this.withdrawTransfer = Long.valueOf(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()).equals(this.id); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java index f5b8d6035..7475e64aa 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java @@ -131,7 +131,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable { public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date, final Money amount) { final boolean isReversed = false; - return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.APPLY_CHARGES.getValue(), date, amount, + return new SavingsAccountTransaction(savingsAccount, office, SavingsAccountTransactionType.PAY_CHARGE.getValue(), date, amount, isReversed); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index f971bc94d..56eeefc9b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -514,6 +514,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi savingsAccount.office(), transferDate); savingsAccount.getTransactions().add(newTransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); + final MathContext mc = MathContext.DECIMAL64; + savingsAccount.calculateInterestUsing(mc, transferDate); this.savingsAccountTransactionRepository.save(newTransferTransaction); this.savingAccountRepository.save(savingsAccount); @@ -534,6 +536,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi savingsAccount.office(), transferDate); savingsAccount.getTransactions().add(withdrawtransferTransaction); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); + final MathContext mc = MathContext.DECIMAL64; + savingsAccount.calculateInterestUsing(mc, transferDate); this.savingsAccountTransactionRepository.save(withdrawtransferTransaction); this.savingAccountRepository.save(savingsAccount); @@ -565,6 +569,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi if (fieldOfficer != null) { savingsAccount.update(fieldOfficer); } + + final MathContext mc = MathContext.DECIMAL64; + savingsAccount.calculateInterestUsing(mc, transferDate); this.savingsAccountTransactionRepository.save(acceptTransferTransaction); this.savingAccountRepository.save(savingsAccount); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java index 59b45ed00..1f8e8945d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java @@ -101,9 +101,9 @@ public class SavingsEnumerations { SavingsAccountTransactionType.WITHDRAW_TRANSFER.getCode(), "Transfer Withdrawn"); break; default: - case APPLY_CHARGES: - optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.APPLY_CHARGES.getValue().longValue(), - SavingsAccountTransactionType.APPLY_CHARGES.getCode(), "Apply Charge"); + case PAY_CHARGE: + optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.PAY_CHARGE.getValue().longValue(), + SavingsAccountTransactionType.PAY_CHARGE.getCode(), "Pay Charge"); break; case WAIVE_CHARGES: optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WAIVE_CHARGES.getValue().longValue(), diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java index d375f17c7..7e962e1b2 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/api/TransferApiConstants.java @@ -35,6 +35,9 @@ public class TransferApiConstants { public static final Set ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(newStaffIdParamName, destinationGroupIdParamName, note)); + public static final Set PROPOSE_AND_ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(localeParamName, + dateFormatParamName, destinationOfficeIdParamName, transferActiveLoans, newStaffIdParamName, destinationGroupIdParamName, note)); + public static final Set REJECT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(note)); public static final Set WITHDRAW_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet(Arrays.asList(note)); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java index 1ea8a16ca..7067d8858 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/data/TransfersDataValidator.java @@ -125,6 +125,41 @@ public final class TransfersDataValidator { throwExceptionIfValidationWarningsExist(dataValidationErrors); } + public void validateForProposeAndAcceptClientTransfer(final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, + TransferApiConstants.PROPOSE_AND_ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS); + final List dataValidationErrors = new ArrayList(); + + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) + .resource(ClientApiConstants.CLIENT_RESOURCE_NAME); + final JsonElement element = this.fromApiJsonHelper.parse(json); + + final Long destinationOfficeId = this.fromApiJsonHelper + .extractLongNamed(TransferApiConstants.destinationOfficeIdParamName, element); + baseDataValidator.reset().parameter(TransferApiConstants.destinationOfficeIdParamName).value(destinationOfficeId).notNull() + .integerGreaterThanZero(); + + if (this.fromApiJsonHelper.parameterExists(TransferApiConstants.newStaffIdParamName, element)) { + final Long newStaffId = this.fromApiJsonHelper.extractLongNamed(TransferApiConstants.newStaffIdParamName, element); + baseDataValidator.reset().parameter(TransferApiConstants.newStaffIdParamName).value(newStaffId).notNull() + .integerGreaterThanZero(); + } + + if (this.fromApiJsonHelper.parameterExists(TransferApiConstants.destinationGroupIdParamName, element)) { + final Long destinationGroupId = this.fromApiJsonHelper.extractLongNamed(TransferApiConstants.destinationGroupIdParamName, + element); + baseDataValidator.reset().parameter(TransferApiConstants.destinationGroupIdParamName).value(destinationGroupId).notNull() + .integerGreaterThanZero(); + } + + validateNote(baseDataValidator, element); + + throwExceptionIfValidationWarningsExist(dataValidationErrors); + } + public void validateForRejectClientTransfer(final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/handler/ProposeAndAcceptClientTransferCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/handler/ProposeAndAcceptClientTransferCommandHandler.java new file mode 100644 index 000000000..0f0a8fa53 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/handler/ProposeAndAcceptClientTransferCommandHandler.java @@ -0,0 +1,31 @@ +/** + * 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.transfer.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.transfer.service.TransferWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ProposeAndAcceptClientTransferCommandHandler implements NewCommandSourceHandler { + + private final TransferWritePlatformService writePlatformService; + + @Autowired + public ProposeAndAcceptClientTransferCommandHandler(final TransferWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.proposeAndAcceptClientTransfer(command.entityId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferEventType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferEventType.java index e101fe2c8..562bf559d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferEventType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferEventType.java @@ -25,4 +25,8 @@ public enum TransferEventType { return this.code; } + public boolean isAcceptance() { + return value.equals(TransferEventType.ACCEPTANCE.value); + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformService.java index 2b88ad6ed..54ae1424a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformService.java @@ -20,4 +20,6 @@ public interface TransferWritePlatformService { CommandProcessingResult rejectClientTransfer(final Long clientId, final JsonCommand jsonCommand); + CommandProcessingResult proposeAndAcceptClientTransfer(final Long clientId, final JsonCommand jsonCommand); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java index 255afe106..a23ec31b0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java @@ -220,6 +220,35 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr } + /** + * This API is meant for transferring clients between branches mainly by + * Organizations following an Individual lending Model
+ * + * @param clientId + * @param destinationOfficeId + * @param jsonCommand + * @return + **/ + @Transactional + @Override + public CommandProcessingResult proposeAndAcceptClientTransfer(final Long clientId, final JsonCommand jsonCommand) { + // validation + this.transfersDataValidator.validateForProposeAndAcceptClientTransfer(jsonCommand.json()); + + final Long destinationOfficeId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.destinationOfficeIdParamName); + final Office office = this.officeRepository.findOneWithNotFoundDetection(destinationOfficeId); + final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId); + handleClientTransferLifecycleEvent(client, office, TransferEventType.PROPOSAL, jsonCommand); + this.clientRepository.saveAndFlush(client); + handleClientTransferLifecycleEvent(client, client.getTransferToOffice(), TransferEventType.ACCEPTANCE, jsonCommand); + this.clientRepository.save(client); + + return new CommandProcessingResultBuilder() // + .withClientId(clientId) // + .withEntityId(clientId) // + .build(); + } + /** * This API is meant for transferring clients between branches mainly by * Organizations following an Individual lending Model
@@ -322,8 +351,8 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr if (staffId != null) { staff = this.staffRepositoryWrapper.findByOfficeHierarchyWithNotFoundDetection(staffId, destinationOffice.getHierarchy()); } - if (destinationGroupId != null) { - destinationGroup = this.groupRepository.findOneWithNotFoundDetection(destinationGroupId); + if (transferEventType.isAcceptance() && destinationGroupId != null) { + destinationGroup = this.groupRepository.findByOfficeWithNotFoundDetection(destinationGroupId, destinationOffice); } /*** Handle Active Loans ***/