feat: implement full current account transaction write service
- New CurrentAccountTransactionWritePlatformService interface with deposit, withdrawal, holdAmount, releaseAmount, undoTransaction, reverseTransaction, and adjustTransaction operations - New CurrentAccountTransactionWritePlatformServiceImpl using m_current_account tables directly (not m_savings_account), with GL journal entry posting - Add holdAmount, releaseAmount, reversal factory methods to CurrentAccountTransaction - Wire all 7 current account transaction command handlers to new write service - Fix CurrentAccountTransactionsApiResource template SQL column: currency_multiplesof - Fix account number search in SearchParameters Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b25d5a30d2
commit
ce0fb18eeb
+1
@@ -44,6 +44,7 @@ public class SearchParameters {
|
|||||||
private String orderBy;
|
private String orderBy;
|
||||||
private String sortOrder;
|
private String sortOrder;
|
||||||
private String accountNo;
|
private String accountNo;
|
||||||
|
private Integer depositType;
|
||||||
private String currencyCode;
|
private String currencyCode;
|
||||||
private Long staffId;
|
private Long staffId;
|
||||||
private Long loanId;
|
private Long loanId;
|
||||||
|
|||||||
+44
@@ -146,4 +146,48 @@ public class CurrentAccountTransaction extends AbstractPersistableCustom<Long> {
|
|||||||
txn.submittedOnDate = transactionDate;
|
txn.submittedOnDate = transactionDate;
|
||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transactionTypeEnum = 8 (Hold Amount)
|
||||||
|
public static CurrentAccountTransaction holdAmount(CurrentAccount account, Office office,
|
||||||
|
BigDecimal amount, LocalDate transactionDate, String reasonForBlock) {
|
||||||
|
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||||
|
txn.currentAccount = account;
|
||||||
|
txn.office = office;
|
||||||
|
txn.transactionTypeEnum = 8;
|
||||||
|
txn.amount = amount;
|
||||||
|
txn.transactionDate = transactionDate;
|
||||||
|
txn.lienTransaction = true;
|
||||||
|
txn.reasonForBlock = reasonForBlock;
|
||||||
|
txn.submittedOnDate = transactionDate;
|
||||||
|
return txn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transactionTypeEnum = 9 (Release Amount)
|
||||||
|
public static CurrentAccountTransaction releaseAmount(CurrentAccount account, Office office,
|
||||||
|
BigDecimal amount, LocalDate transactionDate, Long holdTransactionId) {
|
||||||
|
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||||
|
txn.currentAccount = account;
|
||||||
|
txn.office = office;
|
||||||
|
txn.transactionTypeEnum = 9;
|
||||||
|
txn.amount = amount;
|
||||||
|
txn.transactionDate = transactionDate;
|
||||||
|
txn.releaseIdOfHoldAmountTransaction = holdTransactionId;
|
||||||
|
txn.submittedOnDate = transactionDate;
|
||||||
|
return txn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transactionTypeEnum = 7 (Reversal / Undo)
|
||||||
|
public static CurrentAccountTransaction reversal(CurrentAccount account, Office office,
|
||||||
|
BigDecimal amount, LocalDate transactionDate, Long originalTransactionId) {
|
||||||
|
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||||
|
txn.currentAccount = account;
|
||||||
|
txn.office = office;
|
||||||
|
txn.transactionTypeEnum = 7;
|
||||||
|
txn.amount = amount;
|
||||||
|
txn.transactionDate = transactionDate;
|
||||||
|
txn.reversal = true;
|
||||||
|
txn.originalTransactionId = originalTransactionId;
|
||||||
|
txn.submittedOnDate = transactionDate;
|
||||||
|
return txn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -26,4 +26,6 @@ public interface CurrentAccountReadPlatformService {
|
|||||||
Map<String, Object> retrieveOne(Long accountId);
|
Map<String, Object> retrieveOne(Long accountId);
|
||||||
|
|
||||||
List<Map<String, Object>> retrieveAll();
|
List<Map<String, Object>> retrieveAll();
|
||||||
|
|
||||||
|
List<Map<String, Object>> retrieveAll(Integer offset, Integer limit, String accountNo, String clientName);
|
||||||
}
|
}
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* 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.currentaccount.service;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
|
||||||
|
public interface CurrentAccountTransactionWritePlatformService {
|
||||||
|
|
||||||
|
CommandProcessingResult deposit(Long accountId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult withdrawal(Long accountId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult holdAmount(Long accountId, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult releaseAmount(Long accountId, Long transactionId);
|
||||||
|
|
||||||
|
CommandProcessingResult undoTransaction(Long accountId, Long transactionId, boolean isReversal);
|
||||||
|
|
||||||
|
CommandProcessingResult reverseTransaction(Long accountId, Long transactionId, boolean isReversal, JsonCommand command);
|
||||||
|
|
||||||
|
CommandProcessingResult adjustTransaction(Long accountId, Long transactionId, JsonCommand command);
|
||||||
|
}
|
||||||
+57
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.portfolio.savings.api;
|
package org.apache.fineract.portfolio.savings.api;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
@@ -32,6 +34,10 @@ import jakarta.ws.rs.QueryParam;
|
|||||||
import jakarta.ws.rs.core.Context;
|
import jakarta.ws.rs.core.Context;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.UriInfo;
|
import jakarta.ws.rs.core.UriInfo;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
@@ -43,10 +49,14 @@ import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamE
|
|||||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.exception.CurrentAccountNotFoundException;
|
||||||
|
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||||
|
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadService;
|
||||||
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
||||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
|
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Path("/v1/currentaccounts/{accountId}/transactions")
|
@Path("/v1/currentaccounts/{accountId}/transactions")
|
||||||
@@ -55,11 +65,58 @@ import org.springframework.stereotype.Component;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CurrentAccountTransactionsApiResource {
|
public class CurrentAccountTransactionsApiResource {
|
||||||
|
|
||||||
|
private static final Gson GSON = new GsonBuilder().serializeNulls().create();
|
||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final DefaultToApiJsonSerializer<SavingsAccountTransactionData> toApiJsonSerializer;
|
private final DefaultToApiJsonSerializer<SavingsAccountTransactionData> toApiJsonSerializer;
|
||||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||||
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
|
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
|
||||||
|
private final PaymentTypeReadService paymentTypeReadService;
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("template")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
@Operation(summary = "Retrieve current account transaction template")
|
||||||
|
@ApiResponse(responseCode = "200", description = "OK")
|
||||||
|
public String retrieveTemplate(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.CURRENT_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
final String sql = "SELECT ca.currency_code, ca.currency_digits, ca.currency_multiplesof, "
|
||||||
|
+ "mc.display_symbol, mc.name AS currency_name, mc.internationalized_name_code "
|
||||||
|
+ "FROM m_current_account ca "
|
||||||
|
+ "LEFT JOIN m_currency mc ON mc.code = ca.currency_code "
|
||||||
|
+ "WHERE ca.id = ?";
|
||||||
|
|
||||||
|
final Map<String, Object> template;
|
||||||
|
try {
|
||||||
|
template = jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
|
||||||
|
final Map<String, Object> map = new LinkedHashMap<>();
|
||||||
|
final LocalDate today = LocalDate.now();
|
||||||
|
map.put("date", new int[] { today.getYear(), today.getMonthValue(), today.getDayOfMonth() });
|
||||||
|
|
||||||
|
final Map<String, Object> currency = new LinkedHashMap<>();
|
||||||
|
currency.put("code", rs.getString("currency_code"));
|
||||||
|
currency.put("decimalPlaces", rs.getInt("currency_digits"));
|
||||||
|
currency.put("inMultiplesOf", rs.getInt("currency_multiplesof"));
|
||||||
|
currency.put("displaySymbol", rs.getString("display_symbol"));
|
||||||
|
currency.put("name", rs.getString("currency_name"));
|
||||||
|
currency.put("nameCode", rs.getString("internationalized_name_code"));
|
||||||
|
map.put("currency", currency);
|
||||||
|
return map;
|
||||||
|
}, accountId);
|
||||||
|
} catch (org.springframework.dao.EmptyResultDataAccessException e) {
|
||||||
|
throw new CurrentAccountNotFoundException(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Collection<PaymentTypeData> paymentTypeOptions = paymentTypeReadService.retrieveAllPaymentTypes();
|
||||||
|
template.put("paymentTypeOptions", paymentTypeOptions);
|
||||||
|
|
||||||
|
return GSON.toJson(template);
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{transactionId}")
|
@Path("{transactionId}")
|
||||||
|
|||||||
+4
-2
@@ -101,10 +101,12 @@ public class CurrentAccountsApiResource {
|
|||||||
@QueryParam("offset") final Integer offset,
|
@QueryParam("offset") final Integer offset,
|
||||||
@QueryParam("limit") final Integer limit,
|
@QueryParam("limit") final Integer limit,
|
||||||
@QueryParam("orderBy") final String orderBy,
|
@QueryParam("orderBy") final String orderBy,
|
||||||
@QueryParam("sortOrder") final String sortOrder) {
|
@QueryParam("sortOrder") final String sortOrder,
|
||||||
|
@QueryParam("accountNo") @Parameter(description = "accountNo") final String accountNo,
|
||||||
|
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName) {
|
||||||
|
|
||||||
context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.CURRENT_ACCOUNT_RESOURCE_NAME);
|
context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.CURRENT_ACCOUNT_RESOURCE_NAME);
|
||||||
final List<Map<String, Object>> accounts = currentAccountReadPlatformService.retrieveAll();
|
final List<Map<String, Object>> accounts = currentAccountReadPlatformService.retrieveAll(offset, limit, accountNo, clientName);
|
||||||
return GSON.toJson(accounts);
|
return GSON.toJson(accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -159,7 +159,9 @@ public class FixedDepositAccountsApiResource {
|
|||||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
|
||||||
|
@QueryParam("accountNo") @Parameter(description = "accountNo") final String accountNo,
|
||||||
|
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName) {
|
||||||
|
|
||||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME);
|
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME);
|
||||||
sqlValidator.validate(orderBy);
|
sqlValidator.validate(orderBy);
|
||||||
@@ -170,7 +172,7 @@ public class FixedDepositAccountsApiResource {
|
|||||||
|
|
||||||
if (paginationParameters.isPaged()) {
|
if (paginationParameters.isPaged()) {
|
||||||
final Page<DepositAccountData> account = this.depositAccountReadPlatformService
|
final Page<DepositAccountData> account = this.depositAccountReadPlatformService
|
||||||
.retrieveAllPaged(DepositAccountType.FIXED_DEPOSIT, paginationParameters);
|
.retrieveAllPaged(DepositAccountType.FIXED_DEPOSIT, paginationParameters, accountNo, clientName);
|
||||||
return this.toApiJsonSerializer.serialize(settings, account,
|
return this.toApiJsonSerializer.serialize(settings, account,
|
||||||
DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
DepositsApiConstants.FIXED_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -140,7 +140,9 @@ public class RecurringDepositAccountsApiResource {
|
|||||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
|
||||||
|
@QueryParam("accountNo") @Parameter(description = "accountNo") final String accountNo,
|
||||||
|
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName) {
|
||||||
|
|
||||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME);
|
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME);
|
||||||
sqlValidator.validate(orderBy);
|
sqlValidator.validate(orderBy);
|
||||||
@@ -151,7 +153,7 @@ public class RecurringDepositAccountsApiResource {
|
|||||||
|
|
||||||
if (paginationParameters.isPaged()) {
|
if (paginationParameters.isPaged()) {
|
||||||
final Page<DepositAccountData> account = this.depositAccountReadPlatformService
|
final Page<DepositAccountData> account = this.depositAccountReadPlatformService
|
||||||
.retrieveAllPaged(DepositAccountType.RECURRING_DEPOSIT, paginationParameters);
|
.retrieveAllPaged(DepositAccountType.RECURRING_DEPOSIT, paginationParameters, accountNo, clientName);
|
||||||
return this.toApiJsonSerializer.serialize(settings, account,
|
return this.toApiJsonSerializer.serialize(settings, account,
|
||||||
DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
DepositsApiConstants.RECURRING_DEPOSIT_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -130,7 +130,10 @@ public class SavingsAccountsApiResource {
|
|||||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
|
||||||
|
@QueryParam("accountNo") @Parameter(description = "accountNo") final String accountNo,
|
||||||
|
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName,
|
||||||
|
@QueryParam("depositType") @Parameter(description = "depositType") final Integer depositType) {
|
||||||
|
|
||||||
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
@@ -138,7 +141,7 @@ public class SavingsAccountsApiResource {
|
|||||||
sqlValidator.validate(sortOrder);
|
sqlValidator.validate(sortOrder);
|
||||||
sqlValidator.validate(externalId);
|
sqlValidator.validate(externalId);
|
||||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
||||||
.orderBy(orderBy).sortOrder(sortOrder).build();
|
.orderBy(orderBy).sortOrder(sortOrder).accountNo(accountNo).name(clientName).depositType(depositType).build();
|
||||||
|
|
||||||
final Page<SavingsAccountData> products = savingsAccountReadPlatformService.retrieveAll(searchParameters);
|
final Page<SavingsAccountData> products = savingsAccountReadPlatformService.retrieveAll(searchParameters);
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "ADJUSTTRANSACTION")
|
@CommandType(entity = "CURRENTACCOUNT", action = "ADJUSTTRANSACTION")
|
||||||
public class CurrentAccountTransactionAdjustmentCommandHandler implements NewCommandSourceHandler {
|
public class CurrentAccountTransactionAdjustmentCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public CurrentAccountTransactionAdjustmentCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public CurrentAccountTransactionAdjustmentCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +42,6 @@ public class CurrentAccountTransactionAdjustmentCommandHandler implements NewCom
|
|||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
final Long transactionId = Long.valueOf(command.getTransactionId());
|
final Long transactionId = Long.valueOf(command.getTransactionId());
|
||||||
return this.writePlatformService.adjustSavingsTransaction(command.getSavingsId(), transactionId, command);
|
return this.writePlatformService.adjustTransaction(command.getSavingsId(), transactionId, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "DEPOSIT")
|
@CommandType(entity = "CURRENTACCOUNT", action = "DEPOSIT")
|
||||||
public class DepositCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class DepositCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DepositCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public DepositCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "HOLDAMOUNT")
|
@CommandType(entity = "CURRENTACCOUNT", action = "HOLDAMOUNT")
|
||||||
public class HoldAmountCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class HoldAmountCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public HoldAmountCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public HoldAmountCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "RELEASEAMOUNT")
|
@CommandType(entity = "CURRENTACCOUNT", action = "RELEASEAMOUNT")
|
||||||
public class ReleaseAmountCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class ReleaseAmountCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReleaseAmountCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public ReleaseAmountCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "REVERSETRANSACTION")
|
@CommandType(entity = "CURRENTACCOUNT", action = "REVERSETRANSACTION")
|
||||||
public class ReverseTransactionCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class ReverseTransactionCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public ReverseTransactionCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public ReverseTransactionCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "UNDOTRANSACTION")
|
@CommandType(entity = "CURRENTACCOUNT", action = "UNDOTRANSACTION")
|
||||||
public class UndoTransactionCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class UndoTransactionCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UndoTransactionCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public UndoTransactionCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "CURRENTACCOUNT", action = "WITHDRAWAL")
|
@CommandType(entity = "CURRENTACCOUNT", action = "WITHDRAWAL")
|
||||||
public class WithdrawCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
public class WithdrawCurrentAccountCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
private final SavingsAccountWritePlatformService writePlatformService;
|
private final CurrentAccountTransactionWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public WithdrawCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) {
|
public WithdrawCurrentAccountCommandHandler(final CurrentAccountTransactionWritePlatformService writePlatformService) {
|
||||||
this.writePlatformService = writePlatformService;
|
this.writePlatformService = writePlatformService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.fineract.portfolio.currentaccount.exception.CurrentAccountNotFoundException;
|
import org.apache.fineract.portfolio.currentaccount.exception.CurrentAccountNotFoundException;
|
||||||
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountReadPlatformService;
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountReadPlatformService;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
@@ -226,6 +227,45 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> retrieveAll(final Integer offset, final Integer limit, final String accountNo,
|
||||||
|
final String clientName) {
|
||||||
|
final StringBuilder sqlBuilder = new StringBuilder(BASE_SQL);
|
||||||
|
final List<Object> params = new ArrayList<>();
|
||||||
|
boolean hasWhere = false;
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(accountNo)) {
|
||||||
|
sqlBuilder.append(hasWhere ? " AND " : " WHERE ");
|
||||||
|
sqlBuilder.append("ca.account_no LIKE ?");
|
||||||
|
params.add("%" + accountNo + "%");
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(clientName)) {
|
||||||
|
sqlBuilder.append(hasWhere ? " AND " : " WHERE ");
|
||||||
|
sqlBuilder.append("c.display_name LIKE ?");
|
||||||
|
params.add("%" + clientName + "%");
|
||||||
|
hasWhere = true;
|
||||||
|
}
|
||||||
|
if (limit != null && limit > 0) {
|
||||||
|
sqlBuilder.append(" LIMIT ?");
|
||||||
|
params.add(limit);
|
||||||
|
if (offset != null && offset >= 0) {
|
||||||
|
sqlBuilder.append(" OFFSET ?");
|
||||||
|
params.add(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, Object>> rows = jdbcTemplate.query(sqlBuilder.toString(), new FlatRowMapper(), params.toArray());
|
||||||
|
List<Map<String, Object>> result = new ArrayList<>();
|
||||||
|
for (Map<String, Object> row : rows) {
|
||||||
|
final Map<String, Object> response = buildStructuredResponse(row);
|
||||||
|
final Long id = ((Number) row.get("id")).longValue();
|
||||||
|
response.put("charges", retrieveCharges(id));
|
||||||
|
result.add(response);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Object> buildStructuredResponse(Map<String, Object> row) {
|
private Map<String, Object> buildStructuredResponse(Map<String, Object> row) {
|
||||||
Map<String, Object> out = new LinkedHashMap<>();
|
Map<String, Object> out = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
|||||||
+468
@@ -0,0 +1,468 @@
|
|||||||
|
/**
|
||||||
|
* 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.savings.service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForSavings;
|
||||||
|
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||||
|
import org.apache.fineract.accounting.journalentry.domain.JournalEntry;
|
||||||
|
import org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository;
|
||||||
|
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
|
||||||
|
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||||
|
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.security.service.PlatformSecurityContext;
|
||||||
|
import org.apache.fineract.organisation.office.domain.Office;
|
||||||
|
import org.apache.fineract.portfolio.PortfolioProductType;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountRepository;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountTransaction;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountTransactionRepository;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.exception.CurrentAccountNotFoundException;
|
||||||
|
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountTransactionWritePlatformService;
|
||||||
|
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProduct;
|
||||||
|
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CurrentAccountTransactionWritePlatformServiceImpl implements CurrentAccountTransactionWritePlatformService {
|
||||||
|
|
||||||
|
// Savings entity type used for GL journal entries (EntityType.SAVINGS = 2)
|
||||||
|
private static final Integer ENTITY_TYPE_SAVINGS = 2;
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final CurrentAccountRepository currentAccountRepository;
|
||||||
|
private final CurrentAccountTransactionRepository currentAccountTransactionRepository;
|
||||||
|
private final CurrentProductRepository currentProductRepository;
|
||||||
|
private final ProductToGLAccountMappingRepository productToGLAccountMappingRepository;
|
||||||
|
private final JournalEntryRepository journalEntryRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult deposit(final Long accountId, final JsonCommand command) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
final Office office = account.getOffice();
|
||||||
|
|
||||||
|
LocalDate txnDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
|
if (txnDate == null) txnDate = LocalDate.now();
|
||||||
|
|
||||||
|
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||||
|
validatePositiveAmount(amount, accountId, "deposit");
|
||||||
|
|
||||||
|
final String refNo = command.stringValueOfParameterNamed("accountNumber");
|
||||||
|
|
||||||
|
final CurrentAccountTransaction txn = CurrentAccountTransaction.deposit(account, office, amount, txnDate, refNo);
|
||||||
|
|
||||||
|
final BigDecimal oldBalance = safeBalance(account.getAccountBalanceDerived());
|
||||||
|
final BigDecimal newBalance = oldBalance.add(amount);
|
||||||
|
txn.setRunningBalanceDerived(newBalance);
|
||||||
|
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(txn);
|
||||||
|
|
||||||
|
account.setAccountBalanceDerived(newBalance);
|
||||||
|
account.setTotalDepositsDerived(safeBalance(account.getTotalDepositsDerived()).add(amount));
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
postTransactionGl(account, txn, JournalEntryType.DEBIT, JournalEntryType.CREDIT, "Current Account Deposit");
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(txn.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.withClientId(account.getClient() != null ? account.getClient().getId() : null)
|
||||||
|
.withOfficeId(office != null ? office.getId() : null)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult withdrawal(final Long accountId, final JsonCommand command) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
final Office office = account.getOffice();
|
||||||
|
|
||||||
|
LocalDate txnDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
|
if (txnDate == null) txnDate = LocalDate.now();
|
||||||
|
|
||||||
|
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||||
|
validatePositiveAmount(amount, accountId, "withdrawal");
|
||||||
|
|
||||||
|
final BigDecimal currentBalance = safeBalance(account.getAccountBalanceDerived());
|
||||||
|
final BigDecimal onHold = safeBalance(account.getOnHoldFundsDerived());
|
||||||
|
final BigDecimal available = currentBalance.subtract(onHold);
|
||||||
|
|
||||||
|
if (!account.isAllowOverdraft() && amount.compareTo(available) > 0) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.insufficient.balance",
|
||||||
|
"Insufficient available balance. Available: " + available + ", Requested: " + amount, accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String refNo = command.stringValueOfParameterNamed("accountNumber");
|
||||||
|
|
||||||
|
final CurrentAccountTransaction txn = CurrentAccountTransaction.withdrawal(account, office, amount, txnDate, refNo);
|
||||||
|
|
||||||
|
final BigDecimal newBalance = currentBalance.subtract(amount);
|
||||||
|
txn.setRunningBalanceDerived(newBalance);
|
||||||
|
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(txn);
|
||||||
|
|
||||||
|
account.setAccountBalanceDerived(newBalance);
|
||||||
|
account.setTotalWithdrawalsDerived(safeBalance(account.getTotalWithdrawalsDerived()).add(amount));
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
// Withdrawal GL: DR SAVINGS_CONTROL (liability down), CR SAVINGS_REFERENCE (cash out)
|
||||||
|
postTransactionGl(account, txn, JournalEntryType.CREDIT, JournalEntryType.DEBIT, "Current Account Withdrawal");
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(txn.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.withClientId(account.getClient() != null ? account.getClient().getId() : null)
|
||||||
|
.withOfficeId(office != null ? office.getId() : null)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult holdAmount(final Long accountId, final JsonCommand command) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
final Office office = account.getOffice();
|
||||||
|
|
||||||
|
LocalDate txnDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
|
if (txnDate == null) txnDate = LocalDate.now();
|
||||||
|
|
||||||
|
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||||
|
validatePositiveAmount(amount, accountId, "hold amount");
|
||||||
|
|
||||||
|
final BigDecimal currentBalance = safeBalance(account.getAccountBalanceDerived());
|
||||||
|
final BigDecimal onHold = safeBalance(account.getOnHoldFundsDerived());
|
||||||
|
final BigDecimal available = currentBalance.subtract(onHold);
|
||||||
|
|
||||||
|
if (amount.compareTo(available) > 0) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.insufficient.balance.for.hold",
|
||||||
|
"Insufficient available balance to place hold. Available: " + available + ", Requested: " + amount, accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String reason = command.stringValueOfParameterNamed("reasonForBlock");
|
||||||
|
|
||||||
|
final CurrentAccountTransaction txn = CurrentAccountTransaction.holdAmount(account, office, amount, txnDate, reason);
|
||||||
|
txn.setRunningBalanceDerived(currentBalance);
|
||||||
|
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(txn);
|
||||||
|
|
||||||
|
account.setOnHoldFundsDerived(onHold.add(amount));
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(txn.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.withClientId(account.getClient() != null ? account.getClient().getId() : null)
|
||||||
|
.withOfficeId(office != null ? office.getId() : null)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult releaseAmount(final Long accountId, final Long transactionId) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
final Office office = account.getOffice();
|
||||||
|
|
||||||
|
final CurrentAccountTransaction holdTxn = currentAccountTransactionRepository.findById(transactionId)
|
||||||
|
.orElseThrow(() -> new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.current.account.transaction.not.found",
|
||||||
|
"Hold transaction not found: " + transactionId, transactionId));
|
||||||
|
|
||||||
|
if (!holdTxn.getCurrentAccount().getId().equals(accountId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction does not belong to this account.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holdTxn.isReversed()) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.already.reversed",
|
||||||
|
"Hold transaction is already released/reversed.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final BigDecimal holdAmount = holdTxn.getAmount();
|
||||||
|
final BigDecimal currentBalance = safeBalance(account.getAccountBalanceDerived());
|
||||||
|
|
||||||
|
// Mark hold transaction as reversed
|
||||||
|
holdTxn.setReversed(true);
|
||||||
|
currentAccountTransactionRepository.save(holdTxn);
|
||||||
|
|
||||||
|
// Create release transaction
|
||||||
|
final CurrentAccountTransaction releaseTxn = CurrentAccountTransaction.releaseAmount(
|
||||||
|
account, office, holdAmount, LocalDate.now(), transactionId);
|
||||||
|
releaseTxn.setRunningBalanceDerived(currentBalance);
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(releaseTxn);
|
||||||
|
|
||||||
|
// Reduce onHold
|
||||||
|
final BigDecimal onHold = safeBalance(account.getOnHoldFundsDerived());
|
||||||
|
account.setOnHoldFundsDerived(onHold.subtract(holdAmount).max(BigDecimal.ZERO));
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(releaseTxn.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult undoTransaction(final Long accountId, final Long transactionId, final boolean isReversal) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
|
||||||
|
final CurrentAccountTransaction txn = currentAccountTransactionRepository.findById(transactionId)
|
||||||
|
.orElseThrow(() -> new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction not found: " + transactionId, transactionId));
|
||||||
|
|
||||||
|
if (!txn.getCurrentAccount().getId().equals(accountId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction does not belong to this account.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txn.isReversed()) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.already.reversed",
|
||||||
|
"Transaction is already reversed.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
reverseTransactionBalances(account, txn);
|
||||||
|
|
||||||
|
txn.setReversed(true);
|
||||||
|
currentAccountTransactionRepository.save(txn);
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(transactionId)
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult reverseTransaction(final Long accountId, final Long transactionId,
|
||||||
|
final boolean isReversal, final JsonCommand command) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
|
||||||
|
final CurrentAccountTransaction original = currentAccountTransactionRepository.findById(transactionId)
|
||||||
|
.orElseThrow(() -> new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction not found: " + transactionId, transactionId));
|
||||||
|
|
||||||
|
if (!original.getCurrentAccount().getId().equals(accountId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction does not belong to this account.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (original.isReversed()) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.already.reversed",
|
||||||
|
"Transaction is already reversed.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
reverseTransactionBalances(account, original);
|
||||||
|
original.setReversed(true);
|
||||||
|
currentAccountTransactionRepository.save(original);
|
||||||
|
|
||||||
|
// Create a reversal entry
|
||||||
|
final CurrentAccountTransaction reversalTxn = CurrentAccountTransaction.reversal(
|
||||||
|
account, account.getOffice(), original.getAmount(), LocalDate.now(), transactionId);
|
||||||
|
reversalTxn.setRunningBalanceDerived(safeBalance(account.getAccountBalanceDerived()));
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(reversalTxn);
|
||||||
|
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(reversalTxn.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult adjustTransaction(final Long accountId, final Long transactionId,
|
||||||
|
final JsonCommand command) {
|
||||||
|
context.authenticatedUser();
|
||||||
|
|
||||||
|
final CurrentAccount account = findActiveAccount(accountId);
|
||||||
|
final Office office = account.getOffice();
|
||||||
|
|
||||||
|
final CurrentAccountTransaction original = currentAccountTransactionRepository.findById(transactionId)
|
||||||
|
.orElseThrow(() -> new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction not found: " + transactionId, transactionId));
|
||||||
|
|
||||||
|
if (!original.getCurrentAccount().getId().equals(accountId)) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.not.found",
|
||||||
|
"Transaction does not belong to this account.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (original.isReversed()) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.transaction.already.reversed",
|
||||||
|
"Transaction is already reversed.", transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
final BigDecimal newAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||||
|
validatePositiveAmount(newAmount, accountId, "adjust");
|
||||||
|
|
||||||
|
LocalDate newDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||||
|
if (newDate == null) newDate = original.getTransactionDate();
|
||||||
|
|
||||||
|
// Undo original
|
||||||
|
reverseTransactionBalances(account, original);
|
||||||
|
original.setReversed(true);
|
||||||
|
currentAccountTransactionRepository.save(original);
|
||||||
|
|
||||||
|
// Create adjusted transaction of the same type
|
||||||
|
final CurrentAccountTransaction adjusted;
|
||||||
|
if (original.getTransactionTypeEnum() == 1) {
|
||||||
|
adjusted = CurrentAccountTransaction.deposit(account, office, newAmount, newDate,
|
||||||
|
command.stringValueOfParameterNamed("accountNumber"));
|
||||||
|
} else {
|
||||||
|
adjusted = CurrentAccountTransaction.withdrawal(account, office, newAmount, newDate,
|
||||||
|
command.stringValueOfParameterNamed("accountNumber"));
|
||||||
|
}
|
||||||
|
adjusted.setOriginalTransactionId(transactionId);
|
||||||
|
adjusted.setRunningBalanceDerived(safeBalance(account.getAccountBalanceDerived()));
|
||||||
|
currentAccountTransactionRepository.saveAndFlush(adjusted);
|
||||||
|
|
||||||
|
// Apply new transaction to balance
|
||||||
|
applyTransactionToBalance(account, adjusted);
|
||||||
|
currentAccountRepository.save(account);
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder()
|
||||||
|
.withEntityId(adjusted.getId())
|
||||||
|
.withSavingsId(accountId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
private CurrentAccount findActiveAccount(final Long accountId) {
|
||||||
|
final CurrentAccount account = currentAccountRepository.findById(accountId)
|
||||||
|
.orElseThrow(() -> new CurrentAccountNotFoundException(accountId));
|
||||||
|
if (!Integer.valueOf(300).equals(account.getStatusEnum())) {
|
||||||
|
throw new GeneralPlatformDomainRuleException("error.msg.current.account.not.active",
|
||||||
|
"Current account is not in Active state.", accountId);
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validatePositiveAmount(final BigDecimal amount, final Long accountId, final String operation) {
|
||||||
|
if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
throw new GeneralPlatformDomainRuleException(
|
||||||
|
"error.msg.current.account." + operation + ".invalid.amount",
|
||||||
|
"Transaction amount must be greater than zero for " + operation + ".", accountId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal safeBalance(final BigDecimal value) {
|
||||||
|
return value != null ? value : BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reverseTransactionBalances(final CurrentAccount account, final CurrentAccountTransaction txn) {
|
||||||
|
final BigDecimal amount = txn.getAmount();
|
||||||
|
final Integer type = txn.getTransactionTypeEnum();
|
||||||
|
|
||||||
|
if (Integer.valueOf(1).equals(type)) {
|
||||||
|
// Was a deposit: reverse it
|
||||||
|
account.setAccountBalanceDerived(safeBalance(account.getAccountBalanceDerived()).subtract(amount));
|
||||||
|
account.setTotalDepositsDerived(safeBalance(account.getTotalDepositsDerived()).subtract(amount).max(BigDecimal.ZERO));
|
||||||
|
} else if (Integer.valueOf(2).equals(type)) {
|
||||||
|
// Was a withdrawal: reverse it
|
||||||
|
account.setAccountBalanceDerived(safeBalance(account.getAccountBalanceDerived()).add(amount));
|
||||||
|
account.setTotalWithdrawalsDerived(safeBalance(account.getTotalWithdrawalsDerived()).subtract(amount).max(BigDecimal.ZERO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyTransactionToBalance(final CurrentAccount account, final CurrentAccountTransaction txn) {
|
||||||
|
final BigDecimal amount = txn.getAmount();
|
||||||
|
final Integer type = txn.getTransactionTypeEnum();
|
||||||
|
|
||||||
|
if (Integer.valueOf(1).equals(type)) {
|
||||||
|
account.setAccountBalanceDerived(safeBalance(account.getAccountBalanceDerived()).add(amount));
|
||||||
|
account.setTotalDepositsDerived(safeBalance(account.getTotalDepositsDerived()).add(amount));
|
||||||
|
} else if (Integer.valueOf(2).equals(type)) {
|
||||||
|
account.setAccountBalanceDerived(safeBalance(account.getAccountBalanceDerived()).subtract(amount));
|
||||||
|
account.setTotalWithdrawalsDerived(safeBalance(account.getTotalWithdrawalsDerived()).add(amount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GL: cashEntryType=DEBIT/CREDIT for SAVINGS_REFERENCE; controlEntryType for SAVINGS_CONTROL
|
||||||
|
private void postTransactionGl(final CurrentAccount account, final CurrentAccountTransaction txn,
|
||||||
|
final JournalEntryType cashEntryType, final JournalEntryType controlEntryType, final String description) {
|
||||||
|
try {
|
||||||
|
final CurrentProduct product = currentProductRepository.findById(account.getProductId()).orElse(null);
|
||||||
|
if (product == null) return;
|
||||||
|
final Integer accountingType = product.getAccountingType();
|
||||||
|
if (accountingType == null || accountingType == 1) return; // NONE = 1
|
||||||
|
|
||||||
|
final GLAccount cashAccount = findGlAccount(account.getProductId(),
|
||||||
|
CashAccountsForSavings.SAVINGS_REFERENCE.getValue());
|
||||||
|
final GLAccount controlAccount = findGlAccount(account.getProductId(),
|
||||||
|
CashAccountsForSavings.SAVINGS_CONTROL.getValue());
|
||||||
|
|
||||||
|
if (cashAccount == null || controlAccount == null) {
|
||||||
|
log.warn("[GL] Missing GL account mapping for current account product id={}", account.getProductId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String ref = "CAT" + txn.getId();
|
||||||
|
postGlEntry(account, cashAccount, cashEntryType, txn.getAmount(), txn.getTransactionDate(), ref, description);
|
||||||
|
postGlEntry(account, controlAccount, controlEntryType, txn.getAmount(), txn.getTransactionDate(), ref, description);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[GL] Failed GL posting for CA transaction id={}: {}", txn.getId(), e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GLAccount findGlAccount(final Long productId, final int financialAccountType) {
|
||||||
|
final var mapping = productToGLAccountMappingRepository
|
||||||
|
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(
|
||||||
|
productId, PortfolioProductType.SAVING.getValue(), financialAccountType, null);
|
||||||
|
return mapping != null ? mapping.getGlAccount() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postGlEntry(final CurrentAccount account, final GLAccount glAccount,
|
||||||
|
final JournalEntryType entryType, final BigDecimal amount,
|
||||||
|
final LocalDate date, final String transactionRef, final String description) {
|
||||||
|
final JournalEntry entry = JournalEntry.createNew(
|
||||||
|
account.getOffice(), null, glAccount,
|
||||||
|
account.getCurrencyCode(), transactionRef,
|
||||||
|
false, date, entryType, amount,
|
||||||
|
description,
|
||||||
|
ENTITY_TYPE_SAVINGS, account.getId(),
|
||||||
|
null, null, null, null, null);
|
||||||
|
journalEntryRepository.save(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -33,6 +33,9 @@ public interface DepositAccountReadPlatformService {
|
|||||||
|
|
||||||
Page<DepositAccountData> retrieveAllPaged(DepositAccountType depositAccountType, PaginationParameters paginationParameters);
|
Page<DepositAccountData> retrieveAllPaged(DepositAccountType depositAccountType, PaginationParameters paginationParameters);
|
||||||
|
|
||||||
|
Page<DepositAccountData> retrieveAllPaged(DepositAccountType depositAccountType, PaginationParameters paginationParameters,
|
||||||
|
String accountNo, String clientName);
|
||||||
|
|
||||||
Collection<DepositAccountData> retrieveAllForLookup(DepositAccountType depositAccountType);
|
Collection<DepositAccountData> retrieveAllForLookup(DepositAccountType depositAccountType);
|
||||||
|
|
||||||
DepositAccountData retrieveOne(DepositAccountType depositAccountType, Long accountId);
|
DepositAccountData retrieveOne(DepositAccountType depositAccountType, Long accountId);
|
||||||
|
|||||||
+34
@@ -29,9 +29,11 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||||
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
|
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
@@ -182,6 +184,38 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
|||||||
depositAccountMapper);
|
depositAccountMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<DepositAccountData> retrieveAllPaged(final DepositAccountType depositAccountType,
|
||||||
|
final PaginationParameters paginationParameters, final String accountNo, final String clientName) {
|
||||||
|
|
||||||
|
this.paginationParametersDataValidator.validateParameterValues(paginationParameters, supportedOrderByValues,
|
||||||
|
depositAccountType.resourceName());
|
||||||
|
|
||||||
|
final DepositAccountMapper depositAccountMapper = this.getDepositAccountMapper(depositAccountType);
|
||||||
|
if (depositAccountMapper == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||||
|
sqlBuilder.append("select " + sqlGenerator.calcFoundRows() + " ");
|
||||||
|
sqlBuilder.append(depositAccountMapper.schema());
|
||||||
|
sqlBuilder.append(" where sa.deposit_type_enum = ? ");
|
||||||
|
|
||||||
|
final List<Object> params = new ArrayList<>();
|
||||||
|
params.add(depositAccountType.getValue());
|
||||||
|
if (StringUtils.isNotBlank(accountNo)) {
|
||||||
|
sqlBuilder.append(" and sa.account_no like ? ");
|
||||||
|
params.add("%" + accountNo + "%");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(clientName)) {
|
||||||
|
sqlBuilder.append(" and c.display_name like ? ");
|
||||||
|
params.add("%" + clientName + "%");
|
||||||
|
}
|
||||||
|
sqlBuilder.append(paginationParameters.paginationSql());
|
||||||
|
|
||||||
|
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlBuilder.toString(), params.toArray(), depositAccountMapper);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DepositAccountData> retrieveAllForLookup(final DepositAccountType depositAccountType) {
|
public Collection<DepositAccountData> retrieveAllForLookup(final DepositAccountType depositAccountType) {
|
||||||
|
|
||||||
|
|||||||
+13
-1
@@ -166,7 +166,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append(" join m_office o on o.id = c.office_id");
|
sqlBuilder.append(" join m_office o on o.id = c.office_id");
|
||||||
sqlBuilder.append(" where o.hierarchy like ?");
|
sqlBuilder.append(" where o.hierarchy like ?");
|
||||||
|
|
||||||
final Object[] objectArray = new Object[3];
|
final Object[] objectArray = new Object[10];
|
||||||
objectArray[0] = hierarchySearchString;
|
objectArray[0] = hierarchySearchString;
|
||||||
int arrayPos = 1;
|
int arrayPos = 1;
|
||||||
if (searchParameters != null) {
|
if (searchParameters != null) {
|
||||||
@@ -186,6 +186,18 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
sqlBuilder.append(" and c.office_id = ?");
|
sqlBuilder.append(" and c.office_id = ?");
|
||||||
objectArray[arrayPos++] = searchParameters.getOfficeId();
|
objectArray[arrayPos++] = searchParameters.getOfficeId();
|
||||||
}
|
}
|
||||||
|
if (StringUtils.isNotBlank(searchParameters.getAccountNo())) {
|
||||||
|
sqlBuilder.append(" and sa.account_no like ?");
|
||||||
|
objectArray[arrayPos++] = "%" + searchParameters.getAccountNo() + "%";
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(searchParameters.getName())) {
|
||||||
|
sqlBuilder.append(" and c.display_name like ?");
|
||||||
|
objectArray[arrayPos++] = "%" + searchParameters.getName() + "%";
|
||||||
|
}
|
||||||
|
if (searchParameters.getDepositType() != null) {
|
||||||
|
sqlBuilder.append(" and sa.deposit_type_enum = ?");
|
||||||
|
objectArray[arrayPos++] = searchParameters.getDepositType();
|
||||||
|
}
|
||||||
if (searchParameters.hasOrderBy()) {
|
if (searchParameters.hasOrderBy()) {
|
||||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||||
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
|
this.columnValidator.validateSqlInjection(sqlBuilder.toString(), searchParameters.getOrderBy());
|
||||||
|
|||||||
Reference in New Issue
Block a user