Merge pull request #602 from vishwasbabu/mifosplatform-1.10.2

bug fixes for 1.10.2 release
This commit is contained in:
Vishwas Babu A J
2013-09-22 22:37:27 -07:00
20 changed files with 210 additions and 16 deletions
+45 -4
View File
@@ -90,7 +90,7 @@
<body> <body>
<div id="page-wrapper"> <div id="page-wrapper">
<div id="flybar"> <div id="flybar">
<div id="nav-logo">1.10.1.RELEASE API</div> <div id="nav-logo">1.10.2.RELEASE API</div>
<div class="flybar-nav"> <div class="flybar-nav">
<h2 class="flybar-button">Overview</h2> <h2 class="flybar-button">Overview</h2>
<div class="flybar-menu-overview"> <div class="flybar-menu-overview">
@@ -239,6 +239,14 @@
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td class="alt"></td>
<td>clients/{clientId}?command=proposeAndAcceptTransfer</td>
<td><a href="#clients_propose_and_accept_transfer">Propose and Accept a Client Transfer</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr> <tr>
<td></td> <td></td>
<td>clients/{clientId}/accounts</td> <td>clients/{clientId}/accounts</td>
@@ -2291,6 +2299,37 @@ Request Body:
</div> </div>
<a id="clients_propose_and_accept_transfer" name="clients_propose_and_accept_transfer" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h4>Propose and Accept a Client Transfer</h4>
<p>Abstraction over the <a href="#clients_propose_transfer">Propose</a> and <a href="#clients_propose_transfer">Accept</a> <i>Client Transfer</i> API's which enable a user with Data Scope over both the Target and Destination Branches to directly
transfer a Client to the destination <i>Office</i>.</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/clients/{clientId}?command=proposeAndAcceptTransfer</code>
<code class="method-request">POST clients/1?command=proposeTransfer
Content-Type: application/json
Request Body:
{
"destinationOfficeId":"2",
"destinationGroupId":"13",
"staffId":"1",
"note":"Client Relocating to Bangalore"
}
</code>
<code class="method-response">
{
"clientId": 2,
"resourceId": 2
}
</code>
</div>
</div>
<a id="clients_retrieve" name="clients_retrieve" class="old-syle-anchor">&nbsp;</a> <a id="clients_retrieve" name="clients_retrieve" class="old-syle-anchor">&nbsp;</a>
<div class="method-section"> <div class="method-section">
<div class="method-description"> <div class="method-description">
@@ -8469,7 +8508,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
<tr class=alt> <tr class=alt>
<td>fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, <td>fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId,
incomeFromFeeAccountId, incomeFromPenaltyAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId,
writeOffAccountId</td> writeOffAccountId, transfersInSuspenseAccountId</td>
</tr> </tr>
<tr class="matrixHeadingBG"> <tr class="matrixHeadingBG">
<td><div class="mifosXHeading2">Additional Mandatory Fields for Accrual(3) based accounting</div></td> <td><div class="mifosXHeading2">Additional Mandatory Fields for Accrual(3) based accounting</div></td>
@@ -8478,7 +8517,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
<td>fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, <td>fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId,
incomeFromFeeAccountId, incomeFromPenaltyAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId,
writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId, writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId,
receivablePenaltyAccountId</td> receivablePenaltyAccountId, transfersInSuspenseAccountId</td>
</tr> </tr>
</table> </table>
</div> </div>
@@ -8543,6 +8582,7 @@ Request Body:
"incomeFromFeeAccountId":"37", "incomeFromFeeAccountId":"37",
"incomeFromPenaltyAccountId":"35", "incomeFromPenaltyAccountId":"35",
"writeOffAccountId":"41", "writeOffAccountId":"41",
"transfersInSuspenseAccountId":"4",
"paymentChannelToFundSourceMappings": [ "paymentChannelToFundSourceMappings": [
{ {
"paymentTypeId": "11", "paymentTypeId": "11",
@@ -12323,7 +12363,7 @@ Content-Type: application/json
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields for Cash based accounting (accountingRule = 2)</div></td></tr> <tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Mandatory Fields for Cash based accounting (accountingRule = 2)</div></td></tr>
<tr class=alt> <tr class=alt>
<td>savingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId</td> <td>savingsReferenceAccountId,savingsControlAccountId, interestOnSavingsAccountId, incomeFromFeeAccountId, transfersInSuspenseAccountId</td>
</tr> </tr>
</table> </table>
<br/> <br/>
@@ -12384,6 +12424,7 @@ Request Body:
"annualFeeOnMonthDay": "01 May", "annualFeeOnMonthDay": "01 May",
"accountingRule": "2", "accountingRule": "2",
"savingsReferenceAccountId": "16", "savingsReferenceAccountId": "16",
"transfersInSuspenseAccountId": "16",
"savingsControlAccountId": "15", "savingsControlAccountId": "15",
"interestOnSavingsAccountId": "18", "interestOnSavingsAccountId": "18",
"incomeFromFeeAccountId": "4", "incomeFromFeeAccountId": "4",
@@ -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);
@@ -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;
+1 -1
View File
@@ -1,2 +1,2 @@
releaseVersion=1.10.1.RELEASE releaseVersion=1.10.2.RELEASE
@@ -612,6 +612,10 @@ public class CommandWrapper {
return this.actionName.equalsIgnoreCase("PROPOSETRANSFER") && this.entityName.equalsIgnoreCase("CLIENT"); return this.actionName.equalsIgnoreCase("PROPOSETRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
} }
public boolean isProposeAndAcceptClientTransfer() {
return this.actionName.equalsIgnoreCase("PROPOSEANDACCEPTTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
}
public boolean isWithdrawClientTransfer() { public boolean isWithdrawClientTransfer() {
return this.actionName.equalsIgnoreCase("WITHDRAWTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT"); return this.actionName.equalsIgnoreCase("WITHDRAWTRANSFER") && this.entityName.equalsIgnoreCase("CLIENT");
} }
@@ -362,6 +362,15 @@ public class CommandWrapperBuilder {
return this; 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) { public CommandWrapperBuilder withdrawClientTransferRequest(final Long clientId) {
this.actionName = "WITHDRAWTRANSFER"; this.actionName = "WITHDRAWTRANSFER";
this.entityName = "CLIENT"; this.entityName = "CLIENT";
@@ -171,6 +171,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("closeClientCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isProposeClientTransfer()) { } else if (wrapper.isProposeClientTransfer()) {
handler = this.applicationContext.getBean("proposeClientTransferCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("proposeClientTransferCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isProposeAndAcceptClientTransfer()) {
handler = this.applicationContext.getBean("proposeAndAcceptClientTransferCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isWithdrawClientTransfer()) { } else if (wrapper.isWithdrawClientTransfer()) {
handler = this.applicationContext.getBean("withdrawClientTransferCommandHandler", NewCommandSourceHandler.class); handler = this.applicationContext.getBean("withdrawClientTransferCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isAcceptClientTransfer()) { } else if (wrapper.isAcceptClientTransfer()) {
@@ -212,6 +212,9 @@ public class ClientsApiResource {
} else if (is(commandParam, "proposeTransfer")) { } else if (is(commandParam, "proposeTransfer")) {
commandRequest = builder.proposeClientTransfer(clientId).build(); commandRequest = builder.proposeClientTransfer(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); 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")) { } else if (is(commandParam, "withdrawTransfer")) {
commandRequest = builder.withdrawClientTransferRequest(clientId).build(); commandRequest = builder.withdrawClientTransferRequest(clientId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
@@ -5,6 +5,7 @@
*/ */
package org.mifosplatform.portfolio.group.domain; package org.mifosplatform.portfolio.group.domain;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.portfolio.group.exception.GroupNotFoundException; import org.mifosplatform.portfolio.group.exception.GroupNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -31,6 +32,12 @@ public class GroupRepositoryWrapper {
return entity; 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) { public void save(final Group entity) {
this.repository.save(entity); this.repository.save(entity);
} }
@@ -19,8 +19,9 @@ public enum SavingsAccountTransactionType {
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), // INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), // WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), //
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), // ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), //
WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), APPLY_CHARGES(7, "savingsAccountTransactionType.applyCharges"), INITIATE_TRANSFER( WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), //
12, "savingsAccountTransactionType.initiateTransfer"), // PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), //
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), // APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), // WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"); REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer");
@@ -66,7 +67,7 @@ public enum SavingsAccountTransactionType {
savingsAccountTransactionType = SavingsAccountTransactionType.WAIVE_CHARGES; savingsAccountTransactionType = SavingsAccountTransactionType.WAIVE_CHARGES;
break; break;
case 7: case 7:
savingsAccountTransactionType = SavingsAccountTransactionType.APPLY_CHARGES; savingsAccountTransactionType = SavingsAccountTransactionType.PAY_CHARGE;
break; break;
case 12: case 12:
savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER; savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER;
@@ -105,7 +106,7 @@ public enum SavingsAccountTransactionType {
} }
public boolean isCharge() { public boolean isCharge() {
return this.value.equals(SavingsAccountTransactionType.APPLY_CHARGES.getValue()); return this.value.equals(SavingsAccountTransactionType.PAY_CHARGE.getValue());
} }
public boolean isWaiveCharge() { public boolean isWaiveCharge() {
@@ -35,7 +35,8 @@ public class SavingsAccountTransactionEnumData {
this.withdrawal = Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL.getValue()).equals(this.id); this.withdrawal = Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL.getValue()).equals(this.id);
this.interestPosting = Long.valueOf(SavingsAccountTransactionType.INTEREST_POSTING.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) 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.initiateTransfer = Long.valueOf(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue()).equals(this.id);
this.approveTransfer = Long.valueOf(SavingsAccountTransactionType.APPROVE_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); this.withdrawTransfer = Long.valueOf(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()).equals(this.id);
@@ -131,7 +131,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date, public static SavingsAccountTransaction charge(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
final Money amount) { final Money amount) {
final boolean isReversed = false; 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); isReversed);
} }
@@ -514,6 +514,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
savingsAccount.office(), transferDate); savingsAccount.office(), transferDate);
savingsAccount.getTransactions().add(newTransferTransaction); savingsAccount.getTransactions().add(newTransferTransaction);
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
final MathContext mc = MathContext.DECIMAL64;
savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(newTransferTransaction); this.savingsAccountTransactionRepository.save(newTransferTransaction);
this.savingAccountRepository.save(savingsAccount); this.savingAccountRepository.save(savingsAccount);
@@ -534,6 +536,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
savingsAccount.office(), transferDate); savingsAccount.office(), transferDate);
savingsAccount.getTransactions().add(withdrawtransferTransaction); savingsAccount.getTransactions().add(withdrawtransferTransaction);
savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
final MathContext mc = MathContext.DECIMAL64;
savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction); this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
this.savingAccountRepository.save(savingsAccount); this.savingAccountRepository.save(savingsAccount);
@@ -566,6 +570,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
savingsAccount.update(fieldOfficer); savingsAccount.update(fieldOfficer);
} }
final MathContext mc = MathContext.DECIMAL64;
savingsAccount.calculateInterestUsing(mc, transferDate);
this.savingsAccountTransactionRepository.save(acceptTransferTransaction); this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
this.savingAccountRepository.save(savingsAccount); this.savingAccountRepository.save(savingsAccount);
@@ -101,9 +101,9 @@ public class SavingsEnumerations {
SavingsAccountTransactionType.WITHDRAW_TRANSFER.getCode(), "Transfer Withdrawn"); SavingsAccountTransactionType.WITHDRAW_TRANSFER.getCode(), "Transfer Withdrawn");
break; break;
default: default:
case APPLY_CHARGES: case PAY_CHARGE:
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.APPLY_CHARGES.getValue().longValue(), optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.PAY_CHARGE.getValue().longValue(),
SavingsAccountTransactionType.APPLY_CHARGES.getCode(), "Apply Charge"); SavingsAccountTransactionType.PAY_CHARGE.getCode(), "Pay Charge");
break; break;
case WAIVE_CHARGES: case WAIVE_CHARGES:
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WAIVE_CHARGES.getValue().longValue(), optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WAIVE_CHARGES.getValue().longValue(),
@@ -35,6 +35,9 @@ public class TransferApiConstants {
public static final Set<String> ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(newStaffIdParamName, public static final Set<String> ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(newStaffIdParamName,
destinationGroupIdParamName, note)); destinationGroupIdParamName, note));
public static final Set<String> PROPOSE_AND_ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
dateFormatParamName, destinationOfficeIdParamName, transferActiveLoans, newStaffIdParamName, destinationGroupIdParamName, note));
public static final Set<String> REJECT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(note)); public static final Set<String> REJECT_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(note));
public static final Set<String> WITHDRAW_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(note)); public static final Set<String> WITHDRAW_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(note));
@@ -125,6 +125,41 @@ public final class TransfersDataValidator {
throwExceptionIfValidationWarningsExist(dataValidationErrors); throwExceptionIfValidationWarningsExist(dataValidationErrors);
} }
public void validateForProposeAndAcceptClientTransfer(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
TransferApiConstants.PROPOSE_AND_ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
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) { public void validateForRejectClientTransfer(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
@@ -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);
}
}
@@ -25,4 +25,8 @@ public enum TransferEventType {
return this.code; return this.code;
} }
public boolean isAcceptance() {
return value.equals(TransferEventType.ACCEPTANCE.value);
}
} }
@@ -20,4 +20,6 @@ public interface TransferWritePlatformService {
CommandProcessingResult rejectClientTransfer(final Long clientId, final JsonCommand jsonCommand); CommandProcessingResult rejectClientTransfer(final Long clientId, final JsonCommand jsonCommand);
CommandProcessingResult proposeAndAcceptClientTransfer(final Long clientId, final JsonCommand jsonCommand);
} }
@@ -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 <br/>
*
* @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 * This API is meant for transferring clients between branches mainly by
* Organizations following an Individual lending Model <br/> * Organizations following an Individual lending Model <br/>
@@ -322,8 +351,8 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
if (staffId != null) { if (staffId != null) {
staff = this.staffRepositoryWrapper.findByOfficeHierarchyWithNotFoundDetection(staffId, destinationOffice.getHierarchy()); staff = this.staffRepositoryWrapper.findByOfficeHierarchyWithNotFoundDetection(staffId, destinationOffice.getHierarchy());
} }
if (destinationGroupId != null) { if (transferEventType.isAcceptance() && destinationGroupId != null) {
destinationGroup = this.groupRepository.findOneWithNotFoundDetection(destinationGroupId); destinationGroup = this.groupRepository.findByOfficeWithNotFoundDetection(destinationGroupId, destinationOffice);
} }
/*** Handle Active Loans ***/ /*** Handle Active Loans ***/