[
https://issues.apache.org/jira/browse/FINERACT-627?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16689219#comment-16689219
]
ASF GitHub Bot commented on FINERACT-627:
-----------------------------------------
ShruthiRajaram closed pull request #471: FINERACT-627 back dated client transfer
URL: https://github.com/apache/fineract/pull/471
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index c182e6588..00751bc2c 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -5761,7 +5761,7 @@ <h4>Update Default Savings Account</h4>
<div class="method-section">
<div class="method-description">
<h4>Propose a Client Transfer</h4>
- <p>Allows you to propose the transfer of a <i>Client</i> to a
different <i>Office</i>.</p>
+ <p>Allows you to propose the transfer of a <i>Client</i> to a
different <i>Office</i> on a specific date, if loan or savings transaction not
present from proposed transfer date to current date.</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain
Name/api/v1/clients/{clientId}?command=proposeTransfer</code>
@@ -5769,6 +5769,7 @@ <h4>Propose a Client Transfer</h4>
Content-Type: application/json
Request Body:
{
+ "transferDate":"28 August 2018",
"destinationOfficeId":"2",
"note":"Client Relocating to Bangalore"
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
index fc8904907..f4f14b206 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
@@ -21,6 +21,7 @@
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -62,6 +63,7 @@
import
org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorReadPlatformService;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
+import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -95,10 +97,11 @@ public ClientsApiResource(final PlatformSecurityContext
context, final ClientRea
final AccountDetailsReadPlatformService
accountDetailsReadPlatformService,
final SavingsAccountReadPlatformService
savingsAccountReadPlatformService,
final BulkImportWorkbookPopulatorService
bulkImportWorkbookPopulatorService,
- final BulkImportWorkbookService bulkImportWorkbookService, final
GuarantorReadPlatformService guarantorReadPlatformService) {
- this.context = context;
- this.clientReadPlatformService = readPlatformService;
- this.toApiJsonSerializer = toApiJsonSerializer;
+ final BulkImportWorkbookService
bulkImportWorkbookService,
+ final GuarantorReadPlatformService
guarantorReadPlatformService) {
+ this.context = context;
+ this.clientReadPlatformService = readPlatformService;
+ this.toApiJsonSerializer = toApiJsonSerializer;
this.clientAccountSummaryToApiJsonSerializer =
clientAccountSummaryToApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService =
commandsSourceWritePlatformService;
@@ -361,4 +364,16 @@ public String
retrieveObligeeDetails(@PathParam("clientId") final Long clientId,
return this.toApiJsonSerializer.serialize(ObligeeList);
}
+ @Path("{clientId}/transferproposaldate")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String retrieveTransferTemplate(@PathParam("clientId") final
Long clientId, @Context final UriInfo uriInfo) {
+
+
this.context.authenticatedUser().validateHasReadPermission(ClientApiConstants.CLIENT_RESOURCE_NAME);
+ final Date transferDate =
this.clientReadPlatformService.retrieveClientTransferProposalDate(clientId);
+ if (transferDate != null) {
+ return this.toApiJsonSerializer.serialize(new
LocalDate(transferDate));
+ }
+ return this.toApiJsonSerializer.serialize(transferDate);
+ }
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
index fc9f72f8c..b9461deaa 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.client.service;
import java.util.Collection;
+import java.util.Date;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
@@ -45,4 +46,12 @@
Collection<ClientData> retrieveActiveClientMembersOfCenter(final Long
centerId);
ClientData retrieveAllNarrations(String clientNarrations);
+
+ Date retrieveClientTransferProposalDate(Long clientId);
+
+ Date retrieveClientTransferProposalDateByLoan(Long clientId);
+
+ Date retrieveClientTransferProposalDateBySavings(Long clientId);
+
+ void validateClient(Long clientId);
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
index 9d1babd8a..43968d8d3 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
@@ -9,6 +9,7 @@
*
* 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
@@ -23,6 +24,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Date;
import java.util.List;
import org.apache.commons.lang.StringUtils;
@@ -59,7 +61,11 @@
import org.apache.fineract.portfolio.client.domain.LegalForm;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
+import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
import
org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
import org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.LocalDate;
@@ -100,8 +106,8 @@ public ClientReadPlatformServiceImpl(final
PlatformSecurityContext context, fina
final AddressReadPlatformService addressReadPlatformService,final
ClientFamilyMembersReadPlatformService clientFamilyMembersReadPlatformService,
final ConfigurationReadPlatformService
configurationReadPlatformService,
final EntityDatatableChecksReadService
entityDatatableChecksReadService,
- final ColumnValidator columnValidator) {
- this.context = context;
+ final ColumnValidator columnValidator) {
+ this.context = context;
this.officeReadPlatformService = officeReadPlatformService;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.staffReadPlatformService = staffReadPlatformService;
@@ -112,7 +118,7 @@ public ClientReadPlatformServiceImpl(final
PlatformSecurityContext context, fina
this.configurationReadPlatformService=configurationReadPlatformService;
this.entityDatatableChecksReadService =
entityDatatableChecksReadService;
this.columnValidator = columnValidator;
- }
+ }
@Override
public ClientData retrieveTemplate(final Long officeId, final boolean
staffInSelectedOfficeOnly) {
@@ -816,5 +822,50 @@ public ClientData retrieveAllNarrations(final String
clientNarrations) {
return ClientData.template(null, null, null, null, narrations, null,
null, clientTypeOptions, clientClassificationOptions,
clientNonPersonConstitutionOptions,
clientNonPersonMainBusinessLineOptions, clientLegalFormOptions,null,null,null,
null);
}
+
+ @Override
+ public Date retrieveClientTransferProposalDateByLoan(Long clientId) {
+ try {
+ String sql = "SELECT t.transaction_date FROM m_client
c LEFT JOIN m_loan loan ON c.id = loan.client_id AND c.id = ? AND
loan.loan_status_id = ? LEFT JOIN m_loan_transaction t ON loan.id = t.loan_id
AND t.transaction_type_enum = ? ORDER BY t.id DESC LIMIT 1";
+ return this.jdbcTemplate.queryForObject(sql,
Date.class, clientId,
+
LoanStatus.TRANSFER_IN_PROGRESS.getValue(),
LoanTransactionType.INITIATE_TRANSFER.getValue());
+ } catch (final EmptyResultDataAccessException e) {
+ return null;
+
+ }
+ }
+
+ @Override
+ public Date retrieveClientTransferProposalDateBySavings(Long clientId) {
+ try {
+ String sql = "SELECT t.transaction_date FROM m_client c
LEFT JOIN m_savings_account savings ON c.id = savings.client_id AND c.id = ?
AND savings.status_enum = ? LEFT JOIN m_savings_account_transaction t ON
savings.id = t.savings_account_id AND t.transaction_type_enum = ? ORDER BY t.id
DESC LIMIT 1";
+ return this.jdbcTemplate.queryForObject(sql,
Date.class, clientId,
+
SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue(),
+
SavingsAccountTransactionType.INITIATE_TRANSFER.getValue());
+ } catch (final EmptyResultDataAccessException e) {
+ return null;
+
+ }
+ }
+
+ @Override
+ public Date retrieveClientTransferProposalDate(Long clientId) {
+ validateClient(clientId);
+ Date transferDateForLoan =
retrieveClientTransferProposalDateByLoan(clientId);
+ if (transferDateForLoan == null) {
+ transferDateForLoan =
retrieveClientTransferProposalDateBySavings(clientId);
+ }
+ return transferDateForLoan;
+ }
+
+ @Override
+ public void validateClient(Long clientId) {
+ try {
+ final String sql = "SELECT cl.id FROM m_client cl WHERE
cl.id =? ";
+ this.jdbcTemplate.queryForObject(sql, Long.class,
clientId);
+ } catch (final EmptyResultDataAccessException e) {
+ throw new ClientNotFoundException(clientId);
+ }
+ }
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index b6eed1918..411974ee5 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -19,7 +19,17 @@
package org.apache.fineract.portfolio.loanaccount.service;
import java.math.BigDecimal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import org.apache.commons.lang.StringUtils;
import
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
@@ -57,22 +67,44 @@
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
-import org.apache.fineract.portfolio.account.domain.*;
+import org.apache.fineract.portfolio.account.domain.AccountAssociationType;
+import org.apache.fineract.portfolio.account.domain.AccountAssociations;
+import
org.apache.fineract.portfolio.account.domain.AccountAssociationsRepository;
+import
org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
+import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
+import
org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
+import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
+import
org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
+import org.apache.fineract.portfolio.account.domain.AccountTransferTransaction;
+import org.apache.fineract.portfolio.account.domain.AccountTransferType;
+import
org.apache.fineract.portfolio.account.domain.StandingInstructionPriority;
+import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
+import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
import
org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
import
org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
import
org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
import org.apache.fineract.portfolio.accountdetails.domain.AccountType;
-import org.apache.fineract.portfolio.calendar.domain.*;
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.CalendarRepository;
+import org.apache.fineract.portfolio.calendar.domain.CalendarType;
import
org.apache.fineract.portfolio.calendar.exception.CalendarParameterUpdateNotSupportedException;
import org.apache.fineract.portfolio.charge.domain.Charge;
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
-import org.apache.fineract.portfolio.charge.exception.*;
+import
org.apache.fineract.portfolio.charge.exception.ChargeCannotBeUpdatedException;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeAddedException;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeDeletedException;
import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeDeletedException.LOAN_CHARGE_CANNOT_BE_DELETED_REASON;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBePayedException;
import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBePayedException.LOAN_CHARGE_CANNOT_BE_PAYED_REASON;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeUpdatedException;
import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeUpdatedException.LOAN_CHARGE_CANNOT_BE_UPDATED_REASON;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeWaivedException;
import
org.apache.fineract.portfolio.charge.exception.LoanChargeCannotBeWaivedException.LOAN_CHARGE_CANNOT_BE_WAIVED_REASON;
+import
org.apache.fineract.portfolio.charge.exception.LoanChargeNotFoundException;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
import
org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkDisbursalCommand;
@@ -87,9 +119,44 @@
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanaccount.command.LoanUpdateCommand;
-import org.apache.fineract.portfolio.loanaccount.data.*;
-import org.apache.fineract.portfolio.loanaccount.domain.*;
-import org.apache.fineract.portfolio.loanaccount.exception.*;
+import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
+import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
+import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
+import
org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
+import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
+import
org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
+import
org.apache.fineract.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeRepository;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanOverdueInstallmentCharge;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallmentRepository;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
+import
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
+import
org.apache.fineract.portfolio.loanaccount.exception.DateMismatchException;
+import
org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
+import
org.apache.fineract.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanDisbursalException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanMultiDisbursementException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
+import
org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
+import
org.apache.fineract.portfolio.loanaccount.exception.MultiDisbursementDataRequiredException;
import
org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorDomainService;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
@@ -111,6 +178,7 @@
import
org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import
org.apache.fineract.portfolio.savings.exception.InsufficientAccountBalanceException;
+import org.apache.fineract.portfolio.transfer.api.TransferApiConstants;
import org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
@@ -1792,12 +1860,14 @@ public LoanTransaction initiateLoanTransfer(final Loan
loan, final LocalDate tra
AppUser currentUser = getAppUserIfPresent();
this.loanAssembler.setHelpers(loan);
checkClientOrGroupActive(loan);
+ validateTransactionsForTransfer(loan, transferDate);
+
this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_INITIATE_TRANSFER,
constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
final List<Long> existingTransactionIds = new
ArrayList<>(loan.findExistingTransactionIds());
final List<Long> existingReversedTransactionIds = new
ArrayList<>(loan.findExistingReversedTransactionIds());
-
+
final LoanTransaction newTransferTransaction =
LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate,
DateUtils.getLocalDateTimeOfTenant(), currentUser);
loan.addLoanTransaction(newTransferTransaction);
@@ -2942,4 +3012,19 @@ private void
syncExpectedDateWithActualDisbursementDate(final Loan loan, LocalDa
}
}
+
+ private void validateTransactionsForTransfer(final Loan loan, final
LocalDate transferDate) {
+
+ for (LoanTransaction transaction : loan.getLoanTransactions()) {
+ if
((transaction.getTransactionDate().isEqual(transferDate)
+ &&
transaction.getCreatedDateTime().isEqual(transferDate.toDateTimeAtStartOfDay().toLocalDateTime()))
+ ||
transaction.getTransactionDate().isAfter(transferDate)) {
+ throw new
GeneralPlatformDomainRuleException(TransferApiConstants.transferClientLoanException,
+
TransferApiConstants.transferClientLoanExceptionMessage,
transaction.getCreatedDateTime().toLocalDate(),
+ transferDate);
+ }
+
+ }
+
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
index cf5ae0354..2f25e602a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
@@ -111,7 +111,7 @@
@Column(name = "created_date", nullable = false)
private Date createdDate;
- @ManyToOne
+ @ManyToOne
@JoinColumn(name = "appuser_id", nullable = true)
private AppUser appUser;
@@ -790,5 +790,9 @@ public Long getReleaseIdOfHoldAmountTransaction() {
public boolean isAmountOnHoldNotReleased() {
return (isAmountOnHold() &&
getReleaseIdOfHoldAmountTransaction() == null);
- }
+ }
+
+ public Date getCreatedDate() {
+ return createdDate;
+ }
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index 1e7d782ba..b421330b9 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -18,11 +18,25 @@
*/
package org.apache.fineract.portfolio.savings.service;
-import static org.apache.fineract.portfolio.savings.SavingsApiConstants.*;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_CHARGE_RESOURCE_NAME;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.amountParamName;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.chargeIdParamName;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
+import static
org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawBalanceParamName;
import java.math.BigDecimal;
import java.math.MathContext;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import org.apache.commons.lang.StringUtils;
import
org.apache.fineract.accounting.journalentry.service.JournalEntryWritePlatformService;
@@ -32,6 +46,7 @@
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import
org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import
org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -40,7 +55,11 @@
import
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import
org.apache.fineract.organisation.holiday.domain.HolidayRepositoryWrapper;
-import org.apache.fineract.organisation.monetary.domain.*;
+import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
+import
org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.organisation.staff.domain.Staff;
import org.apache.fineract.organisation.staff.domain.StaffRepositoryWrapper;
@@ -72,12 +91,30 @@
import org.apache.fineract.portfolio.savings.data.SavingsAccountDataValidator;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDTO;
import
org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDataValidator;
-import org.apache.fineract.portfolio.savings.domain.*;
-import org.apache.fineract.portfolio.savings.exception.*;
+import
org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransaction;
+import
org.apache.fineract.portfolio.savings.domain.DepositAccountOnHoldTransactionRepository;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountCharge;
+import
org.apache.fineract.portfolio.savings.domain.SavingsAccountChargeRepositoryWrapper;
+import
org.apache.fineract.portfolio.savings.domain.SavingsAccountDomainService;
+import
org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountStatusType;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
+import
org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionRepository;
+import
org.apache.fineract.portfolio.savings.exception.PostInterestAsOnDateException;
import
org.apache.fineract.portfolio.savings.exception.PostInterestAsOnDateException.PostInterestAsOnException_TYPE;
+import
org.apache.fineract.portfolio.savings.exception.PostInterestClosingDateException;
+import
org.apache.fineract.portfolio.savings.exception.SavingsAccountClosingNotAllowedException;
+import
org.apache.fineract.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
+import
org.apache.fineract.portfolio.savings.exception.SavingsOfficerAssignmentException;
+import
org.apache.fineract.portfolio.savings.exception.SavingsOfficerUnassignmentException;
+import
org.apache.fineract.portfolio.savings.exception.TransactionUpdateNotAllowedException;
+import org.apache.fineract.portfolio.transfer.api.TransferApiConstants;
import org.apache.fineract.useradministration.domain.AppUser;
import org.apache.fineract.useradministration.domain.AppUserRepositoryWrapper;
import org.joda.time.LocalDate;
+import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
@@ -720,6 +757,9 @@ public SavingsAccountTransaction
initiateSavingsTransfer(final SavingsAccount sa
final boolean isSavingsInterestPostingAtCurrentPeriodEnd =
this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
+
+ validateTransactionsForTransfer(savingsAccount, transferDate);
+
final Integer financialYearBeginningMonth =
this.configurationDomainService.retrieveFinancialYearBeginningMonth();
this.savingAccountAssembler.setHelpers(savingsAccount);
final Set<Long> existingTransactionIds = new HashSet<>();
@@ -1497,4 +1537,19 @@ public CommandProcessingResult unblockDebits(final Long
savingsId) {
return new
CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
+
+ private void validateTransactionsForTransfer(final SavingsAccount
savingsAccount, final LocalDate transferDate) {
+
+ for (SavingsAccountTransaction transaction :
savingsAccount.getTransactions()) {
+ if
((transaction.getTransactionLocalDate().isEqual(transferDate)
+ &&
transaction.getTransactionLocalDate().isAfter(new LocalDate(transferDate)))
+ ||
transaction.getTransactionLocalDate().isAfter(transferDate)) {
+ throw new
GeneralPlatformDomainRuleException(TransferApiConstants.transferClientSavingsException,
+
TransferApiConstants.transferClientSavingsException, new
LocalDate(transaction.getCreatedDate()),
+ transferDate);
+ }
+
+ }
+
+ }
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/api/TransferApiConstants.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/api/TransferApiConstants.java
index 0135f0055..37519e92e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/api/TransferApiConstants.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/api/TransferApiConstants.java
@@ -18,24 +18,26 @@
*/
package org.apache.fineract.portfolio.transfer.api;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
public class TransferApiConstants {
- // general
- public static final String localeParamName = "locale";
- public static final String dateFormatParamName = "dateFormat";
-
- // request parameters
- public static final String idParamName = "id";
- public static final String destinationGroupIdParamName =
"destinationGroupId";
- public static final String clients = "clients";
- public static final String inheritDestinationGroupLoanOfficer =
"inheritDestinationGroupLoanOfficer";
- public static final String newStaffIdParamName = "staffId";
- public static final String transferActiveLoans = "transferActiveLoans";
- public static final String destinationOfficeIdParamName =
"destinationOfficeId";
- public static final String note = "note";
+ // general
+ public static final String localeParamName = "locale";
+ public static final String dateFormatParamName = "dateFormat";
+ // request parameters
+ public static final String idParamName = "id";
+ public static final String destinationGroupIdParamName =
"destinationGroupId";
+ public static final String clients = "clients";
+ public static final String inheritDestinationGroupLoanOfficer =
"inheritDestinationGroupLoanOfficer";
+ public static final String newStaffIdParamName = "staffId";
+ public static final String transferActiveLoans = "transferActiveLoans";
+ public static final String destinationOfficeIdParamName =
"destinationOfficeId";
+ public static final String note = "note";
+ public static final String transferDate = "transferDate";
+ public static final String transferClientLoanException =
"error.msg.caanot.transfer.client.as.loan.transaction.present.on.or.after.transfer.date";
+ public static final String transferClientLoanExceptionMessage = "error
msg caanot transfer client as loan transaction present on or after transfer
date";
+ public static final String transferClientSavingsException =
"error.msg.caanot.transfer.client.as.savings.transaction.present.on.or.after.transfer.date";
+ public static final String transferClientSavingsExceptionMessage =
"error msg caanot transfer client as savings transaction present on or after
transfer date";
+ public static final String transferClientToSameOfficeException =
"error.msg.cannot.transfer.clinet.as.selected.office.and.current.office.are.same";
+ public static final String transferClientToSameOfficeExceptionMessage =
"error.msg.cannot.transfer.clinet.as.selected.office.and.current.office.are.same";
}
\ No newline at end of file
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/data/TransfersDataValidator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/data/TransfersDataValidator.java
index 273e87a08..b769212a3 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/data/TransfersDataValidator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/data/TransfersDataValidator.java
@@ -35,6 +35,7 @@
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants;
import org.apache.fineract.portfolio.transfer.api.TransferApiConstants;
+import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -54,7 +55,7 @@
private static final Set<String>
PROPOSE_CLIENT_TRANSFER_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(TransferApiConstants.localeParamName,
TransferApiConstants.dateFormatParamName,
TransferApiConstants.destinationOfficeIdParamName,
TransferApiConstants.transferActiveLoans,
- TransferApiConstants.note));
+ TransferApiConstants.note,
TransferApiConstants.transferDate));
private static final Set<String> ACCEPT_CLIENT_TRANSFER_DATA_PARAMETERS
= new HashSet<>(
Arrays.asList(TransferApiConstants.newStaffIdParamName,
TransferApiConstants.destinationGroupIdParamName,
@@ -132,7 +133,7 @@ public void validateForProposeClientTransfer(final String
json) {
.extractLongNamed(TransferApiConstants.destinationOfficeIdParamName, element);
baseDataValidator.reset().parameter(TransferApiConstants.destinationOfficeIdParamName).value(destinationOfficeId).notNull()
.integerGreaterThanZero();
-
+
validateNote(baseDataValidator, element);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java
index d037c1612..b464dba9b 100755
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java
@@ -20,13 +20,12 @@
import java.util.ArrayList;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
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.organisation.office.domain.Office;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
@@ -42,7 +41,6 @@
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.domain.ClientStatus;
import
org.apache.fineract.portfolio.client.exception.ClientHasBeenClosedException;
-import
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.portfolio.group.domain.GroupRepositoryWrapper;
import org.apache.fineract.portfolio.group.exception.ClientNotInGroupException;
@@ -60,6 +58,7 @@
import
org.apache.fineract.portfolio.transfer.exception.ClientNotAwaitingTransferApprovalOrOnHoldException;
import
org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException;
import
org.apache.fineract.portfolio.transfer.exception.TransferNotSupportedException.TRANSFER_NOT_SUPPORTED_REASON;
+import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -295,8 +294,13 @@ public CommandProcessingResult proposeClientTransfer(final
Long clientId, final
final Long destinationOfficeId =
jsonCommand.longValueOfParameterNamed(TransferApiConstants.destinationOfficeIdParamName);
final Office office =
this.officeRepository.findOneWithNotFoundDetection(destinationOfficeId);
final Client client =
this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
- handleClientTransferLifecycleEvent(client, office,
TransferEventType.PROPOSAL, jsonCommand);
- this.clientRepositoryWrapper.save(client);
+ 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) //
@@ -369,6 +373,7 @@ private void handleClientTransferLifecycleEvent(final
Client client, final Offic
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());
}
@@ -387,17 +392,17 @@ private void handleClientTransferLifecycleEvent(final
Client client, final Offic
if (loan.isDisbursed() && !loan.isClosed()) {
switch (transferEventType) {
case ACCEPTANCE:
-
this.loanWritePlatformService.acceptLoanTransfer(loan,
DateUtils.getLocalDateOfTenant(),
+
this.loanWritePlatformService.acceptLoanTransfer(loan,
loan.getLastUserTransactionDate(),
destinationOffice, staff);
break;
case PROPOSAL:
-
this.loanWritePlatformService.initiateLoanTransfer(loan,
DateUtils.getLocalDateOfTenant());
+
this.loanWritePlatformService.initiateLoanTransfer(loan, transferDate);
break;
case REJECTION:
this.loanWritePlatformService.rejectLoanTransfer(loan);
break;
case WITHDRAWAL:
-
this.loanWritePlatformService.withdrawLoanTransfer(loan,
DateUtils.getLocalDateOfTenant());
+
this.loanWritePlatformService.withdrawLoanTransfer(loan,
loan.getLastUserTransactionDate());
}
}
}
@@ -411,18 +416,18 @@ private void handleClientTransferLifecycleEvent(final
Client client, final Offic
switch (transferEventType) {
case ACCEPTANCE:
this.savingsAccountWritePlatformService.acceptSavingsTransfer(savingsAccount,
- DateUtils.getLocalDateOfTenant(),
destinationOffice, staff);
+
savingsAccount.retrieveLastTransactionDate(), destinationOffice, staff);
break;
case PROPOSAL:
this.savingsAccountWritePlatformService.initiateSavingsTransfer(savingsAccount,
- DateUtils.getLocalDateOfTenant());
+ transferDate);
break;
case REJECTION:
this.savingsAccountWritePlatformService.rejectSavingsTransfer(savingsAccount);
break;
case WITHDRAWAL:
this.savingsAccountWritePlatformService.withdrawSavingsTransfer(savingsAccount,
- DateUtils.getLocalDateOfTenant());
+
savingsAccount.retrieveLastTransactionDate());
}
}
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> ADDING TRANSFER DATE WHEN A CLIENT IS TRANSFERED FROM ONE BRANCH TO ANOTHER
> ---------------------------------------------------------------------------
>
> Key: FINERACT-627
> URL: https://issues.apache.org/jira/browse/FINERACT-627
> Project: Apache Fineract
> Issue Type: New Feature
> Components: Client
> Affects Versions: 1.1.0
> Environment: Ubuntu 16
> Reporter: Jimmy Jubha Mayala
> Assignee: Shruthi M R
> Priority: Major
> Labels: easyfix, gsoc, p2
> Fix For: 1.2.0
>
>
> We need this feature in Mifosx. The current scenario is, when you want to
> transfer a client from one branch to another you do not need to choose which
> date the transfer was made, Mifos x picks the current date of the transfer.
> so for us we find it to be a big need to have a place to select a date when
> we are transferring a client from one branch to another. simply because most
> of the time our clients transfer are done with back dates. This helps put a
> real record concerning a client transfer.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)