blob: bd605db8b1c430862483a1f18e42c72cc3d8f112 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.transfer.service;
import com.google.common.collect.Iterables;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
import org.apache.fineract.organisation.staff.domain.Staff;
import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper;
import org.apache.fineract.portfolio.calendar.domain.Calendar;
import org.apache.fineract.portfolio.calendar.domain.CalendarEntityType;
import org.apache.fineract.portfolio.calendar.domain.CalendarInstance;
import org.apache.fineract.portfolio.calendar.domain.CalendarInstanceRepository;
import org.apache.fineract.portfolio.calendar.domain.CalendarType;
import org.apache.fineract.portfolio.calendar.service.CalendarUtils;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.domain.ClientStatus;
import org.apache.fineract.portfolio.client.domain.ClientTransferDetails;
import org.apache.fineract.portfolio.client.domain.ClientTransferDetailsRepositoryWrapper;
import org.apache.fineract.portfolio.client.exception.ClientHasBeenClosedException;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
import org.apache.fineract.portfolio.group.exception.ClientNotInGroupException;
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
import org.apache.fineract.portfolio.note.service.NoteWritePlatformService;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.apache.fineract.portfolio.transfer.api.TransferApiConstants;
import org.apache.fineract.portfolio.transfer.data.TransfersDataValidator;
import org.apache.fineract.portfolio.transfer.exception.ClientNotAwaitingTransferApprovalException;
import org.apache.fineract.portfolio.transfer.exception.ClientNotAwaitingTransferApprovalOrOnHoldException;
import org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException;
import org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException.TransferNotSupportedReason;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWritePlatformService {
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final OfficeRepositoryWrapper officeRepository;
private final CalendarInstanceRepository calendarInstanceRepository;
private final GroupRepositoryWrapper groupRepository;
private final LoanWritePlatformService loanWritePlatformService;
private final SavingsAccountWritePlatformService savingsAccountWritePlatformService;
private final LoanRepositoryWrapper loanRepositoryWrapper;
private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper;
private final TransfersDataValidator transfersDataValidator;
private final NoteWritePlatformService noteWritePlatformService;
private final StaffRepositoryWrapper staffRepositoryWrapper;
private final ClientTransferDetailsRepositoryWrapper clientTransferDetailsRepositoryWrapper;
private final PlatformSecurityContext context;
@Autowired
public TransferWritePlatformServiceJpaRepositoryImpl(final ClientRepositoryWrapper clientRepositoryWrapper,
final OfficeRepositoryWrapper officeRepository, final CalendarInstanceRepository calendarInstanceRepository,
final LoanWritePlatformService loanWritePlatformService, final GroupRepositoryWrapper groupRepository,
final LoanRepositoryWrapper loanRepositoryWrapper, final TransfersDataValidator transfersDataValidator,
final NoteWritePlatformService noteWritePlatformService, final StaffRepositoryWrapper staffRepositoryWrapper,
final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper,
final SavingsAccountWritePlatformService savingsAccountWritePlatformService,
final ClientTransferDetailsRepositoryWrapper clientTransferDetailsRepositoryWrapper, final PlatformSecurityContext context) {
this.clientRepositoryWrapper = clientRepositoryWrapper;
this.officeRepository = officeRepository;
this.calendarInstanceRepository = calendarInstanceRepository;
this.loanWritePlatformService = loanWritePlatformService;
this.groupRepository = groupRepository;
this.loanRepositoryWrapper = loanRepositoryWrapper;
this.transfersDataValidator = transfersDataValidator;
this.noteWritePlatformService = noteWritePlatformService;
this.staffRepositoryWrapper = staffRepositoryWrapper;
this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper;
this.savingsAccountWritePlatformService = savingsAccountWritePlatformService;
this.clientTransferDetailsRepositoryWrapper = clientTransferDetailsRepositoryWrapper;
this.context = context;
}
@Override
@Transactional
public CommandProcessingResult transferClientsBetweenGroups(final Long sourceGroupId, final JsonCommand jsonCommand) {
this.transfersDataValidator.validateForClientsTransferBetweenGroups(jsonCommand.json());
final Group sourceGroup = this.groupRepository.findOneWithNotFoundDetection(sourceGroupId);
final Long destinationGroupId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.destinationGroupIdParamName);
final Group destinationGroup = this.groupRepository.findOneWithNotFoundDetection(destinationGroupId);
final Long staffId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.newStaffIdParamName);
final Boolean inheritDestinationGroupLoanOfficer = jsonCommand
.booleanObjectValueOfParameterNamed(TransferApiConstants.inheritDestinationGroupLoanOfficer);
Staff staff = null;
final Office sourceOffice = sourceGroup.getOffice();
if (staffId != null) {
staff = this.staffRepositoryWrapper.findByOfficeHierarchyWithNotFoundDetection(staffId, sourceOffice.getHierarchy());
}
final List<Client> clients = assembleListOfClients(jsonCommand);
if (sourceGroupId.equals(destinationGroupId)) {
throw new TransferNotSupportedException(TransferNotSupportedReason.SOURCE_AND_DESTINATION_GROUP_CANNOT_BE_SAME, sourceGroupId,
destinationGroupId);
}
/*** Do not allow bulk client transfers across branches ***/
if (!sourceOffice.getId().equals(destinationGroup.getOffice().getId())) {
throw new TransferNotSupportedException(TransferNotSupportedReason.BULK_CLIENT_TRANSFER_ACROSS_BRANCHES, sourceGroupId,
destinationGroupId);
}
for (final Client client : clients) {
transferClientBetweenGroups(sourceGroup, client, destinationGroup, inheritDestinationGroupLoanOfficer, staff);
}
return new CommandProcessingResultBuilder() //
.withEntityId(sourceGroupId) //
.build();
}
/****
* Variables that would make sense <br>
* <ul>
* <li>inheritDestinationGroupLoanOfficer: Default true</li>
* <li>newStaffId: Optional field with Id of new Loan Officer to be linked to this client and all his JLG loans for
* this group</li>
* </ul>
***/
@Transactional
public void transferClientBetweenGroups(final Group sourceGroup, final Client client, final Group destinationGroup,
final Boolean inheritDestinationGroupLoanOfficer, final Staff newLoanOfficer) {
// next I shall validate that the client is present in this group
if (!sourceGroup.hasClientAsMember(client)) {
throw new ClientNotInGroupException(client.getId(), sourceGroup.getId());
}
// Is client active?
if (client.isNotActive()) {
throw new ClientHasBeenClosedException(client.getId());
}
/**
* TODO: for now we need to ensure that only one collection sheet calendar can be linked with a center or group
* entity <br/>
**/
final CalendarInstance sourceGroupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
sourceGroup.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue());
// get all customer loans synced with this group calendar Instance
final List<CalendarInstance> activeLoanCalendarInstances = this.calendarInstanceRepository
.findCalendarInstancesForActiveLoansByGroupIdAndClientId(sourceGroup.getId(), client.getId());
/**
* if a calendar is present in the source group along with loans synced with it, we should ensure that the
* destination group also has a collection calendar
**/
if (sourceGroupCalendarInstance != null && !activeLoanCalendarInstances.isEmpty()) {
// get the destination calendar
final CalendarInstance destinationGroupCalendarInstance = this.calendarInstanceRepository
.findByEntityIdAndEntityTypeIdAndCalendarTypeId(destinationGroup.getId(), CalendarEntityType.GROUPS.getValue(),
CalendarType.COLLECTION.getValue());
if (destinationGroupCalendarInstance == null) {
throw new TransferNotSupportedException(TransferNotSupportedReason.DESTINATION_GROUP_HAS_NO_MEETING,
destinationGroup.getId());
}
final Calendar sourceGroupCalendar = sourceGroupCalendarInstance.getCalendar();
final Calendar destinationGroupCalendar = destinationGroupCalendarInstance.getCalendar();
/***
* Ensure that the recurrence pattern are same for collection meeting in both the source and the destination
* calendar
***/
if (!(CalendarUtils.isFrequencySame(sourceGroupCalendar.getRecurrence(), destinationGroupCalendar.getRecurrence())
&& CalendarUtils.isIntervalSame(sourceGroupCalendar.getRecurrence(), destinationGroupCalendar.getRecurrence()))) {
throw new TransferNotSupportedException(TransferNotSupportedReason.DESTINATION_GROUP_MEETING_FREQUENCY_MISMATCH,
sourceGroup.getId(), destinationGroup.getId());
}
/** map all JLG loans for this client to the destinationGroup **/
for (final CalendarInstance calendarInstance : activeLoanCalendarInstances) {
calendarInstance.updateCalendar(destinationGroupCalendar);
this.calendarInstanceRepository.save(calendarInstance);
}
// reschedule all JLG Loans to follow new Calendar
this.loanWritePlatformService.applyMeetingDateChanges(destinationGroupCalendar, activeLoanCalendarInstances);
}
/**
* Now Change the loan officer for this client and all his active JLG loans
**/
final Staff destinationGroupLoanOfficer = destinationGroup.getStaff();
/**
* In case of a loan officer transfer, set the new loan officer value
**/
if (sourceGroup.getId().equals(destinationGroup.getId()) && newLoanOfficer != null) {
client.updateStaff(newLoanOfficer);
} /*** Else default to destination group Officer (If present) ***/
else if (destinationGroupLoanOfficer != null) {
client.updateStaff(destinationGroupLoanOfficer);
}
client.getGroups().add(destinationGroup);
this.clientRepositoryWrapper.saveAndFlush(client);
/**
* Active JLG loans are now linked to the new Group and Loan officer
**/
final List<Loan> allClientJLGLoans = this.loanRepositoryWrapper.findByClientIdAndGroupId(client.getId(), sourceGroup.getId());
for (final Loan loan : allClientJLGLoans) {
if (loan.status().isActiveOrAwaitingApprovalOrDisbursal()) {
loan.updateGroup(destinationGroup);
if (inheritDestinationGroupLoanOfficer != null && inheritDestinationGroupLoanOfficer == true
&& destinationGroupLoanOfficer != null) {
loan.reassignLoanOfficer(destinationGroupLoanOfficer, DateUtils.getLocalDateOfTenant());
} else if (newLoanOfficer != null) {
loan.reassignLoanOfficer(newLoanOfficer, DateUtils.getLocalDateOfTenant());
}
this.loanRepositoryWrapper.saveAndFlush(loan);
}
}
/**
* change client group membership (only if source group and destination group are not the same, i.e only Loan
* officer Transfer)
**/
if (!sourceGroup.getId().equals(destinationGroup.getId())) {
client.getGroups().remove(sourceGroup);
}
}
/**
* This API is meant for transferring clients between branches mainly by Organizations following an Individual
* lending Model <br>
*
* @param clientId
* @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.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId, true);
handleClientTransferLifecycleEvent(client, office, TransferEventType.PROPOSAL, jsonCommand);
this.clientRepositoryWrapper.saveAndFlush(client);
handleClientTransferLifecycleEvent(client, client.getTransferToOffice(), TransferEventType.ACCEPTANCE, jsonCommand);
this.clientRepositoryWrapper.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 <br>
* If the Client is linked to any Groups, we can optionally choose to have all the linkages broken and all JLG Loans
* are converted into Individual Loans
*
* @param clientId
* @param jsonCommand
* @return
**/
@Transactional
@Override
public CommandProcessingResult proposeClientTransfer(final Long clientId, final JsonCommand jsonCommand) {
// validation
this.transfersDataValidator.validateForProposeClientTransfer(jsonCommand.json());
final Long destinationOfficeId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.destinationOfficeIdParamName);
final Office office = this.officeRepository.findOneWithNotFoundDetection(destinationOfficeId);
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
if (client.getOffice().getId().equals(destinationOfficeId)) {
throw new GeneralPlatformDomainRuleException(TransferApiConstants.transferClientToSameOfficeException,
TransferApiConstants.transferClientToSameOfficeExceptionMessage, office.getName());
}
handleClientTransferLifecycleEvent(client, office, TransferEventType.PROPOSAL, jsonCommand);
this.clientRepositoryWrapper.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 <br>
* If the Client is linked to any Groups, we can optionally choose to have all the linkages broken and all JLG Loans
* are converted into Individual Loans
*
* @param clientId
* @param jsonCommand
* @return
**/
@Transactional
@Override
public CommandProcessingResult acceptClientTransfer(final Long clientId, final JsonCommand jsonCommand) {
// validation
this.transfersDataValidator.validateForAcceptClientTransfer(jsonCommand.json());
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId, true);
validateClientAwaitingTransferAcceptance(client);
handleClientTransferLifecycleEvent(client, client.getTransferToOffice(), TransferEventType.ACCEPTANCE, jsonCommand);
this.clientRepositoryWrapper.save(client);
return new CommandProcessingResultBuilder() //
.withClientId(clientId) //
.withEntityId(clientId) //
.build();
}
@Override
@Transactional
public CommandProcessingResult withdrawClientTransfer(final Long clientId, final JsonCommand jsonCommand) {
// validation
this.transfersDataValidator.validateForWithdrawClientTransfer(jsonCommand.json());
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
validateClientAwaitingTransferAcceptanceOnHold(client);
handleClientTransferLifecycleEvent(client, client.getOffice(), TransferEventType.WITHDRAWAL, jsonCommand);
this.clientRepositoryWrapper.save(client);
return new CommandProcessingResultBuilder() //
.withClientId(clientId) //
.withEntityId(clientId) //
.build();
}
@Override
@Transactional
public CommandProcessingResult rejectClientTransfer(final Long clientId, final JsonCommand jsonCommand) {
// validation
this.transfersDataValidator.validateForRejectClientTransfer(jsonCommand.json());
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
handleClientTransferLifecycleEvent(client, client.getOffice(), TransferEventType.REJECTION, jsonCommand);
this.clientRepositoryWrapper.save(client);
return new CommandProcessingResultBuilder() //
.withClientId(clientId) //
.withEntityId(clientId) //
.build();
}
private void handleClientTransferLifecycleEvent(final Client client, final Office destinationOffice,
final TransferEventType transferEventType, final JsonCommand jsonCommand) {
final Date todaysDate = DateUtils.getDateOfTenant();
/** Get destination loan officer if exists **/
Staff staff = null;
Group destinationGroup = null;
final Long staffId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.newStaffIdParamName);
final Long destinationGroupId = jsonCommand.longValueOfParameterNamed(TransferApiConstants.destinationGroupIdParamName);
final LocalDate transferDate = jsonCommand.localDateValueOfParameterNamed(TransferApiConstants.transferDate);
if (staffId != null) {
staff = this.staffRepositoryWrapper.findByOfficeHierarchyWithNotFoundDetection(staffId, destinationOffice.getHierarchy());
}
if (transferEventType.isAcceptance() && destinationGroupId != null) {
destinationGroup = this.groupRepository.findByOfficeWithNotFoundDetection(destinationGroupId, destinationOffice);
}
/*** Handle Active Loans ***/
if (this.loanRepositoryWrapper.doNonClosedLoanAccountsExistForClient(client.getId())) {
// get each individual loan for the client
for (final Loan loan : this.loanRepositoryWrapper.findLoanByClientId(client.getId())) {
/**
* We need to create transactions etc only for loans which are disbursed and not yet closed
**/
if (loan.isDisbursed() && !loan.isClosed()) {
switch (transferEventType) {
case ACCEPTANCE:
this.loanWritePlatformService.acceptLoanTransfer(loan, loan.getLastUserTransactionDate(), destinationOffice,
staff);
break;
case PROPOSAL:
this.loanWritePlatformService.initiateLoanTransfer(loan, transferDate);
break;
case REJECTION:
this.loanWritePlatformService.rejectLoanTransfer(loan);
break;
case WITHDRAWAL:
this.loanWritePlatformService.withdrawLoanTransfer(loan, loan.getLastUserTransactionDate());
}
}
}
}
/*** Handle Active Savings (Currently throw and exception) ***/
if (this.savingsAccountRepositoryWrapper.doNonClosedSavingAccountsExistForClient(client.getId())) {
// get each individual saving account for the client
for (final SavingsAccount savingsAccount : this.savingsAccountRepositoryWrapper.findSavingAccountByClientId(client.getId())) {
if (savingsAccount.isActivated() && !savingsAccount.isClosed()) {
switch (transferEventType) {
case ACCEPTANCE:
this.savingsAccountWritePlatformService.acceptSavingsTransfer(savingsAccount,
savingsAccount.retrieveLastTransactionDate(), destinationOffice, staff);
break;
case PROPOSAL:
this.savingsAccountWritePlatformService.initiateSavingsTransfer(savingsAccount, transferDate);
break;
case REJECTION:
this.savingsAccountWritePlatformService.rejectSavingsTransfer(savingsAccount);
break;
case WITHDRAWAL:
this.savingsAccountWritePlatformService.withdrawSavingsTransfer(savingsAccount,
savingsAccount.retrieveLastTransactionDate());
}
}
}
}
switch (transferEventType) {
case ACCEPTANCE:
client.setStatus(ClientStatus.ACTIVE.getValue());
client.updateTransferToOffice(null);
client.updateOffice(destinationOffice);
client.updateOfficeJoiningDate(client.getProposedTransferDate());
client.updateProposedTransferDate(null);
if (client.getGroups().size() == 1) {
if (destinationGroup == null) {
throw new TransferNotSupportedException(TransferNotSupportedReason.CLIENT_DESTINATION_GROUP_NOT_SPECIFIED,
client.getId());
} else if (!destinationGroup.isActive()) {
throw new GroupNotActiveException(destinationGroup.getId());
}
transferClientBetweenGroups(Iterables.get(client.getGroups(), 0), client, destinationGroup, true, staff);
} else if (client.getGroups().size() == 0 && destinationGroup != null) {
client.getGroups().add(destinationGroup);
client.updateStaff(destinationGroup.getStaff());
if (staff != null) {
client.updateStaff(staff);
}
} else if (destinationGroup == null) {
/** for individual with no groups **/
if (staff != null) {
client.updateStaff(staff);
}
}
break;
case PROPOSAL:
client.setStatus(ClientStatus.TRANSFER_IN_PROGRESS.getValue());
client.updateTransferToOffice(destinationOffice);
client.updateProposedTransferDate(Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
break;
case REJECTION:
client.setStatus(ClientStatus.TRANSFER_ON_HOLD.getValue());
client.updateTransferToOffice(null);
client.updateProposedTransferDate(null);
break;
case WITHDRAWAL:
client.setStatus(ClientStatus.ACTIVE.getValue());
client.updateTransferToOffice(null);
client.updateProposedTransferDate(null);
}
this.noteWritePlatformService.createAndPersistClientNote(client, jsonCommand);
Date proposedTransferDate = transferDate != null ? Date.from(transferDate.atStartOfDay(ZoneId.systemDefault()).toInstant()) : null;
this.clientTransferDetailsRepositoryWrapper.save(ClientTransferDetails.instance(client.getId(), client.getOffice().getId(),
destinationOffice.getId(), proposedTransferDate, transferEventType.getValue(),
Date.from(DateUtils.getLocalDateTimeOfTenant().atZone(ZoneId.systemDefault()).toInstant()),
this.context.authenticatedUser().getId()));
}
private List<Client> assembleListOfClients(final JsonCommand command) {
final List<Client> clients = new ArrayList<>();
if (command.parameterExists(TransferApiConstants.clients)) {
final JsonArray clientsArray = command.arrayOfParameterNamed(TransferApiConstants.clients);
if (clientsArray != null) {
for (int i = 0; i < clientsArray.size(); i++) {
final JsonObject jsonObject = clientsArray.get(i).getAsJsonObject();
if (jsonObject.has(TransferApiConstants.idParamName)) {
final Long id = jsonObject.get(TransferApiConstants.idParamName).getAsLong();
final Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(id);
clients.add(client);
}
}
}
}
return clients;
}
private void validateClientAwaitingTransferAcceptance(final Client client) {
if (!client.isTransferInProgress()) {
throw new ClientNotAwaitingTransferApprovalException(client.getId());
}
}
/**
* private void validateGroupAwaitingTransferAcceptance(final Group group) { if (!group.isTransferInProgress()) {
* throw new ClientNotAwaitingTransferApprovalException(group.getId()); } }
**/
private void validateClientAwaitingTransferAcceptanceOnHold(final Client client) {
if (!client.isTransferInProgressOrOnHold()) {
throw new ClientNotAwaitingTransferApprovalOrOnHoldException(client.getId());
}
}
/**
* private void validateGroupAwaitingTransferAcceptanceOnHold(final Group group) { if
* (!group.isTransferInProgressOrOnHold()) { throw new ClientNotAwaitingTransferApprovalException(group.getId()); }
* }
**/
}