FINERACT-627 Back dated client transfer
This commit is contained in:
@@ -5761,7 +5761,7 @@ Request Body:
|
||||
<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 @@ Request Body:
|
||||
Content-Type: application/json
|
||||
Request Body:
|
||||
{
|
||||
"transferDate":"28 August 2018",
|
||||
"destinationOfficeId":"2",
|
||||
"note":"Client Relocating to Bangalore"
|
||||
}
|
||||
|
||||
+19
-4
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.client.api;
|
||||
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.data.ObligeeData;
|
||||
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 class ClientsApiResource {
|
||||
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 class ClientsApiResource {
|
||||
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);
|
||||
}
|
||||
}
|
||||
+9
@@ -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 @@ public interface ClientReadPlatformService {
|
||||
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);
|
||||
}
|
||||
+54
-3
@@ -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.sql.SQLException;
|
||||
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.ClientStatus;
|
||||
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 class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
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 class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
this.configurationReadPlatformService=configurationReadPlatformService;
|
||||
this.entityDatatableChecksReadService = entityDatatableChecksReadService;
|
||||
this.columnValidator = columnValidator;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientData retrieveTemplate(final Long officeId, final boolean staffInSelectedOfficeOnly) {
|
||||
@@ -816,5 +822,50 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+93
-8
@@ -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.organisation.workingdays.domain.WorkingDaysRepository
|
||||
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.domain.Group;
|
||||
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.domain.PaymentDetail;
|
||||
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 class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
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 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -111,7 +111,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
|
||||
@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 final class SavingsAccountTransaction extends AbstractPersistableCustom<L
|
||||
|
||||
public boolean isAmountOnHoldNotReleased() {
|
||||
return (isAmountOnHold() && getReleaseIdOfHoldAmountTransaction() == null);
|
||||
}
|
||||
}
|
||||
|
||||
public Date getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
}
|
||||
+60
-5
@@ -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.ApiParameterError;
|
||||
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.data.StatusEnum;
|
||||
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.SavingsAccountChargeDataValida
|
||||
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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
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 class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+19
-17
@@ -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";
|
||||
}
|
||||
+3
-2
@@ -35,6 +35,7 @@ import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
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 @@ public final class TransfersDataValidator {
|
||||
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 final class TransfersDataValidator {
|
||||
.extractLongNamed(TransferApiConstants.destinationOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(TransferApiConstants.destinationOfficeIdParamName).value(destinationOfficeId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
|
||||
validateNote(baseDataValidator, element);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
+16
-11
@@ -20,13 +20,12 @@ package org.apache.fineract.portfolio.transfer.service;
|
||||
|
||||
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.Client;
|
||||
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.ClientNotAwaitingTransfe
|
||||
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 class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
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 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
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 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
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 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user