FINERACT-1977: 4-eye-principle, maker-checker permission
This commit is contained in:
+42
-54
@@ -52,7 +52,6 @@ import org.apache.fineract.batch.exception.BatchReferenceInvalidException;
|
|||||||
import org.apache.fineract.batch.exception.ErrorInfo;
|
import org.apache.fineract.batch.exception.ErrorInfo;
|
||||||
import org.apache.fineract.batch.service.ResolutionHelper.BatchRequestNode;
|
import org.apache.fineract.batch.service.ResolutionHelper.BatchRequestNode;
|
||||||
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
||||||
import org.apache.fineract.infrastructure.core.exception.AbstractIdempotentCommandException;
|
|
||||||
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||||
import org.apache.fineract.infrastructure.core.filters.BatchCallHandler;
|
import org.apache.fineract.infrastructure.core.filters.BatchCallHandler;
|
||||||
import org.apache.fineract.infrastructure.core.filters.BatchFilter;
|
import org.apache.fineract.infrastructure.core.filters.BatchFilter;
|
||||||
@@ -62,10 +61,8 @@ import org.springframework.dao.ConcurrencyFailureException;
|
|||||||
import org.springframework.dao.NonTransientDataAccessException;
|
import org.springframework.dao.NonTransientDataAccessException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.TransactionException;
|
import org.springframework.transaction.TransactionException;
|
||||||
import org.springframework.transaction.TransactionExecution;
|
import org.springframework.transaction.TransactionExecution;
|
||||||
import org.springframework.transaction.TransactionStatus;
|
|
||||||
import org.springframework.transaction.TransactionSystemException;
|
import org.springframework.transaction.TransactionSystemException;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
@@ -104,8 +101,7 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<BatchResponse> handleBatchRequestsWithoutEnclosingTransaction(final List<BatchRequest> requestList, UriInfo uriInfo) {
|
public List<BatchResponse> handleBatchRequestsWithoutEnclosingTransaction(final List<BatchRequest> requestList, UriInfo uriInfo) {
|
||||||
BatchRequestContextHolder.setEnclosingTransaction(Optional.empty());
|
return handleBatchRequests(requestList, uriInfo, false);
|
||||||
return handleBatchRequests(false, requestList, uriInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,7 +113,18 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<BatchResponse> handleBatchRequestsWithEnclosingTransaction(final List<BatchRequest> requestList, final UriInfo uriInfo) {
|
public List<BatchResponse> handleBatchRequestsWithEnclosingTransaction(final List<BatchRequest> requestList, final UriInfo uriInfo) {
|
||||||
return callInTransaction(Function.identity()::apply, () -> handleBatchRequests(true, requestList, uriInfo));
|
return handleBatchRequests(requestList, uriInfo, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BatchResponse> handleBatchRequests(final List<BatchRequest> requestList, final UriInfo uriInfo,
|
||||||
|
boolean enclosingTransaction) {
|
||||||
|
BatchRequestContextHolder.setIsEnclosingTransaction(enclosingTransaction);
|
||||||
|
try {
|
||||||
|
return enclosingTransaction ? callInTransaction(Function.identity()::apply, () -> handleRequestNodes(requestList, uriInfo))
|
||||||
|
: handleRequestNodes(requestList, uriInfo);
|
||||||
|
} finally {
|
||||||
|
BatchRequestContextHolder.resetIsEnclosingTransaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,18 +143,15 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
|
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
|
||||||
transactionConfigurator.accept(transactionTemplate);
|
transactionConfigurator.accept(transactionTemplate);
|
||||||
return transactionTemplate.execute(status -> {
|
return transactionTemplate.execute(status -> {
|
||||||
BatchRequestContextHolder.setEnclosingTransaction(Optional.of(status));
|
BatchRequestContextHolder.setEnclosingTransaction(status);
|
||||||
try {
|
try {
|
||||||
responseList.addAll(request.get());
|
responseList.addAll(request.get());
|
||||||
return responseList;
|
return responseList;
|
||||||
} catch (BatchExecutionException ex) {
|
} catch (BatchExecutionException ex) {
|
||||||
status.setRollbackOnly();
|
responseList.add(buildErrorResponse(ex.getCause(), ex.getRequest()));
|
||||||
return List.of(buildErrorResponse(ex.getCause(), ex.getRequest()));
|
return responseList;
|
||||||
} catch (RuntimeException ex) {
|
|
||||||
status.setRollbackOnly();
|
|
||||||
return buildErrorResponses(ex, responseList);
|
|
||||||
} finally {
|
} finally {
|
||||||
BatchRequestContextHolder.setEnclosingTransaction(Optional.empty());
|
BatchRequestContextHolder.resetTransaction();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (TransactionException | NonTransientDataAccessException ex) {
|
} catch (TransactionException | NonTransientDataAccessException ex) {
|
||||||
@@ -163,24 +167,17 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
* @param uriInfo
|
* @param uriInfo
|
||||||
* @return {@code List<BatchResponse>}
|
* @return {@code List<BatchResponse>}
|
||||||
*/
|
*/
|
||||||
private List<BatchResponse> handleBatchRequests(boolean enclosingTransaction, final List<BatchRequest> requestList,
|
private List<BatchResponse> handleRequestNodes(final List<BatchRequest> requestList, final UriInfo uriInfo) {
|
||||||
final UriInfo uriInfo) {
|
|
||||||
final List<BatchRequestNode> rootNodes;
|
final List<BatchRequestNode> rootNodes;
|
||||||
try {
|
try {
|
||||||
rootNodes = this.resolutionHelper.buildNodesTree(requestList);
|
rootNodes = this.resolutionHelper.buildNodesTree(requestList);
|
||||||
} catch (BatchReferenceInvalidException e) {
|
} catch (BatchReferenceInvalidException e) {
|
||||||
return List.of(buildErrorResponse(e));
|
return List.of(buildOrThrowErrorResponse(e, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
final ArrayList<BatchResponse> responseList = new ArrayList<>(requestList.size());
|
final ArrayList<BatchResponse> responseList = new ArrayList<>(requestList.size());
|
||||||
for (BatchRequestNode rootNode : rootNodes) {
|
for (BatchRequestNode rootNode : rootNodes) {
|
||||||
if (enclosingTransaction) {
|
this.callRequestRecursive(rootNode.getRequest(), rootNode, responseList, uriInfo);
|
||||||
this.callRequestRecursive(rootNode.getRequest(), rootNode, responseList, uriInfo, enclosingTransaction);
|
|
||||||
} else {
|
|
||||||
ArrayList<BatchResponse> localResponseList = new ArrayList<>();
|
|
||||||
this.callRequestRecursive(rootNode.getRequest(), rootNode, localResponseList, uriInfo, enclosingTransaction);
|
|
||||||
responseList.addAll(localResponseList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
responseList.sort(Comparator.comparing(BatchResponse::getRequestId));
|
responseList.sort(Comparator.comparing(BatchResponse::getRequestId));
|
||||||
return responseList;
|
return responseList;
|
||||||
@@ -197,18 +194,10 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
* the collected responses
|
* the collected responses
|
||||||
* @return {@code BatchResponse}
|
* @return {@code BatchResponse}
|
||||||
*/
|
*/
|
||||||
private void callRequestRecursive(BatchRequest request, BatchRequestNode requestNode, List<BatchResponse> responseList, UriInfo uriInfo,
|
private void callRequestRecursive(BatchRequest request, BatchRequestNode requestNode, List<BatchResponse> responseList,
|
||||||
boolean enclosingTransaction) {
|
UriInfo uriInfo) {
|
||||||
// run current node
|
// run current node
|
||||||
BatchResponse response;
|
BatchResponse response = executeRequest(request, uriInfo);
|
||||||
if (enclosingTransaction) {
|
|
||||||
response = executeRequest(request, uriInfo);
|
|
||||||
} else {
|
|
||||||
List<BatchResponse> transactionResponse = callInTransaction(
|
|
||||||
transactionTemplate -> transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
|
|
||||||
() -> List.of(executeRequest(request, uriInfo)));
|
|
||||||
response = transactionResponse.get(0);
|
|
||||||
}
|
|
||||||
responseList.add(response);
|
responseList.add(response);
|
||||||
if (response.getStatusCode() != null && response.getStatusCode() == SC_OK) {
|
if (response.getStatusCode() != null && response.getStatusCode() == SC_OK) {
|
||||||
// run child nodes
|
// run child nodes
|
||||||
@@ -217,13 +206,10 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
BatchRequest resolvedChildRequest;
|
BatchRequest resolvedChildRequest;
|
||||||
try {
|
try {
|
||||||
resolvedChildRequest = this.resolutionHelper.resolveRequest(childRequest, response);
|
resolvedChildRequest = this.resolutionHelper.resolveRequest(childRequest, response);
|
||||||
|
callRequestRecursive(resolvedChildRequest, childNode, responseList, uriInfo);
|
||||||
} catch (JsonPathException jpex) {
|
} catch (JsonPathException jpex) {
|
||||||
responseList.add(buildErrorResponse(jpex, childRequest));
|
responseList.add(buildOrThrowErrorResponse(jpex, childRequest));
|
||||||
return;
|
|
||||||
} catch (RuntimeException ex) {
|
|
||||||
throw new BatchExecutionException(childRequest, ex);
|
|
||||||
}
|
}
|
||||||
callRequestRecursive(resolvedChildRequest, childNode, responseList, uriInfo, enclosingTransaction);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
responseList.addAll(parentRequestFailedRecursive(request, requestNode, response, null));
|
responseList.addAll(parentRequestFailedRecursive(request, requestNode, response, null));
|
||||||
@@ -245,7 +231,7 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
log.debug("Batch request: method [{}], relative url [{}]", request.getMethod(), request.getRelativeUrl());
|
log.debug("Batch request: method [{}], relative url [{}]", request.getMethod(), request.getRelativeUrl());
|
||||||
Either<RuntimeException, BatchRequest> preprocessorResult = runPreprocessors(request);
|
Either<RuntimeException, BatchRequest> preprocessorResult = runPreprocessors(request);
|
||||||
if (preprocessorResult.isLeft()) {
|
if (preprocessorResult.isLeft()) {
|
||||||
throw new BatchExecutionException(request, preprocessorResult.getLeft());
|
return buildOrThrowErrorResponse(preprocessorResult.getLeft(), request);
|
||||||
} else {
|
} else {
|
||||||
request = preprocessorResult.get();
|
request = preprocessorResult.get();
|
||||||
}
|
}
|
||||||
@@ -253,19 +239,16 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
BatchRequestContextHolder.setRequestAttributes(new HashMap<>(Optional.ofNullable(request.getHeaders())
|
BatchRequestContextHolder.setRequestAttributes(new HashMap<>(Optional.ofNullable(request.getHeaders())
|
||||||
.map(list -> list.stream().collect(Collectors.toMap(Header::getName, Header::getValue)))
|
.map(list -> list.stream().collect(Collectors.toMap(Header::getName, Header::getValue)))
|
||||||
.orElse(Collections.emptyMap())));
|
.orElse(Collections.emptyMap())));
|
||||||
BatchCallHandler callHandler = new BatchCallHandler(this.batchFilters, commandStrategy::execute);
|
if (BatchRequestContextHolder.isEnclosingTransaction()) {
|
||||||
Optional<TransactionStatus> transaction = BatchRequestContextHolder.getEnclosingTransaction();
|
|
||||||
if (transaction.isPresent()) {
|
|
||||||
entityManager.flush();
|
entityManager.flush();
|
||||||
}
|
}
|
||||||
|
BatchCallHandler callHandler = new BatchCallHandler(this.batchFilters, commandStrategy::execute);
|
||||||
final BatchResponse rootResponse = callHandler.serviceCall(request, uriInfo);
|
final BatchResponse rootResponse = callHandler.serviceCall(request, uriInfo);
|
||||||
log.debug("Batch response: status code [{}], method [{}], relative url [{}]", rootResponse.getStatusCode(), request.getMethod(),
|
log.debug("Batch response: status code [{}], method [{}], relative url [{}]", rootResponse.getStatusCode(), request.getMethod(),
|
||||||
request.getRelativeUrl());
|
request.getRelativeUrl());
|
||||||
return rootResponse;
|
return rootResponse;
|
||||||
} catch (AbstractIdempotentCommandException idempotentException) {
|
|
||||||
return buildErrorResponse(idempotentException, request);
|
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw new BatchExecutionException(request, ex);
|
return buildOrThrowErrorResponse(ex, request);
|
||||||
} finally {
|
} finally {
|
||||||
BatchRequestContextHolder.resetRequestAttributes();
|
BatchRequestContextHolder.resetRequestAttributes();
|
||||||
}
|
}
|
||||||
@@ -313,11 +296,6 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
return responseList;
|
return responseList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private BatchResponse buildErrorResponse(@NotNull Throwable ex) {
|
|
||||||
return buildErrorResponse(ex, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the response when any exception raised
|
* Return the response when any exception raised
|
||||||
*
|
*
|
||||||
@@ -346,6 +324,15 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
return buildErrorResponse(requestId, statusCode, body, headers);
|
return buildErrorResponse(requestId, statusCode, body, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BatchResponse buildOrThrowErrorResponse(RuntimeException ex, BatchRequest request) {
|
||||||
|
BatchResponse response = buildErrorResponse(ex, request);
|
||||||
|
if (response.getStatusCode() != SC_OK && BatchRequestContextHolder.isEnclosingTransaction()) {
|
||||||
|
BatchRequestContextHolder.getTransaction().ifPresent(TransactionExecution::setRollbackOnly);
|
||||||
|
throw new BatchExecutionException(request, ex);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<BatchResponse> buildErrorResponses(Throwable ex, @NotNull List<BatchResponse> responseList) {
|
private List<BatchResponse> buildErrorResponses(Throwable ex, @NotNull List<BatchResponse> responseList) {
|
||||||
BatchResponse response = responseList.isEmpty() ? null
|
BatchResponse response = responseList.isEmpty() ? null
|
||||||
@@ -368,9 +355,10 @@ public class BatchApiServiceImpl implements BatchApiService {
|
|||||||
}
|
}
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
requestId = response.getRequestId();
|
requestId = response.getRequestId();
|
||||||
if (response.getStatusCode() == null || response.getStatusCode() != SC_OK) {
|
Integer responseCode = response.getStatusCode();
|
||||||
if (response.getStatusCode() != null) {
|
if (responseCode == null || responseCode != SC_OK) {
|
||||||
statusCode = response.getStatusCode();
|
if (responseCode != null) {
|
||||||
|
statusCode = responseCode;
|
||||||
}
|
}
|
||||||
body = "Transaction is being rolled back. First erroneous request: \n" + new Gson().toJson(response);
|
body = "Transaction is being rolled back. First erroneous request: \n" + new Gson().toJson(response);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,14 @@ public class CommandSource extends AbstractPersistableCustom {
|
|||||||
this.commandAsJson = json;
|
this.commandAsJson = json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AppUser getMaker() {
|
||||||
|
return maker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppUser getChecker() {
|
||||||
|
return checker;
|
||||||
|
}
|
||||||
|
|
||||||
public String getActionName() {
|
public String getActionName() {
|
||||||
return this.actionName;
|
return this.actionName;
|
||||||
}
|
}
|
||||||
|
|||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.commands.exception;
|
|
||||||
|
|
||||||
import org.apache.fineract.commands.domain.CommandSource;
|
|
||||||
|
|
||||||
public class RollbackTransactionAsCommandIsNotApprovedByCheckerException extends RuntimeException {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When maker-checker is configured globally and also for the current transaction.
|
|
||||||
*
|
|
||||||
* An initial save determines if there are any integrity rule or data problems.
|
|
||||||
*
|
|
||||||
* If there isn't... and the transaction is from a maker... then this roll back is issued and the
|
|
||||||
* commandSourceResult is used to write the audit entry.
|
|
||||||
*/
|
|
||||||
private final CommandSource commandSourceResult;
|
|
||||||
|
|
||||||
public RollbackTransactionAsCommandIsNotApprovedByCheckerException(final CommandSource commandSourceResult) {
|
|
||||||
this.commandSourceResult = commandSourceResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandSource getCommandSourceResult() {
|
|
||||||
return this.commandSourceResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.commands.exception;
|
||||||
|
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When maker-checker is configured globally and also for the current transaction. An initial save determines if there
|
||||||
|
* are any integrity rule or data problems. If there isn't... and the transaction is from a maker... then this roll back
|
||||||
|
* is issued and the commandSourceResult is used to write the audit entry.
|
||||||
|
*/
|
||||||
|
public class RollbackTransactionNotApprovedException extends RuntimeException {
|
||||||
|
|
||||||
|
private final CommandProcessingResult result;
|
||||||
|
|
||||||
|
public RollbackTransactionNotApprovedException(Long commandId, Long entityId) {
|
||||||
|
this.result = new CommandProcessingResultBuilder().withCommandId(commandId).withEntityId(entityId).setRollbackTransaction(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandProcessingResult getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -30,6 +30,11 @@ public class UnsupportedCommandException extends RuntimeException {
|
|||||||
this.unsupportedCommandName = unsupportedCommandName;
|
this.unsupportedCommandName = unsupportedCommandName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UnsupportedCommandException(final String unsupportedCommandName, String message) {
|
||||||
|
super(message);
|
||||||
|
this.unsupportedCommandName = unsupportedCommandName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUnsupportedCommandName() {
|
public String getUnsupportedCommandName() {
|
||||||
return this.unsupportedCommandName;
|
return this.unsupportedCommandName;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.commands.service;
|
package org.apache.fineract.commands.service;
|
||||||
|
|
||||||
import org.apache.fineract.commands.domain.CommandSource;
|
|
||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
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;
|
||||||
@@ -28,8 +27,6 @@ public interface CommandProcessingService {
|
|||||||
|
|
||||||
CommandProcessingResult executeCommand(CommandWrapper wrapper, JsonCommand command, boolean isApprovedByChecker);
|
CommandProcessingResult executeCommand(CommandWrapper wrapper, JsonCommand command, boolean isApprovedByChecker);
|
||||||
|
|
||||||
CommandProcessingResult logCommand(CommandSource commandSourceResult);
|
boolean validateRollbackCommand(CommandWrapper commandWrapper, AppUser user);
|
||||||
|
|
||||||
boolean validateCommand(CommandWrapper commandWrapper, AppUser user);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-9
@@ -26,7 +26,10 @@ import org.apache.fineract.commands.domain.CommandSource;
|
|||||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
import org.apache.fineract.commands.exception.CommandNotFoundException;
|
import org.apache.fineract.commands.exception.CommandNotFoundException;
|
||||||
|
import org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException;
|
||||||
|
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.exception.ErrorHandler;
|
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -95,19 +98,24 @@ public class CommandSourceService {
|
|||||||
idempotencyKey);
|
idempotencyKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
|
||||||
public CommandSource getInitialCommandSource(CommandWrapper wrapper, JsonCommand jsonCommand, AppUser maker, String idempotencyKey) {
|
public CommandSource getInitialCommandSource(CommandWrapper wrapper, JsonCommand jsonCommand, AppUser maker, String idempotencyKey) {
|
||||||
CommandSource commandSourceResult;
|
CommandSource commandSourceResult = CommandSource.fullEntryFrom(wrapper, jsonCommand, maker, idempotencyKey,
|
||||||
if (jsonCommand.commandId() != null) {
|
UNDER_PROCESSING.getValue());
|
||||||
commandSourceResult = commandSourceRepository.findById(jsonCommand.commandId())
|
|
||||||
.orElseThrow(() -> new CommandNotFoundException(jsonCommand.commandId()));
|
|
||||||
commandSourceResult.markAsChecked(maker);
|
|
||||||
} else {
|
|
||||||
commandSourceResult = CommandSource.fullEntryFrom(wrapper, jsonCommand, maker, idempotencyKey, UNDER_PROCESSING.getValue());
|
|
||||||
}
|
|
||||||
if (commandSourceResult.getCommandJson() == null) {
|
if (commandSourceResult.getCommandJson() == null) {
|
||||||
commandSourceResult.setCommandJson("{}");
|
commandSourceResult.setCommandJson("{}");
|
||||||
}
|
}
|
||||||
return commandSourceResult;
|
return commandSourceResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public CommandProcessingResult processCommand(NewCommandSourceHandler handler, JsonCommand command, CommandSource commandSource,
|
||||||
|
AppUser user, boolean isApprovedByChecker, boolean isMakerChecker) {
|
||||||
|
final CommandProcessingResult result = handler.processCommand(command);
|
||||||
|
boolean isRollback = !isApprovedByChecker && !user.isCheckerSuperUser() && (isMakerChecker || result.isRollbackTransaction());
|
||||||
|
if (isRollback) {
|
||||||
|
commandSource.markAsAwaitingApproval();
|
||||||
|
throw new RollbackTransactionNotApprovedException(commandSource.getId(), commandSource.getResourceId());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-9
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.commands.service;
|
package org.apache.fineract.commands.service;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
import java.util.Objects;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fineract.commands.domain.CommandSource;
|
import org.apache.fineract.commands.domain.CommandSource;
|
||||||
@@ -26,6 +27,8 @@ import org.apache.fineract.commands.domain.CommandSourceRepository;
|
|||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
import org.apache.fineract.commands.exception.CommandNotAwaitingApprovalException;
|
import org.apache.fineract.commands.exception.CommandNotAwaitingApprovalException;
|
||||||
import org.apache.fineract.commands.exception.CommandNotFoundException;
|
import org.apache.fineract.commands.exception.CommandNotFoundException;
|
||||||
|
import org.apache.fineract.commands.exception.UnsupportedCommandException;
|
||||||
|
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
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.infrastructure.core.serialization.FromJsonHelper;
|
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||||
@@ -45,10 +48,10 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
|||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
private final CommandProcessingService processAndLogCommandService;
|
private final CommandProcessingService processAndLogCommandService;
|
||||||
private final SchedulerJobRunnerReadService schedulerJobRunnerReadService;
|
private final SchedulerJobRunnerReadService schedulerJobRunnerReadService;
|
||||||
|
private final ConfigurationDomainService configurationService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult logCommandSource(final CommandWrapper wrapper) {
|
public CommandProcessingResult logCommandSource(final CommandWrapper wrapper) {
|
||||||
|
|
||||||
boolean isApprovedByChecker = false;
|
boolean isApprovedByChecker = false;
|
||||||
|
|
||||||
// check if is update of own account details
|
// check if is update of own account details
|
||||||
@@ -77,7 +80,6 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult approveEntry(final Long makerCheckerId) {
|
public CommandProcessingResult approveEntry(final Long makerCheckerId) {
|
||||||
|
|
||||||
final CommandSource commandSourceInput = validateMakerCheckerTransaction(makerCheckerId);
|
final CommandSource commandSourceInput = validateMakerCheckerTransaction(makerCheckerId);
|
||||||
validateIsUpdateAllowed();
|
validateIsUpdateAllowed();
|
||||||
|
|
||||||
@@ -111,16 +113,24 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CommandSource validateMakerCheckerTransaction(final Long makerCheckerId) {
|
private CommandSource validateMakerCheckerTransaction(final Long makerCheckerId) {
|
||||||
|
final CommandSource commandSource = this.commandSourceRepository.findById(makerCheckerId)
|
||||||
final CommandSource commandSourceInput = this.commandSourceRepository.findById(makerCheckerId)
|
|
||||||
.orElseThrow(() -> new CommandNotFoundException(makerCheckerId));
|
.orElseThrow(() -> new CommandNotFoundException(makerCheckerId));
|
||||||
if (!commandSourceInput.isMarkedAsAwaitingApproval()) {
|
if (!commandSource.isMarkedAsAwaitingApproval()) {
|
||||||
throw new CommandNotAwaitingApprovalException(makerCheckerId);
|
throw new CommandNotAwaitingApprovalException(makerCheckerId);
|
||||||
}
|
}
|
||||||
|
AppUser appUser = this.context.authenticatedUser();
|
||||||
this.context.authenticatedUser().validateHasCheckerPermissionTo(commandSourceInput.getPermissionCode());
|
String permissionCode = commandSource.getPermissionCode();
|
||||||
|
appUser.validateHasCheckerPermissionTo(permissionCode);
|
||||||
return commandSourceInput;
|
if (!configurationService.isSameMakerCheckerEnabled() && !appUser.isCheckerSuperUser()) {
|
||||||
|
AppUser maker = commandSource.getMaker();
|
||||||
|
if (maker == null) {
|
||||||
|
throw new UnsupportedCommandException(permissionCode, "Maker user is missing.");
|
||||||
|
}
|
||||||
|
if (Objects.equals(appUser.getId(), maker.getId())) {
|
||||||
|
throw new UnsupportedCommandException(permissionCode, "Can not be checked by the same user.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return commandSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateIsUpdateAllowed() {
|
private void validateIsUpdateAllowed() {
|
||||||
|
|||||||
+31
-57
@@ -35,14 +35,12 @@ import org.apache.fineract.batch.exception.ErrorInfo;
|
|||||||
import org.apache.fineract.commands.domain.CommandProcessingResultType;
|
import org.apache.fineract.commands.domain.CommandProcessingResultType;
|
||||||
import org.apache.fineract.commands.domain.CommandSource;
|
import org.apache.fineract.commands.domain.CommandSource;
|
||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
import org.apache.fineract.commands.exception.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
|
|
||||||
import org.apache.fineract.commands.exception.UnsupportedCommandException;
|
import org.apache.fineract.commands.exception.UnsupportedCommandException;
|
||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.commands.provider.CommandHandlerProvider;
|
import org.apache.fineract.commands.provider.CommandHandlerProvider;
|
||||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||||
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.infrastructure.core.data.CommandProcessingResultBuilder;
|
|
||||||
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
||||||
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||||
@@ -58,7 +56,6 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
|
|||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -76,9 +73,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
private final ConfigurationDomainService configurationDomainService;
|
private final ConfigurationDomainService configurationDomainService;
|
||||||
private final CommandHandlerProvider commandHandlerProvider;
|
private final CommandHandlerProvider commandHandlerProvider;
|
||||||
private final IdempotencyKeyResolver idempotencyKeyResolver;
|
private final IdempotencyKeyResolver idempotencyKeyResolver;
|
||||||
private final IdempotencyKeyGenerator idempotencyKeyGenerator;
|
|
||||||
private final CommandSourceService commandSourceService;
|
private final CommandSourceService commandSourceService;
|
||||||
private final ErrorHandler errorHandler;
|
|
||||||
|
|
||||||
private final FineractRequestContextHolder fineractRequestContextHolder;
|
private final FineractRequestContextHolder fineractRequestContextHolder;
|
||||||
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
|
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
|
||||||
@@ -92,73 +87,68 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
|
|
||||||
Long commandId = (Long) fineractRequestContextHolder.getAttribute(COMMAND_SOURCE_ID, null);
|
Long commandId = (Long) fineractRequestContextHolder.getAttribute(COMMAND_SOURCE_ID, null);
|
||||||
boolean isRetry = commandId != null;
|
boolean isRetry = commandId != null;
|
||||||
|
boolean isEnclosingTransaction = BatchRequestContextHolder.isEnclosingTransaction();
|
||||||
|
|
||||||
CommandSource commandSource = null;
|
CommandSource commandSource = null;
|
||||||
String idempotencyKey;
|
String idempotencyKey;
|
||||||
if (isRetry) {
|
if (isRetry) {
|
||||||
commandSource = commandSourceService.getCommandSource(commandId);
|
commandSource = commandSourceService.getCommandSource(commandId);
|
||||||
idempotencyKey = commandSource.getIdempotencyKey();
|
idempotencyKey = commandSource.getIdempotencyKey();
|
||||||
|
} else if ((commandId = command.commandId()) != null) { // action on the command itself
|
||||||
|
commandSource = commandSourceService.getCommandSource(commandId);
|
||||||
|
idempotencyKey = commandSource.getIdempotencyKey();
|
||||||
} else {
|
} else {
|
||||||
idempotencyKey = idempotencyKeyResolver.resolve(wrapper);
|
idempotencyKey = idempotencyKeyResolver.resolve(wrapper);
|
||||||
}
|
}
|
||||||
exceptionWhenTheRequestAlreadyProcessed(wrapper, idempotencyKey, isRetry);
|
exceptionWhenTheRequestAlreadyProcessed(wrapper, idempotencyKey, isRetry);
|
||||||
|
|
||||||
boolean sameTransaction = BatchRequestContextHolder.getEnclosingTransaction().isPresent();
|
AppUser user = context.authenticatedUser(wrapper);
|
||||||
if (commandSource == null) {
|
if (commandSource == null) {
|
||||||
AppUser user = context.authenticatedUser(wrapper);
|
if (isEnclosingTransaction) {
|
||||||
if (sameTransaction) {
|
|
||||||
commandSource = commandSourceService.getInitialCommandSource(wrapper, command, user, idempotencyKey);
|
commandSource = commandSourceService.getInitialCommandSource(wrapper, command, user, idempotencyKey);
|
||||||
} else {
|
} else {
|
||||||
commandSource = commandSourceService.saveInitialNewTransaction(wrapper, command, user, idempotencyKey);
|
commandSource = commandSourceService.saveInitialNewTransaction(wrapper, command, user, idempotencyKey);
|
||||||
storeCommandIdInContext(commandSource); // Store command id as a request attribute
|
commandId = commandSource.getId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (commandId != null) {
|
||||||
|
storeCommandIdInContext(commandSource); // Store command id as a request attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isMakerChecker = configurationDomainService.isMakerCheckerEnabledForTask(wrapper.taskPermissionName());
|
||||||
|
if (isApprovedByChecker || (isMakerChecker && user.isCheckerSuperUser())) {
|
||||||
|
commandSource.markAsChecked(user);
|
||||||
|
}
|
||||||
setIdempotencyKeyStoreFlag(true);
|
setIdempotencyKeyStoreFlag(true);
|
||||||
|
|
||||||
final CommandProcessingResult result;
|
final CommandProcessingResult result;
|
||||||
try {
|
try {
|
||||||
result = findCommandHandler(wrapper).processCommand(command);
|
result = commandSourceService.processCommand(findCommandHandler(wrapper), command, commandSource, user, isApprovedByChecker,
|
||||||
|
isMakerChecker);
|
||||||
} catch (Throwable t) { // NOSONAR
|
} catch (Throwable t) { // NOSONAR
|
||||||
RuntimeException mappable = ErrorHandler.getMappable(t);
|
RuntimeException mappable = ErrorHandler.getMappable(t);
|
||||||
ErrorInfo errorInfo = commandSourceService.generateErrorInfo(mappable);
|
ErrorInfo errorInfo = commandSourceService.generateErrorInfo(mappable);
|
||||||
commandSource.setResultStatusCode(errorInfo.getStatusCode());
|
Integer statusCode = errorInfo.getStatusCode();
|
||||||
|
commandSource.setResultStatusCode(statusCode);
|
||||||
commandSource.setResult(errorInfo.getMessage());
|
commandSource.setResult(errorInfo.getMessage());
|
||||||
commandSource.setStatus(ERROR);
|
if (statusCode != SC_OK) {
|
||||||
if (!sameTransaction) { // TODO: temporary solution
|
commandSource.setStatus(ERROR);
|
||||||
|
}
|
||||||
|
if (!isEnclosingTransaction) { // TODO: temporary solution
|
||||||
commandSource = commandSourceService.saveResultNewTransaction(commandSource);
|
commandSource = commandSourceService.saveResultNewTransaction(commandSource);
|
||||||
}
|
}
|
||||||
publishHookErrorEvent(wrapper, command, errorInfo); // TODO must be performed in a new transaction
|
// must not throw any exception; must persist in new transaction as the current transaction was already
|
||||||
|
// marked as rollback
|
||||||
|
publishHookErrorEvent(wrapper, command, errorInfo);
|
||||||
throw mappable;
|
throw mappable;
|
||||||
}
|
}
|
||||||
|
|
||||||
commandSource.updateForAudit(result);
|
|
||||||
commandSource.setResultStatusCode(SC_OK);
|
commandSource.setResultStatusCode(SC_OK);
|
||||||
|
commandSource.updateForAudit(result);
|
||||||
commandSource.setResult(toApiJsonSerializer.serializeResult(result));
|
commandSource.setResult(toApiJsonSerializer.serializeResult(result));
|
||||||
commandSource.setStatus(PROCESSED);
|
commandSource.setStatus(PROCESSED);
|
||||||
|
|
||||||
boolean isRollback = !isApprovedByChecker && (result.isRollbackTransaction()
|
|
||||||
|| configurationDomainService.isMakerCheckerEnabledForTask(wrapper.taskPermissionName()));
|
|
||||||
// TODO: this should be removed, can not override audit information (and maker-checker does not work)
|
|
||||||
if (!isRollback && result.hasChanges()) {
|
|
||||||
commandSource.setCommandJson(toApiJsonSerializer.serializeResult(result.getChanges()));
|
|
||||||
}
|
|
||||||
|
|
||||||
commandSource = commandSourceService.saveResultSameTransaction(commandSource);
|
commandSource = commandSourceService.saveResultSameTransaction(commandSource);
|
||||||
if (sameTransaction) {
|
storeCommandIdInContext(commandSource); // Store command id as a request attribute
|
||||||
storeCommandIdInContext(commandSource); // Store command id as a request attribute
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRollback) {
|
|
||||||
/*
|
|
||||||
* JournalEntry will generate a new transactionId every time. Updating the transactionId with old
|
|
||||||
* transactionId, because as there are no entries are created with new transactionId, will throw an error
|
|
||||||
* when checker approves the transaction
|
|
||||||
*/
|
|
||||||
commandSource.setTransactionId(command.getTransactionId());
|
|
||||||
// TODO: this should be removed together with lines 147-149
|
|
||||||
commandSource.setCommandJson(command.json()); // Set back CommandSource json data
|
|
||||||
throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(commandSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.setRollbackTransaction(null);
|
result.setRollbackTransaction(null);
|
||||||
publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, result); // TODO must be performed in a
|
publishHookEvent(wrapper.entityName(), wrapper.actionName(), command, result); // TODO must be performed in a
|
||||||
@@ -201,24 +191,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
fineractRequestContextHolder.setAttribute(IDEMPOTENCY_KEY_STORE_FLAG, flag);
|
fineractRequestContextHolder.setAttribute(IDEMPOTENCY_KEY_STORE_FLAG, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public CommandProcessingResult logCommand(CommandSource commandSource) {
|
|
||||||
commandSource.markAsAwaitingApproval();
|
|
||||||
if (commandSource.getIdempotencyKey() == null) {
|
|
||||||
commandSource.setIdempotencyKey(idempotencyKeyGenerator.create());
|
|
||||||
}
|
|
||||||
commandSource = commandSourceService.saveResultSameTransaction(commandSource);
|
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder().withCommandId(commandSource.getId()).withEntityId(commandSource.getResourceId())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public CommandProcessingResult fallbackExecuteCommand(Exception e) {
|
public CommandProcessingResult fallbackExecuteCommand(Exception e) {
|
||||||
if (e instanceof RollbackTransactionAsCommandIsNotApprovedByCheckerException ex) {
|
|
||||||
return logCommand(ex.getCommandSourceResult());
|
|
||||||
}
|
|
||||||
throw ErrorHandler.getMappable(e);
|
throw ErrorHandler.getMappable(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,10 +255,10 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validateCommand(final CommandWrapper commandWrapper, final AppUser user) {
|
public boolean validateRollbackCommand(final CommandWrapper commandWrapper, final AppUser user) {
|
||||||
boolean rollbackTransaction = configurationDomainService.isMakerCheckerEnabledForTask(commandWrapper.taskPermissionName());
|
|
||||||
user.validateHasPermissionTo(commandWrapper.getTaskPermissionName());
|
user.validateHasPermissionTo(commandWrapper.getTaskPermissionName());
|
||||||
return rollbackTransaction;
|
boolean isMakerChecker = configurationDomainService.isMakerCheckerEnabledForTask(commandWrapper.taskPermissionName());
|
||||||
|
return isMakerChecker && !user.isCheckerSuperUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
|
private void publishHookEvent(final String entityName, final String actionName, JsonCommand command, final Object result) {
|
||||||
|
|||||||
+2
@@ -25,6 +25,8 @@ public interface ConfigurationDomainService {
|
|||||||
|
|
||||||
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
|
boolean isMakerCheckerEnabledForTask(String taskPermissionCode);
|
||||||
|
|
||||||
|
boolean isSameMakerCheckerEnabled();
|
||||||
|
|
||||||
boolean isAmazonS3Enabled();
|
boolean isAmazonS3Enabled();
|
||||||
|
|
||||||
boolean isRescheduleFutureRepaymentsEnabled();
|
boolean isRescheduleFutureRepaymentsEnabled();
|
||||||
|
|||||||
+65
-18
@@ -27,15 +27,16 @@ public final class BatchRequestContextHolder {
|
|||||||
|
|
||||||
private BatchRequestContextHolder() {}
|
private BatchRequestContextHolder() {}
|
||||||
|
|
||||||
private static final ThreadLocal<Map<String, Object>> batchAttributes = new NamedThreadLocal<>("BatchAttributesForProcessing");
|
private static final ThreadLocal<Map<String, Object>> batchAttributes = new NamedThreadLocal<>("batchAttributes");
|
||||||
|
|
||||||
private static final ThreadLocal<Optional<TransactionStatus>> enclosingTransaction = new NamedThreadLocal<>("EnclosingTransaction") {
|
private static final ThreadLocal<Optional<TransactionStatus>> batchTransaction = new NamedThreadLocal<>("batchTransaction") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Optional<TransactionStatus> initialValue() {
|
protected Optional<TransactionStatus> initialValue() {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private static final ThreadLocal<Boolean> isEnclosingTransaction = new NamedThreadLocal<>("isEnclosingTransaction");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the batch attributes are set
|
* True if the batch attributes are set
|
||||||
@@ -47,12 +48,12 @@ public final class BatchRequestContextHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the batch attributes are set and the enclosing transaction is set to true
|
* Returns the batch attributes for the current thread.
|
||||||
*
|
*
|
||||||
* @return
|
* @return the batch attributes for the current thread, cna be null
|
||||||
*/
|
*/
|
||||||
public static Optional<TransactionStatus> getEnclosingTransaction() {
|
public static Map<String, Object> getRequestAttributes() {
|
||||||
return enclosingTransaction.get();
|
return batchAttributes.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,15 +66,6 @@ public final class BatchRequestContextHolder {
|
|||||||
batchAttributes.set(requestAttributes);
|
batchAttributes.set(requestAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the batch attributes for the current thread.
|
|
||||||
*
|
|
||||||
* @return the batch attributes for the current thread, cna be null
|
|
||||||
*/
|
|
||||||
public static Map<String, Object> getRequestAttributes() {
|
|
||||||
return batchAttributes.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the batch attributes for the current thread.
|
* Reset the batch attributes for the current thread.
|
||||||
*/
|
*/
|
||||||
@@ -82,11 +74,66 @@ public final class BatchRequestContextHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the enclosing transaction flag for the current thread.
|
* True if the batch attributes are set and the enclosing transaction is set to true
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isEnclosingTransaction() {
|
||||||
|
return Boolean.TRUE.equals(isEnclosingTransaction.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the isEnclosingTransaction flag for the current thread.
|
||||||
|
*
|
||||||
|
* @param isEnclosingTransaction
|
||||||
|
*/
|
||||||
|
public static void setIsEnclosingTransaction(boolean isEnclosingTransaction) {
|
||||||
|
BatchRequestContextHolder.isEnclosingTransaction.set(isEnclosingTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetIsEnclosingTransaction() {
|
||||||
|
isEnclosingTransaction.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the transaction
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Optional<TransactionStatus> getTransaction() {
|
||||||
|
return batchTransaction.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the enclosing transaction
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Optional<TransactionStatus> getEnclosingTransaction() {
|
||||||
|
return isEnclosingTransaction() ? getTransaction() : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the transaction for the current thread.
|
||||||
*
|
*
|
||||||
* @param enclosingTransaction
|
* @param enclosingTransaction
|
||||||
*/
|
*/
|
||||||
public static void setEnclosingTransaction(Optional<TransactionStatus> enclosingTransaction) {
|
public static void setTransaction(TransactionStatus enclosingTransaction) {
|
||||||
BatchRequestContextHolder.enclosingTransaction.set(enclosingTransaction);
|
batchTransaction.set(Optional.ofNullable(enclosingTransaction));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the enclosing transaction for the current thread.
|
||||||
|
*
|
||||||
|
* @param enclosingTransaction
|
||||||
|
*/
|
||||||
|
public static void setEnclosingTransaction(TransactionStatus enclosingTransaction) {
|
||||||
|
if (isEnclosingTransaction()) {
|
||||||
|
setTransaction(enclosingTransaction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetTransaction() {
|
||||||
|
batchTransaction.set(Optional.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* 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.infrastructure.core.exceptionmapper;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import jakarta.ws.rs.ext.ExceptionMapper;
|
||||||
|
import jakarta.ws.rs.ext.Provider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link ExceptionMapper} to map {@link PlatformApiDataValidationException} thrown by platform into a HTTP API
|
||||||
|
* friendly format.
|
||||||
|
*
|
||||||
|
* The {@link PlatformApiDataValidationException} is typically thrown in data validation of the parameters passed in
|
||||||
|
* with an api request.
|
||||||
|
*/
|
||||||
|
@Provider
|
||||||
|
@Component
|
||||||
|
@Scope("singleton")
|
||||||
|
@Slf4j
|
||||||
|
public class RollbackTransactionNotApprovedExceptionMapper
|
||||||
|
implements FineractExceptionMapper, ExceptionMapper<RollbackTransactionNotApprovedException> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(final RollbackTransactionNotApprovedException exception) {
|
||||||
|
log.warn("Exception: {}", exception.getClass().getName());
|
||||||
|
return Response.ok().entity(new Gson().toJson(exception.getResult())).type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int errorCode() {
|
||||||
|
return 2000;
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -47,8 +47,12 @@ public class UnsupportedCommandExceptionMapper implements ExceptionMapper<Unsupp
|
|||||||
final List<ApiParameterError> errors = new ArrayList<>();
|
final List<ApiParameterError> errors = new ArrayList<>();
|
||||||
|
|
||||||
final StringBuilder validationErrorCode = new StringBuilder("error.msg.command.unsupported");
|
final StringBuilder validationErrorCode = new StringBuilder("error.msg.command.unsupported");
|
||||||
|
String message = exception.getMessage();
|
||||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The command ").append(exception.getUnsupportedCommandName())
|
final StringBuilder defaultEnglishMessage = new StringBuilder("The command ").append(exception.getUnsupportedCommandName())
|
||||||
.append(" is not supported.");
|
.append(" is not supported.");
|
||||||
|
if (message != null) {
|
||||||
|
defaultEnglishMessage.append(" ").append(message);
|
||||||
|
}
|
||||||
log.warn("Exception: {}, Message: {}", exception.getClass().getName(), defaultEnglishMessage);
|
log.warn("Exception: {}, Message: {}", exception.getClass().getName(), defaultEnglishMessage);
|
||||||
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
|
||||||
exception.getUnsupportedCommandName(), exception.getUnsupportedCommandName());
|
exception.getUnsupportedCommandName(), exception.getUnsupportedCommandName());
|
||||||
|
|||||||
+1
-4
@@ -25,7 +25,6 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||||
import org.apache.fineract.commands.service.CommandSourceService;
|
import org.apache.fineract.commands.service.CommandSourceService;
|
||||||
import org.apache.fineract.commands.service.SynchronousCommandProcessingService;
|
import org.apache.fineract.commands.service.SynchronousCommandProcessingService;
|
||||||
import org.apache.fineract.infrastructure.core.domain.BatchRequestContextHolder;
|
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -39,11 +38,9 @@ public class IdempotencyStoreHelper {
|
|||||||
|
|
||||||
public void storeCommandResult(Integer response, String body, Long commandId) {
|
public void storeCommandResult(Integer response, String body, Long commandId) {
|
||||||
commandSourceRepository.findById(commandId).ifPresent(commandSource -> {
|
commandSourceRepository.findById(commandId).ifPresent(commandSource -> {
|
||||||
boolean sameTransaction = BatchRequestContextHolder.getEnclosingTransaction().isPresent();
|
|
||||||
commandSource.setResultStatusCode(response);
|
commandSource.setResultStatusCode(response);
|
||||||
commandSource.setResult(body);
|
commandSource.setResult(body);
|
||||||
commandSource = sameTransaction ? commandSourceService.saveResultSameTransaction(commandSource)
|
commandSourceService.saveResultSameTransaction(commandSource);
|
||||||
: commandSourceService.saveResultNewTransaction(commandSource);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -657,6 +657,10 @@ public class AppUser extends AbstractPersistableCustom implements PlatformUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCheckerSuperUser() {
|
||||||
|
return hasPermissionTo("CHECKER_SUPER_USER");
|
||||||
|
}
|
||||||
|
|
||||||
public void validateHasDatatableReadPermission(final String datatable) {
|
public void validateHasDatatableReadPermission(final String datatable) {
|
||||||
if (hasNotPermissionForDatatable(datatable, "READ")) {
|
if (hasNotPermissionForDatatable(datatable, "READ")) {
|
||||||
throw new NoAuthorizationException("Not authorised to read datatable: " + datatable);
|
throw new NoAuthorizationException("Not authorised to read datatable: " + datatable);
|
||||||
|
|||||||
+6
@@ -34,6 +34,7 @@ import org.apache.fineract.infrastructure.core.domain.ActionContext;
|
|||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.exceptionmapper.IdempotentCommandExceptionMapper;
|
import org.apache.fineract.infrastructure.core.exceptionmapper.IdempotentCommandExceptionMapper;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -48,6 +49,11 @@ public class IdempotencyCommandProcessFailedExceptionTest {
|
|||||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInconsistentStatus() {
|
public void testInconsistentStatus() {
|
||||||
IdempotentCommandExceptionMapper mapper = new IdempotentCommandExceptionMapper();
|
IdempotentCommandExceptionMapper mapper = new IdempotentCommandExceptionMapper();
|
||||||
|
|||||||
+6
@@ -54,6 +54,7 @@ import org.apache.fineract.investor.service.AccountingService;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -90,6 +91,11 @@ public class LoanAccountOwnerTransferBusinessStepTest {
|
|||||||
externalAssetOwnerTransferLoanMappingRepository, accountingService, businessEventNotifierService);
|
externalAssetOwnerTransferLoanMappingRepository, accountingService, businessEventNotifierService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenLoanNoTransfer() {
|
public void givenLoanNoTransfer() {
|
||||||
// given
|
// given
|
||||||
|
|||||||
+4
-1
@@ -38,6 +38,7 @@ import org.apache.fineract.infrastructure.bulkimport.importhandler.helper.EnumOp
|
|||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||||
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
|
import org.apache.fineract.infrastructure.core.serialization.GoogleGsonSerializerHelper;
|
||||||
|
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||||
import org.apache.fineract.portfolio.savings.data.SavingsActivation;
|
import org.apache.fineract.portfolio.savings.data.SavingsActivation;
|
||||||
@@ -147,7 +148,9 @@ public class SavingsImportHandler implements ImportHandler {
|
|||||||
Long interestPostingPeriodTypeId = null;
|
Long interestPostingPeriodTypeId = null;
|
||||||
EnumOptionData interestPostingPeriodTypeEnum = null;
|
EnumOptionData interestPostingPeriodTypeEnum = null;
|
||||||
if (interestPostingPeriodType != null) {
|
if (interestPostingPeriodType != null) {
|
||||||
if (interestPostingPeriodType.equalsIgnoreCase(MONTHLY)) {
|
if (interestPostingPeriodType.equalsIgnoreCase(DAILY)) {
|
||||||
|
interestPostingPeriodTypeId = SavingsPostingInterestPeriodType.DAILY.getValue().longValue();
|
||||||
|
} else if (interestPostingPeriodType.equalsIgnoreCase(MONTHLY)) {
|
||||||
interestPostingPeriodTypeId = 4L;
|
interestPostingPeriodTypeId = 4L;
|
||||||
} else if (interestPostingPeriodType.equalsIgnoreCase(QUARTERLY)) {
|
} else if (interestPostingPeriodType.equalsIgnoreCase(QUARTERLY)) {
|
||||||
interestPostingPeriodTypeId = 5L;
|
interestPostingPeriodTypeId = 5L;
|
||||||
|
|||||||
+8
-6
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.infrastructure.configuration.domain;
|
package org.apache.fineract.infrastructure.configuration.domain;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -74,6 +75,11 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSameMakerCheckerEnabled() {
|
||||||
|
return getGlobalConfigurationPropertyData("enable-same-maker-checker").isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAmazonS3Enabled() {
|
public boolean isAmazonS3Enabled() {
|
||||||
return getGlobalConfigurationPropertyData("amazon-S3").isEnabled();
|
return getGlobalConfigurationPropertyData("amazon-S3").isEnabled();
|
||||||
@@ -379,18 +385,14 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
|||||||
return property.getValue();
|
return property.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private GlobalConfigurationPropertyData getGlobalConfigurationPropertyData(final String propertyName) {
|
private GlobalConfigurationPropertyData getGlobalConfigurationPropertyData(final String propertyName) {
|
||||||
return globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName).toData();
|
return globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName).toData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSubRatesEnabled() {
|
public boolean isSubRatesEnabled() {
|
||||||
GlobalConfigurationPropertyData configuration = getGlobalConfigurationPropertyData("sub-rates");
|
return getGlobalConfigurationPropertyData("sub-rates").isEnabled();
|
||||||
if (configuration == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return configuration.isEnabled();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -294,7 +294,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
|
|||||||
validateParentGroupRulesBeforeClientActivation(newClient);
|
validateParentGroupRulesBeforeClientActivation(newClient);
|
||||||
runEntityDatatableCheck(newClient.getId(), newClient.getLegalForm());
|
runEntityDatatableCheck(newClient.getId(), newClient.getLegalForm());
|
||||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build();
|
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build();
|
||||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
rollbackTransaction = this.commandProcessingService.validateRollbackCommand(commandWrapper, currentUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clientRepository.saveAndFlush(newClient);
|
this.clientRepository.saveAndFlush(newClient);
|
||||||
|
|||||||
+3
-3
@@ -172,16 +172,16 @@ public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
|
|||||||
|
|
||||||
if (newGroup.isCenter()) {
|
if (newGroup.isCenter()) {
|
||||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateCenter(null).build();
|
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateCenter(null).build();
|
||||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
rollbackTransaction = this.commandProcessingService.validateRollbackCommand(commandWrapper, currentUser);
|
||||||
} else {
|
} else {
|
||||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateGroup(null).build();
|
final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateGroup(null).build();
|
||||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
rollbackTransaction = this.commandProcessingService.validateRollbackCommand(commandWrapper, currentUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newGroup.isCenter() && newGroup.hasActiveClients()) {
|
if (!newGroup.isCenter() && newGroup.hasActiveClients()) {
|
||||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().associateClientsToGroup(newGroup.getId()).build();
|
final CommandWrapper commandWrapper = new CommandWrapperBuilder().associateClientsToGroup(newGroup.getId()).build();
|
||||||
rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser);
|
rollbackTransaction = this.commandProcessingService.validateRollbackCommand(commandWrapper, currentUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pre-save to generate id for use in group hierarchy
|
// pre-save to generate id for use in group hierarchy
|
||||||
|
|||||||
+2
-1
@@ -656,7 +656,8 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
|||||||
public CommandProcessingResult createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) {
|
public CommandProcessingResult createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) {
|
||||||
|
|
||||||
final CommandWrapper commandWrapper = new CommandWrapperBuilder().savingsAccountActivation(null).build();
|
final CommandWrapper commandWrapper = new CommandWrapperBuilder().savingsAccountActivation(null).build();
|
||||||
boolean rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, savingsAccountDataDTO.getAppliedBy());
|
boolean rollbackTransaction = this.commandProcessingService.validateRollbackCommand(commandWrapper,
|
||||||
|
savingsAccountDataDTO.getAppliedBy());
|
||||||
|
|
||||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),
|
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),
|
||||||
savingsAccountDataDTO.getGroup(), savingsAccountDataDTO.getSavingsProduct(), savingsAccountDataDTO.getApplicationDate(),
|
savingsAccountDataDTO.getGroup(), savingsAccountDataDTO.getSavingsProduct(), savingsAccountDataDTO.getApplicationDate(),
|
||||||
|
|||||||
@@ -150,4 +150,5 @@
|
|||||||
<include file="parts/0128_savings_audit.xml" relativeToChangelogFile="true" />
|
<include file="parts/0128_savings_audit.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0129_transaction_summary_with_asset_owner_report_overpaid_amount.xml" relativeToChangelogFile="true" />
|
<include file="parts/0129_transaction_summary_with_asset_owner_report_overpaid_amount.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0130_add_create_delinquency_action_permission.xml" relativeToChangelogFile="true" />
|
<include file="parts/0130_add_create_delinquency_action_permission.xml" relativeToChangelogFile="true" />
|
||||||
|
<include file="parts/0131_add_configuration_maker_checker.xml" relativeToChangelogFile="true" />
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||||
|
<changeSet author="fineract" id="1">
|
||||||
|
<insert tableName="c_configuration">
|
||||||
|
<column name="name" value="enable-same-maker-checker"/>
|
||||||
|
<column name="value"/>
|
||||||
|
<column name="date_value"/>
|
||||||
|
<column name="string_value"/>
|
||||||
|
<column name="enabled" valueBoolean="false"/>
|
||||||
|
<column name="is_trap_door" valueBoolean="false"/>
|
||||||
|
<column name="description"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+15
-3
@@ -66,7 +66,11 @@ public class LoanItemListenerStepDefinitions implements En {
|
|||||||
});
|
});
|
||||||
|
|
||||||
When("LoanItemListener.onReadError method executed", () -> {
|
When("LoanItemListener.onReadError method executed", () -> {
|
||||||
loanItemListener.onReadError(exception);
|
try {
|
||||||
|
loanItemListener.onReadError(exception);
|
||||||
|
} finally {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("LoanItemListener.onReadError result should match", () -> {
|
Then("LoanItemListener.onReadError result should match", () -> {
|
||||||
@@ -87,7 +91,11 @@ public class LoanItemListenerStepDefinitions implements En {
|
|||||||
});
|
});
|
||||||
|
|
||||||
When("LoanItemListener.onProcessError method executed", () -> {
|
When("LoanItemListener.onProcessError method executed", () -> {
|
||||||
loanItemListener.onProcessError(loan, exception);
|
try {
|
||||||
|
loanItemListener.onProcessError(loan, exception);
|
||||||
|
} finally {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("LoanItemListener.onProcessError result should match", () -> {
|
Then("LoanItemListener.onProcessError result should match", () -> {
|
||||||
@@ -108,7 +116,11 @@ public class LoanItemListenerStepDefinitions implements En {
|
|||||||
});
|
});
|
||||||
|
|
||||||
When("LoanItemListener.onWriteError method executed", () -> {
|
When("LoanItemListener.onWriteError method executed", () -> {
|
||||||
loanItemListener.onWriteError(exception, new Chunk<>(List.of(loan)));
|
try {
|
||||||
|
loanItemListener.onWriteError(exception, new Chunk<>(List.of(loan)));
|
||||||
|
} finally {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("LoanItemListener.onWriteError result should match", () -> {
|
Then("LoanItemListener.onWriteError result should match", () -> {
|
||||||
|
|||||||
+6
@@ -42,6 +42,7 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualPlatformService;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -66,6 +67,11 @@ public class AddPeriodicAccrualEntriesBusinessStepTest {
|
|||||||
underTest = new AddPeriodicAccrualEntriesBusinessStep(loanAccrualPlatformService);
|
underTest = new AddPeriodicAccrualEntriesBusinessStep(loanAccrualPlatformService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenLoanWithAccrual() throws MultiException {
|
public void givenLoanWithAccrual() throws MultiException {
|
||||||
// given
|
// given
|
||||||
|
|||||||
+5
-1
@@ -122,7 +122,11 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
|
|||||||
});
|
});
|
||||||
|
|
||||||
When("ApplyLoanLockTasklet.execute method executed", () -> {
|
When("ApplyLoanLockTasklet.execute method executed", () -> {
|
||||||
resultItem = applyLoanLockTasklet.execute(stepContribution, null);
|
try {
|
||||||
|
resultItem = applyLoanLockTasklet.execute(stepContribution, null);
|
||||||
|
} finally {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("ApplyLoanLockTasklet.execute result should match", () -> {
|
Then("ApplyLoanLockTasklet.execute result should match", () -> {
|
||||||
|
|||||||
+6
@@ -46,6 +46,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanSummary;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -72,6 +73,11 @@ public class CheckLoanRepaymentDueBusinessStepTest {
|
|||||||
underTest = new CheckLoanRepaymentDueBusinessStep(configurationDomainService, businessEventNotifierService);
|
underTest = new CheckLoanRepaymentDueBusinessStep(configurationDomainService, businessEventNotifierService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenLoanWithInstallmentDueAfterConfiguredDaysWhenStepExecutionThenBusinessEventIsRaised() {
|
public void givenLoanWithInstallmentDueAfterConfiguredDaysWhenStepExecutionThenBusinessEventIsRaised() {
|
||||||
ArgumentCaptor<LoanRepaymentDueBusinessEvent> loanRepaymentDueEvent = ArgumentCaptor.forClass(LoanRepaymentDueBusinessEvent.class);
|
ArgumentCaptor<LoanRepaymentDueBusinessEvent> loanRepaymentDueEvent = ArgumentCaptor.forClass(LoanRepaymentDueBusinessEvent.class);
|
||||||
|
|||||||
+6
-1
@@ -43,6 +43,7 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -69,6 +70,11 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
|
|||||||
underTest = new CheckLoanRepaymentOverdueBusinessStep(configurationDomainService, businessEventNotifierService);
|
underTest = new CheckLoanRepaymentOverdueBusinessStep(configurationDomainService, businessEventNotifierService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenLoanWithInstallmentOverdueAfterConfiguredDaysWhenStepExecutionThenBusinessEventIsRaised() {
|
public void givenLoanWithInstallmentOverdueAfterConfiguredDaysWhenStepExecutionThenBusinessEventIsRaised() {
|
||||||
ArgumentCaptor<LoanRepaymentOverdueBusinessEvent> loanRepaymentDueBusinessEventArgumentCaptor = ArgumentCaptor
|
ArgumentCaptor<LoanRepaymentOverdueBusinessEvent> loanRepaymentDueBusinessEventArgumentCaptor = ArgumentCaptor
|
||||||
@@ -169,5 +175,4 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
|
|||||||
assertEquals(repaymentInstallment, loanPayloadForEvent);
|
assertEquals(repaymentInstallment, loanPayloadForEvent);
|
||||||
assertEquals(processedLoan, loanForProcessing);
|
assertEquals(processedLoan, loanForProcessing);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -40,6 +40,7 @@ import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
|||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -73,6 +74,11 @@ class LoanItemReaderTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private Loan loan;
|
private Loan loan;
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoanItemReaderSimple() throws Exception {
|
public void testLoanItemReaderSimple() throws Exception {
|
||||||
// given
|
// given
|
||||||
@@ -163,5 +169,4 @@ class LoanItemReaderTest {
|
|||||||
|
|
||||||
Mockito.verifyNoMoreInteractions(loanRepository);
|
Mockito.verifyNoMoreInteractions(loanRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -47,6 +47,7 @@ import org.apache.fineract.portfolio.delinquency.helper.DelinquencyEffectivePaus
|
|||||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -100,6 +101,11 @@ public class SetLoanDelinquencyTagsBusinessStepTest {
|
|||||||
delinquencyReadPlatformService, businessEventNotifierService);
|
delinquencyReadPlatformService, businessEventNotifierService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link SetLoanDelinquencyTagsBusinessStep#execute(Loan)} success scenario.
|
* Tests {@link SetLoanDelinquencyTagsBusinessStep#execute(Loan)} success scenario.
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ public class COBBulkEventConfigurationTest {
|
|||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
|
ThreadLocalContextUtil.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+6
@@ -42,6 +42,7 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
|||||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -73,6 +74,11 @@ class InlineLoanCOBExecutorServiceImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private FineractProperties.FineractBodyItemSizeLimitProperties fineractBodyItemSizeLimitProperties;
|
private FineractProperties.FineractBodyItemSizeLimitProperties fineractBodyItemSizeLimitProperties;
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldExceptionThrownIfLoanIsAlreadyLocked() {
|
void shouldExceptionThrownIfLoanIsAlreadyLocked() {
|
||||||
JsonCommand command = mock(JsonCommand.class);
|
JsonCommand command = mock(JsonCommand.class);
|
||||||
|
|||||||
+6
-1
@@ -37,6 +37,7 @@ import org.apache.fineract.infrastructure.core.domain.ActionContext;
|
|||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -71,6 +72,11 @@ public class PurgeProcessedCommandsTaskletTest {
|
|||||||
underTest = new PurgeProcessedCommandsTasklet(repository, configurationDomainService);
|
underTest = new PurgeProcessedCommandsTasklet(repository, configurationDomainService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenEventsForPurgeWhenTaskExecutionThenEventsPurgeForDaysCriteria() {
|
public void givenEventsForPurgeWhenTaskExecutionThenEventsPurgeForDaysCriteria() {
|
||||||
// given
|
// given
|
||||||
@@ -97,5 +103,4 @@ public class PurgeProcessedCommandsTaskletTest {
|
|||||||
// then
|
// then
|
||||||
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-14
@@ -25,13 +25,10 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import io.cucumber.java8.En;
|
import io.cucumber.java8.En;
|
||||||
import io.github.resilience4j.retry.RetryRegistry;
|
import io.github.resilience4j.retry.RetryRegistry;
|
||||||
import io.github.resilience4j.retry.event.RetryEvent;
|
import io.github.resilience4j.retry.event.RetryEvent;
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.apache.fineract.commands.domain.CommandSource;
|
|
||||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||||
import org.apache.fineract.commands.exception.RollbackTransactionAsCommandIsNotApprovedByCheckerException;
|
import org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException;
|
||||||
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.infrastructure.core.domain.FineractRequestContextHolder;
|
import org.apache.fineract.infrastructure.core.domain.FineractRequestContextHolder;
|
||||||
@@ -69,7 +66,7 @@ public class CommandServiceStepDefinitions implements En {
|
|||||||
ReflectionTestUtils.setField(processAndLogCommandService, "fineractRequestContextHolder", contextHolder);
|
ReflectionTestUtils.setField(processAndLogCommandService, "fineractRequestContextHolder", contextHolder);
|
||||||
Mockito.when(contextHolder.getAttribute(any(), any())).thenThrow(new CannotAcquireLockException("BLOW IT UP!!!"))
|
Mockito.when(contextHolder.getAttribute(any(), any())).thenThrow(new CannotAcquireLockException("BLOW IT UP!!!"))
|
||||||
.thenThrow(new ObjectOptimisticLockingFailureException("Dummy", new RuntimeException("BLOW IT UP!!!")))
|
.thenThrow(new ObjectOptimisticLockingFailureException("Dummy", new RuntimeException("BLOW IT UP!!!")))
|
||||||
.thenThrow(new RollbackTransactionAsCommandIsNotApprovedByCheckerException(new DummyCommandSource()));
|
.thenThrow(new RollbackTransactionNotApprovedException(1L, null));
|
||||||
|
|
||||||
this.retryRegistry.retry("executeCommand").getEventPublisher().onRetry(event -> {
|
this.retryRegistry.retry("executeCommand").getEventPublisher().onRetry(event -> {
|
||||||
log.warn("... retry event: {}", event);
|
log.warn("... retry event: {}", event);
|
||||||
@@ -147,13 +144,4 @@ public class CommandServiceStepDefinitions implements En {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "m_portfolio_command_source")
|
|
||||||
public static class DummyCommandSource extends CommandSource {
|
|
||||||
|
|
||||||
public DummyCommandSource() {
|
|
||||||
setId(1L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-14
@@ -89,24 +89,12 @@ public class CommandSourceServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateFromExisting() {
|
public void testCreateFromExisting() {
|
||||||
CommandWrapper wrapper = CommandWrapper.wrap("act", "ent", 1L, 1L);
|
|
||||||
long commandId = 1L;
|
long commandId = 1L;
|
||||||
JsonCommand jsonCommand = JsonCommand.fromExistingCommand(commandId, "", null, null, null, 1L, null, null, null, null, null, null,
|
|
||||||
null, null, null, null, null);
|
|
||||||
CommandSource commandMock = Mockito.mock(CommandSource.class);
|
CommandSource commandMock = Mockito.mock(CommandSource.class);
|
||||||
Mockito.when(commandSourceRepository.saveAndFlush(commandMock)).thenReturn(commandMock);
|
|
||||||
Mockito.when(commandSourceRepository.findById(commandId)).thenReturn(Optional.of(commandMock));
|
Mockito.when(commandSourceRepository.findById(commandId)).thenReturn(Optional.of(commandMock));
|
||||||
AppUser appUser = Mockito.mock(AppUser.class);
|
|
||||||
|
|
||||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "t1", "n1", ZoneId.systemDefault().toString(), null));
|
CommandSource actual = underTest.getCommandSource(commandId);
|
||||||
|
Assertions.assertEquals(commandMock, actual);
|
||||||
CommandSource actual = underTest.saveInitialNewTransaction(wrapper, jsonCommand, appUser, "idk");
|
|
||||||
|
|
||||||
ArgumentCaptor<CommandSource> commandSourceArgumentCaptor = ArgumentCaptor.forClass(CommandSource.class);
|
|
||||||
Mockito.verify(commandSourceRepository).saveAndFlush(commandSourceArgumentCaptor.capture());
|
|
||||||
|
|
||||||
CommandSource captured = commandSourceArgumentCaptor.getValue();
|
|
||||||
Assertions.assertEquals(actual, captured);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+20
-12
@@ -67,8 +67,6 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private IdempotencyKeyResolver idempotencyKeyResolver;
|
private IdempotencyKeyResolver idempotencyKeyResolver;
|
||||||
@Mock
|
@Mock
|
||||||
private IdempotencyKeyGenerator idempotencyKeyGenerator;
|
|
||||||
@Mock
|
|
||||||
private CommandSourceService commandSourceService;
|
private CommandSourceService commandSourceService;
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
@@ -93,19 +91,21 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
when(commandWrapper.isNoteResource()).thenReturn(false);
|
when(commandWrapper.isNoteResource()).thenReturn(false);
|
||||||
when(commandWrapper.isSurveyResource()).thenReturn(false);
|
when(commandWrapper.isSurveyResource()).thenReturn(false);
|
||||||
when(commandWrapper.isLoanDisburseDetailResource()).thenReturn(false);
|
when(commandWrapper.isLoanDisburseDetailResource()).thenReturn(false);
|
||||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
|
||||||
|
|
||||||
NewCommandSourceHandler newCommandSourceHandler = Mockito.mock(NewCommandSourceHandler.class);
|
long commandId = 1L;
|
||||||
|
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||||
|
when(jsonCommand.commandId()).thenReturn(commandId);
|
||||||
|
|
||||||
|
NewCommandSourceHandler commandHandler = Mockito.mock(NewCommandSourceHandler.class);
|
||||||
CommandProcessingResult commandProcessingResult = Mockito.mock(CommandProcessingResult.class);
|
CommandProcessingResult commandProcessingResult = Mockito.mock(CommandProcessingResult.class);
|
||||||
when(commandProcessingResult.isRollbackTransaction()).thenReturn(false);
|
when(commandProcessingResult.isRollbackTransaction()).thenReturn(false);
|
||||||
when(newCommandSourceHandler.processCommand(jsonCommand)).thenReturn(commandProcessingResult);
|
when(commandHandler.processCommand(jsonCommand)).thenReturn(commandProcessingResult);
|
||||||
when(commandHandlerProvider.getHandler(Mockito.any(), Mockito.any())).thenReturn(newCommandSourceHandler);
|
when(commandHandlerProvider.getHandler(Mockito.any(), Mockito.any())).thenReturn(commandHandler);
|
||||||
|
|
||||||
when(configurationDomainService.isMakerCheckerEnabledForTask(Mockito.any())).thenReturn(false);
|
when(configurationDomainService.isMakerCheckerEnabledForTask(Mockito.any())).thenReturn(false);
|
||||||
String idk = "idk";
|
String idk = "idk";
|
||||||
when(idempotencyKeyResolver.resolve(commandWrapper)).thenReturn(idk);
|
when(idempotencyKeyResolver.resolve(commandWrapper)).thenReturn(idk);
|
||||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||||
long commandId = 1L;
|
|
||||||
when(commandSource.getId()).thenReturn(commandId);
|
when(commandSource.getId()).thenReturn(commandId);
|
||||||
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(null);
|
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(null);
|
||||||
when(commandSourceService.getCommandSource(commandId)).thenReturn(commandSource);
|
when(commandSourceService.getCommandSource(commandId)).thenReturn(commandSource);
|
||||||
@@ -116,9 +116,12 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
when(commandSource.getStatus()).thenReturn(CommandProcessingResultType.PROCESSED.getValue());
|
when(commandSource.getStatus()).thenReturn(CommandProcessingResultType.PROCESSED.getValue());
|
||||||
when(context.authenticatedUser(Mockito.any(CommandWrapper.class))).thenReturn(appUser);
|
when(context.authenticatedUser(Mockito.any(CommandWrapper.class))).thenReturn(appUser);
|
||||||
|
|
||||||
|
when(commandSourceService.processCommand(commandHandler, jsonCommand, commandSource, appUser, false, false))
|
||||||
|
.thenReturn(commandProcessingResult);
|
||||||
|
|
||||||
CommandProcessingResult actualCommandProcessingResult = underTest.executeCommand(commandWrapper, jsonCommand, false);
|
CommandProcessingResult actualCommandProcessingResult = underTest.executeCommand(commandWrapper, jsonCommand, false);
|
||||||
|
|
||||||
verify(commandSourceService).saveInitialNewTransaction(commandWrapper, jsonCommand, appUser, idk);
|
verify(commandSourceService).getCommandSource(commandId);
|
||||||
assertEquals(CommandProcessingResultType.PROCESSED.getValue(), commandSource.getStatus());
|
assertEquals(CommandProcessingResultType.PROCESSED.getValue(), commandSource.getStatus());
|
||||||
verify(commandSourceService).saveResultSameTransaction(commandSource);
|
verify(commandSourceService).saveResultSameTransaction(commandSource);
|
||||||
|
|
||||||
@@ -133,19 +136,21 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
when(commandWrapper.isSurveyResource()).thenReturn(false);
|
when(commandWrapper.isSurveyResource()).thenReturn(false);
|
||||||
when(commandWrapper.isLoanDisburseDetailResource()).thenReturn(false);
|
when(commandWrapper.isLoanDisburseDetailResource()).thenReturn(false);
|
||||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||||
|
Long commandId = jsonCommand.commandId();
|
||||||
|
|
||||||
NewCommandSourceHandler newCommandSourceHandler = Mockito.mock(NewCommandSourceHandler.class);
|
NewCommandSourceHandler commandHandler = Mockito.mock(NewCommandSourceHandler.class);
|
||||||
CommandProcessingResult commandProcessingResult = Mockito.mock(CommandProcessingResult.class);
|
CommandProcessingResult commandProcessingResult = Mockito.mock(CommandProcessingResult.class);
|
||||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||||
when(commandProcessingResult.isRollbackTransaction()).thenReturn(false);
|
when(commandProcessingResult.isRollbackTransaction()).thenReturn(false);
|
||||||
RuntimeException runtimeException = new RuntimeException("foo");
|
RuntimeException runtimeException = new RuntimeException("foo");
|
||||||
when(newCommandSourceHandler.processCommand(jsonCommand)).thenThrow(runtimeException);
|
when(commandHandler.processCommand(jsonCommand)).thenThrow(runtimeException);
|
||||||
when(commandHandlerProvider.getHandler(Mockito.any(), Mockito.any())).thenReturn(newCommandSourceHandler);
|
when(commandHandlerProvider.getHandler(Mockito.any(), Mockito.any())).thenReturn(commandHandler);
|
||||||
|
|
||||||
when(configurationDomainService.isMakerCheckerEnabledForTask(Mockito.any())).thenReturn(false);
|
when(configurationDomainService.isMakerCheckerEnabledForTask(Mockito.any())).thenReturn(false);
|
||||||
String idk = "idk";
|
String idk = "idk";
|
||||||
when(idempotencyKeyResolver.resolve(commandWrapper)).thenReturn(idk);
|
when(idempotencyKeyResolver.resolve(commandWrapper)).thenReturn(idk);
|
||||||
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(null);
|
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(null);
|
||||||
|
when(commandSourceService.getCommandSource(commandId)).thenReturn(commandSource);
|
||||||
|
|
||||||
AppUser appUser = Mockito.mock(AppUser.class);
|
AppUser appUser = Mockito.mock(AppUser.class);
|
||||||
when(context.authenticatedUser(Mockito.any(CommandWrapper.class))).thenReturn(appUser);
|
when(context.authenticatedUser(Mockito.any(CommandWrapper.class))).thenReturn(appUser);
|
||||||
@@ -155,11 +160,14 @@ public class SynchronousCommandProcessingServiceTest {
|
|||||||
|
|
||||||
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(initialCommandSource);
|
when(commandSourceService.findCommandSource(commandWrapper, idk)).thenReturn(initialCommandSource);
|
||||||
|
|
||||||
|
when(commandSourceService.processCommand(commandHandler, jsonCommand, commandSource, appUser, false, false))
|
||||||
|
.thenThrow(runtimeException);
|
||||||
|
|
||||||
Assertions.assertThrows(RuntimeException.class, () -> {
|
Assertions.assertThrows(RuntimeException.class, () -> {
|
||||||
underTest.executeCommand(commandWrapper, jsonCommand, false);
|
underTest.executeCommand(commandWrapper, jsonCommand, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
verify(commandSourceService).saveInitialNewTransaction(commandWrapper, jsonCommand, appUser, idk);
|
verify(commandSourceService).getCommandSource(commandId);
|
||||||
verify(commandSourceService).generateErrorInfo(runtimeException);
|
verify(commandSourceService).generateErrorInfo(runtimeException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -42,6 +42,7 @@ import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
|||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -79,6 +80,11 @@ public class BusinessDateWritePlatformServiceTest {
|
|||||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void businessDateIsNotEnabled() {
|
public void businessDateIsNotEnabled() {
|
||||||
JsonCommand command = JsonCommand.from("");
|
JsonCommand command = JsonCommand.from("");
|
||||||
|
|||||||
+6
-1
@@ -33,6 +33,7 @@ import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDa
|
|||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
@@ -48,6 +49,11 @@ public class CustomAuditingHandlerTest {
|
|||||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.of("Asia/Kolkata")))));
|
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.of("Asia/Kolkata")))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void markCreated() {
|
public void markCreated() {
|
||||||
MappingContext mappingContext = Mockito.mock(MappingContext.class);
|
MappingContext mappingContext = Mockito.mock(MappingContext.class);
|
||||||
@@ -111,5 +117,4 @@ public class CustomAuditingHandlerTest {
|
|||||||
assertEquals(now.getHour(), targetObject.getCreatedDate().get().getHour());
|
assertEquals(now.getHour(), targetObject.getCreatedDate().get().getHour());
|
||||||
assertEquals(now.getMinute(), targetObject.getCreatedDate().get().getMinute());
|
assertEquals(now.getMinute(), targetObject.getCreatedDate().get().getMinute());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -28,6 +28,7 @@ import java.util.Optional;
|
|||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ public class CustomDateTimeProviderTest {
|
|||||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void instanceDateProvider() {
|
public void instanceDateProvider() {
|
||||||
Optional<TemporalAccessor> dateTimeProvider = CustomDateTimeProvider.INSTANCE.getNow();
|
Optional<TemporalAccessor> dateTimeProvider = CustomDateTimeProvider.INSTANCE.getNow();
|
||||||
@@ -65,5 +71,4 @@ public class CustomDateTimeProviderTest {
|
|||||||
assertEquals(now.getHour(), ((OffsetDateTime) dateTimeProvider.get()).getHour());
|
assertEquals(now.getHour(), ((OffsetDateTime) dateTimeProvider.get()).getHour());
|
||||||
assertEquals(now.getMinute(), ((OffsetDateTime) dateTimeProvider.get()).getMinute());
|
assertEquals(now.getMinute(), ((OffsetDateTime) dateTimeProvider.get()).getMinute());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -32,6 +32,7 @@ import java.util.Map;
|
|||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -43,6 +44,11 @@ public class DateUtilsTest {
|
|||||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 12))));
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 6, 12))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSystemZoneIdTest() {
|
public void getSystemZoneIdTest() {
|
||||||
TimeZone.setDefault(TimeZone.getTimeZone("GMT+02:00"));
|
TimeZone.setDefault(TimeZone.getTimeZone("GMT+02:00"));
|
||||||
|
|||||||
+14
@@ -21,12 +21,26 @@ package org.apache.fineract.infrastructure.dataqueries.service;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.infrastructure.dataqueries.service.export.DatatableExportUtil;
|
import org.apache.fineract.infrastructure.dataqueries.service.export.DatatableExportUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class DatatableExportUtilTest {
|
public class DatatableExportUtilTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptyFolderTest() {
|
public void emptyFolderTest() {
|
||||||
Assert.assertEquals("", DatatableExportUtil.normalizeFolderName(""));
|
Assert.assertEquals("", DatatableExportUtil.normalizeFolderName(""));
|
||||||
|
|||||||
+6
-1
@@ -35,6 +35,7 @@ import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
|||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventRepository;
|
import org.apache.fineract.infrastructure.event.external.repository.ExternalEventRepository;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -69,6 +70,11 @@ public class PurgeExternalEventsTaskletTest {
|
|||||||
underTest = new PurgeExternalEventsTasklet(repository, configurationDomainService);
|
underTest = new PurgeExternalEventsTasklet(repository, configurationDomainService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenEventsForPurgeWhenTaskExecutionThenEventsPurgeForDaysCriteria() {
|
public void givenEventsForPurgeWhenTaskExecutionThenEventsPurgeForDaysCriteria() {
|
||||||
// given
|
// given
|
||||||
@@ -95,5 +101,4 @@ public class PurgeExternalEventsTaskletTest {
|
|||||||
// then
|
// then
|
||||||
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.event.external.repository.ExternalEven
|
|||||||
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventView;
|
import org.apache.fineract.infrastructure.event.external.repository.domain.ExternalEventView;
|
||||||
import org.apache.fineract.infrastructure.event.external.service.message.MessageFactory;
|
import org.apache.fineract.infrastructure.event.external.service.message.MessageFactory;
|
||||||
import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
|
import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -97,6 +98,11 @@ class SendAsynchronousEventsTaskletTest {
|
|||||||
configurationDomainService);
|
configurationDomainService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
private void configureExternalEventsProducerReadBatchSizeProperty() {
|
private void configureExternalEventsProducerReadBatchSizeProperty() {
|
||||||
FineractProperties.FineractEventsProperties eventsProperties = new FineractProperties.FineractEventsProperties();
|
FineractProperties.FineractEventsProperties eventsProperties = new FineractProperties.FineractEventsProperties();
|
||||||
FineractProperties.FineractExternalEventsProperties externalProperties = new FineractProperties.FineractExternalEventsProperties();
|
FineractProperties.FineractExternalEventsProperties externalProperties = new FineractProperties.FineractExternalEventsProperties();
|
||||||
|
|||||||
+6
-1
@@ -26,10 +26,16 @@ import java.util.Map;
|
|||||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class ExternalEventTest {
|
class ExternalEventTest {
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstructorWorks() {
|
public void testConstructorWorks() {
|
||||||
// given
|
// given
|
||||||
@@ -56,6 +62,5 @@ class ExternalEventTest {
|
|||||||
assertThat(result.getBusinessDate()).isEqualTo(currentBusinessDate);
|
assertThat(result.getBusinessDate()).isEqualTo(currentBusinessDate);
|
||||||
assertThat(result.getCreatedAt()).isNotNull();
|
assertThat(result.getCreatedAt()).isNotNull();
|
||||||
assertThat(result.getSentAt()).isNull();
|
assertThat(result.getSentAt()).isNull();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -57,6 +57,7 @@ import org.apache.fineract.infrastructure.event.external.service.support.ByteBuf
|
|||||||
import org.apache.fineract.investor.enricher.LoanAccountDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanAccountDataV1Enricher;
|
||||||
import org.apache.fineract.investor.enricher.LoanTransactionAdjustmentDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanTransactionAdjustmentDataV1Enricher;
|
||||||
import org.apache.fineract.investor.enricher.LoanTransactionDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanTransactionDataV1Enricher;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -110,6 +111,11 @@ class ExternalEventServiceTest {
|
|||||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPostEventShouldFailWhenNullEventIsGiven() {
|
public void testPostEventShouldFailWhenNullEventIsGiven() {
|
||||||
// given
|
// given
|
||||||
|
|||||||
+6
-1
@@ -70,6 +70,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -105,6 +106,11 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
|||||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoanDelinquencyRangeEventPayloadSerialization() throws IOException {
|
public void testLoanDelinquencyRangeEventPayloadSerialization() throws IOException {
|
||||||
// given
|
// given
|
||||||
@@ -340,5 +346,4 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
|
|||||||
ReflectionTestUtils.setField(loanCharge, "id", 1L);
|
ReflectionTestUtils.setField(loanCharge, "id", 1L);
|
||||||
return loanCharge;
|
return loanCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -47,6 +47,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanChargePaidByReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanChargePaidByReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -78,6 +79,11 @@ public class LoanAdjustTransactionBusinessEventSerializerTest {
|
|||||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loanTransactionReversedOnDateSerializationTest() {
|
void loanTransactionReversedOnDateSerializationTest() {
|
||||||
Loan loanForProcessing = Mockito.mock(Loan.class);
|
Loan loanForProcessing = Mockito.mock(Loan.class);
|
||||||
@@ -107,5 +113,4 @@ public class LoanAdjustTransactionBusinessEventSerializerTest {
|
|||||||
.toAvroDTO(businessEvent);
|
.toAvroDTO(businessEvent);
|
||||||
assertEquals(reversedLocalDate, loanTransactionAdjustmentDataV1.getTransactionToAdjust().getReversedOnDate());
|
assertEquals(reversedLocalDate, loanTransactionAdjustmentDataV1.getTransactionToAdjust().getReversedOnDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -90,6 +90,7 @@ public class LoanRepaymentBusinessEventSerializerTest {
|
|||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
moneyHelper.close();
|
moneyHelper.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,5 +182,4 @@ public class LoanRepaymentBusinessEventSerializerTest {
|
|||||||
AvroRuntimeException exceptionThrown = assertThrows(AvroRuntimeException.class, () -> serializer.toAvroDTO(event));
|
AvroRuntimeException exceptionThrown = assertThrows(AvroRuntimeException.class, () -> serializer.toAvroDTO(event));
|
||||||
assertTrue(exceptionThrown.getMessage().contains("does not accept null values"));
|
assertTrue(exceptionThrown.getMessage().contains("does not accept null values"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -56,6 +56,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
|
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequestRepository;
|
||||||
import org.apache.fineract.useradministration.domain.AppUser;
|
import org.apache.fineract.useradministration.domain.AppUser;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -99,6 +100,11 @@ class LoanCOBApiFilterTest {
|
|||||||
testObj = new LoanCOBApiFilter(helper);
|
testObj = new LoanCOBApiFilter(helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldLoanAndExternalMatchToo() {
|
void shouldLoanAndExternalMatchToo() {
|
||||||
String externalId = UUID.randomUUID().toString();
|
String externalId = UUID.randomUUID().toString();
|
||||||
|
|||||||
+6
-1
@@ -45,6 +45,7 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
|||||||
import org.apache.fineract.investor.enricher.LoanAccountDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanAccountDataV1Enricher;
|
||||||
import org.apache.fineract.investor.enricher.LoanChargeDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanChargeDataV1Enricher;
|
||||||
import org.apache.fineract.investor.enricher.LoanTransactionDataV1Enricher;
|
import org.apache.fineract.investor.enricher.LoanTransactionDataV1Enricher;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -66,6 +67,11 @@ public class EnricherTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoanAccountDataEnricher() {
|
public void testLoanAccountDataEnricher() {
|
||||||
LoanAccountDataV1Enricher loanAccountDataV1Enricher = mock(LoanAccountDataV1Enricher.class);
|
LoanAccountDataV1Enricher loanAccountDataV1Enricher = mock(LoanAccountDataV1Enricher.class);
|
||||||
@@ -178,5 +184,4 @@ public class EnricherTest {
|
|||||||
assertEquals(PURCHASE_PRICE_RATIO, data.getPurchasePriceRatio());
|
assertEquals(PURCHASE_PRICE_RATIO, data.getPurchasePriceRatio());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-1
@@ -76,6 +76,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -130,6 +131,11 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
|||||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenLoanAccountWithDelinquencyBucketWhenRangeChangeThenEventIsRaised() {
|
public void givenLoanAccountWithDelinquencyBucketWhenRangeChangeThenEventIsRaised() {
|
||||||
ArgumentCaptor<LoanDelinquencyRangeChangeBusinessEvent> loanDeliquencyRangeChangeEvent = ArgumentCaptor
|
ArgumentCaptor<LoanDelinquencyRangeChangeBusinessEvent> loanDeliquencyRangeChangeEvent = ArgumentCaptor
|
||||||
@@ -614,5 +620,4 @@ public class DelinquencyWritePlatformServiceRangeChangeEventTest {
|
|||||||
Loan loanPayloadForEvent = loanDelinquencyRangeChangeEvent.getValue().get();
|
Loan loanPayloadForEvent = loanDelinquencyRangeChangeEvent.getValue().get();
|
||||||
assertEquals(loanForProcessing, loanPayloadForEvent);
|
assertEquals(loanForProcessing, loanPayloadForEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -105,6 +105,7 @@ public class LoanDelinquencyDomainServiceTest {
|
|||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void deregister() {
|
public void deregister() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
moneyHelperStatic.close();
|
moneyHelperStatic.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
@@ -27,16 +27,23 @@ import static org.mockito.Mockito.when;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||||
|
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
|
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||||
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
||||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
@@ -46,11 +53,21 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||||||
*/
|
*/
|
||||||
public class LoanTest {
|
public class LoanTest {
|
||||||
|
|
||||||
|
private final LocalDate actualDate = LocalDate.now(ZoneId.systemDefault());
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests {@link Loan#getCharges()} with charges.
|
* Tests {@link Loan#getCharges()} with charges.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGetChargesWithCharges() {
|
public void testGetChargesWithCharges() {
|
||||||
|
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||||
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, actualDate)));
|
||||||
|
|
||||||
Loan loan = new Loan();
|
Loan loan = new Loan();
|
||||||
ReflectionTestUtils.setField(loan, "charges", Collections.singleton(buildLoanCharge()));
|
ReflectionTestUtils.setField(loan, "charges", Collections.singleton(buildLoanCharge()));
|
||||||
|
|
||||||
|
|||||||
+6
@@ -48,6 +48,7 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail
|
|||||||
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationTransactionType;
|
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationTransactionType;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
|
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -83,6 +84,11 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
|
|||||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void chargePaymentTransactionTestWithExactAmount() {
|
public void chargePaymentTransactionTestWithExactAmount() {
|
||||||
final BigDecimal chargeAmount = BigDecimal.valueOf(100);
|
final BigDecimal chargeAmount = BigDecimal.valueOf(100);
|
||||||
|
|||||||
+6
@@ -44,6 +44,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -104,6 +105,11 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio
|
|||||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// IN ADVANCE
|
// IN ADVANCE
|
||||||
@Test
|
@Test
|
||||||
public void inAdvancePaymentOfPrincipal() {
|
public void inAdvancePaymentOfPrincipal() {
|
||||||
|
|||||||
+6
@@ -44,6 +44,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -105,6 +106,11 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio
|
|||||||
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
ThreadLocalContextUtil.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, transactionDate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// IN ADVANCE
|
// IN ADVANCE
|
||||||
@Test
|
@Test
|
||||||
public void inAdvancePaymentOfPrincipal() {
|
public void inAdvancePaymentOfPrincipal() {
|
||||||
|
|||||||
+1
@@ -69,6 +69,7 @@ public class LoanCalculateRepaymentPastDueServiceTest {
|
|||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
ThreadLocalContextUtil.reset();
|
||||||
moneyHelper.close();
|
moneyHelper.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-6
@@ -2153,12 +2153,7 @@ public class BatchApiTest {
|
|||||||
|
|
||||||
LOG.info("Batch Response : {}", new Gson().toJson(responseOfQueryAndUpdateDatatableBatch));
|
LOG.info("Batch Response : {}", new Gson().toJson(responseOfQueryAndUpdateDatatableBatch));
|
||||||
|
|
||||||
final BatchResponse queryResponse = responseOfQueryAndUpdateDatatableBatch.get(0);
|
final BatchResponse updateResponse = responseOfQueryAndUpdateDatatableBatch.get(0);
|
||||||
|
|
||||||
Assertions.assertEquals(1L, queryResponse.getRequestId());
|
|
||||||
Assertions.assertEquals(HttpStatus.SC_OK, queryResponse.getStatusCode(), "Verify Status Code 200 for query datatable entry");
|
|
||||||
|
|
||||||
final BatchResponse updateResponse = responseOfQueryAndUpdateDatatableBatch.get(1);
|
|
||||||
|
|
||||||
Assertions.assertEquals(2L, updateResponse.getRequestId());
|
Assertions.assertEquals(2L, updateResponse.getRequestId());
|
||||||
Assertions.assertEquals(HttpStatus.SC_BAD_REQUEST, updateResponse.getStatusCode(),
|
Assertions.assertEquals(HttpStatus.SC_BAD_REQUEST, updateResponse.getStatusCode(),
|
||||||
|
|||||||
+5
-2
@@ -21,6 +21,7 @@ package org.apache.fineract.integrationtests;
|
|||||||
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.PAUSE;
|
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.PAUSE;
|
||||||
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.RESUME;
|
import static org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction.RESUME;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
@@ -109,8 +110,10 @@ public class DelinquencyBucketsIntegrationTest {
|
|||||||
// then
|
// then
|
||||||
assertNotNull(delinquencyRangeResponse01);
|
assertNotNull(delinquencyRangeResponse01);
|
||||||
assertNotNull(ranges);
|
assertNotNull(ranges);
|
||||||
assertEquals(1, ranges.get(0).getMinimumAgeDays(), "Expected Min Age Days to 1");
|
assertFalse(ranges.isEmpty());
|
||||||
assertEquals(3, ranges.get(0).getMaximumAgeDays(), "Expected Max Age Days to 3");
|
GetDelinquencyRangesResponse range = ranges.get(ranges.size() - 1);
|
||||||
|
assertEquals(1, range.getMinimumAgeDays(), "Expected Min Age Days to 1");
|
||||||
|
assertEquals(3, range.getMaximumAgeDays(), "Expected Max Age Days to 3");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+22
-18
@@ -19,22 +19,25 @@
|
|||||||
package org.apache.fineract.integrationtests;
|
package org.apache.fineract.integrationtests;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
import io.restassured.builder.RequestSpecBuilder;
|
import io.restassured.builder.RequestSpecBuilder;
|
||||||
import io.restassured.builder.ResponseSpecBuilder;
|
import io.restassured.builder.ResponseSpecBuilder;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.restassured.response.Response;
|
import io.restassured.response.Response;
|
||||||
|
import io.restassured.response.ResponseBody;
|
||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.apache.fineract.cob.data.BusinessStep;
|
import org.apache.fineract.cob.data.BusinessStep;
|
||||||
import org.apache.fineract.cob.data.JobBusinessStepConfigData;
|
import org.apache.fineract.cob.data.JobBusinessStepConfigData;
|
||||||
import org.apache.fineract.infrastructure.core.exception.AbstractIdempotentCommandException;
|
import org.apache.fineract.infrastructure.core.exception.AbstractIdempotentCommandException;
|
||||||
import org.apache.fineract.integrationtests.common.IdempotencyHelper;
|
import org.apache.fineract.integrationtests.common.IdempotencyHelper;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -70,9 +73,9 @@ public class IdempotencyTest {
|
|||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
||||||
Response responseSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
Response responseSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
||||||
Assertions.assertEquals(response.getBody().asString(), responseSecond.getBody().asString());
|
assertEquals(response.getBody().asString(), responseSecond.getBody().asString());
|
||||||
Assertions.assertNull(response.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNull(response.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertNotNull(responseSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNotNull(responseSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
|
|
||||||
idempotencyKeyHeader = UUID.randomUUID().toString();
|
idempotencyKeyHeader = UUID.randomUUID().toString();
|
||||||
|
|
||||||
@@ -89,9 +92,9 @@ public class IdempotencyTest {
|
|||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
||||||
Response updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
Response updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
||||||
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
||||||
|
|
||||||
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
|
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
|
||||||
applyChargeStep = newStepConfig.getBusinessSteps().stream()
|
applyChargeStep = newStepConfig.getBusinessSteps().stream()
|
||||||
@@ -109,9 +112,9 @@ public class IdempotencyTest {
|
|||||||
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKeyHeader);
|
||||||
|
|
||||||
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
||||||
|
|
||||||
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
|
newStepConfig = IdempotencyHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, LOAN_JOB_NAME);
|
||||||
applyChargeStep = newStepConfig.getBusinessSteps().stream()
|
applyChargeStep = newStepConfig.getBusinessSteps().stream()
|
||||||
@@ -126,14 +129,14 @@ public class IdempotencyTest {
|
|||||||
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
updateSecond = IdempotencyHelper.updateBusinessStepOrder(requestSpec, updateResponseSpec, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(originalStepConfig.getBusinessSteps()), idempotencyKeyHeader);
|
IdempotencyHelper.toJsonString(originalStepConfig.getBusinessSteps()), idempotencyKeyHeader);
|
||||||
|
|
||||||
Assertions.assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNull(update.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNotNull(updateSecond.header(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
assertEquals(update.getBody().asString(), updateSecond.getBody().asString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shoudTheSecondRequestWithSameIdempotencyKeyWillFailureToo() {
|
public void shouldTheSecondRequestWithSameIdempotencyKeyWillFailureToo() {
|
||||||
ResponseSpecification responseSpecForError = new ResponseSpecBuilder().expectStatusCode(400).build();
|
ResponseSpecification responseSpecForError = new ResponseSpecBuilder().expectStatusCode(400).build();
|
||||||
List<BusinessStep> requestBody = new ArrayList<>();
|
List<BusinessStep> requestBody = new ArrayList<>();
|
||||||
String idempotencyKey = UUID.randomUUID().toString();
|
String idempotencyKey = UUID.randomUUID().toString();
|
||||||
@@ -141,13 +144,14 @@ public class IdempotencyTest {
|
|||||||
|
|
||||||
Response response1 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
|
Response response1 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
|
||||||
Assertions.assertNull(response1.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNull(response1.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
String originalBody = response1.getBody().asString();
|
ResponseBody body1 = response1.getBody();
|
||||||
|
assertNotNull(body1);
|
||||||
|
|
||||||
Response response2 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
|
Response response2 = IdempotencyHelper.updateBusinessStepOrderWithError(requestSpec, responseSpecForError, LOAN_JOB_NAME,
|
||||||
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
|
IdempotencyHelper.toJsonString(requestBody), idempotencyKey);
|
||||||
Assertions.assertNotNull(response2.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
assertNotNull(response2.getHeader(AbstractIdempotentCommandException.IDEMPOTENT_CACHE_HEADER));
|
||||||
Assertions.assertEquals(originalBody, response2.getBody().asString());
|
assertEquals((Map) body1.jsonPath().get(""), response2.getBody().jsonPath().get(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BusinessStep getBusinessSteps(Long order, String stepName) {
|
private BusinessStep getBusinessSteps(Long order, String stepName) {
|
||||||
|
|||||||
+8
-8
@@ -181,8 +181,8 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
|
|||||||
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
|
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
|
||||||
.transactionAmount(BigDecimal.valueOf(1000.00)).locale("en"));
|
.transactionAmount(BigDecimal.valueOf(1000.00)).locale("en"));
|
||||||
|
|
||||||
final float feePortion = 50.0f;
|
final double feePortion = 50.0d;
|
||||||
final float penaltyPortion = 100.0f;
|
final double penaltyPortion = 100.0d;
|
||||||
|
|
||||||
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
|
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
|
||||||
ChargesHelper.getLoanSpecifiedDueDateWithAccountTransferJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
|
ChargesHelper.getLoanSpecifiedDueDateWithAccountTransferJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
|
||||||
@@ -209,8 +209,8 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
|
|||||||
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
|
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
|
||||||
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
|
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
|
||||||
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
|
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
|
||||||
assertEquals(400.0f, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
|
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
|
||||||
assertEquals(400.0f, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
|
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
|
|
||||||
scheduleJobHelper.executeAndAwaitJob(jobName);
|
scheduleJobHelper.executeAndAwaitJob(jobName);
|
||||||
@@ -218,11 +218,11 @@ public class LoanChargePaymentWithAdvancedPaymentAllocationTest {
|
|||||||
loanDetails = loanTransactionHelper.getLoanDetails((long) loanId);
|
loanDetails = loanTransactionHelper.getLoanDetails((long) loanId);
|
||||||
assertEquals(5, loanDetails.getRepaymentSchedule().getPeriods().size());
|
assertEquals(5, loanDetails.getRepaymentSchedule().getPeriods().size());
|
||||||
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesDue());
|
assertEquals(feePortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesDue());
|
||||||
assertEquals(0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
|
assertEquals(0.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getFeeChargesOutstanding());
|
||||||
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
|
assertEquals(penaltyPortion, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesDue());
|
||||||
assertEquals(0, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
|
assertEquals(0.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPenaltyChargesOutstanding());
|
||||||
assertEquals(400, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
|
assertEquals(400.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalDueForPeriod());
|
||||||
assertEquals(250, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
|
assertEquals(250.0d, loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalOutstandingForPeriod());
|
||||||
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
assertEquals(LocalDate.of(2023, 1, 16), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
|
||||||
} finally {
|
} finally {
|
||||||
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
|
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
|
||||||
|
|||||||
+162
-5
@@ -18,17 +18,31 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.integrationtests;
|
package org.apache.fineract.integrationtests;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
import io.restassured.builder.RequestSpecBuilder;
|
import io.restassured.builder.RequestSpecBuilder;
|
||||||
import io.restassured.builder.ResponseSpecBuilder;
|
import io.restassured.builder.ResponseSpecBuilder;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import org.apache.fineract.client.models.GetMakerCheckerResponse;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.fineract.client.models.GlobalConfigurationPropertyData;
|
||||||
|
import org.apache.fineract.client.models.PutPermissionsRequest;
|
||||||
|
import org.apache.fineract.integrationtests.common.AuditHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.CommonConstants;
|
||||||
|
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
import org.apache.fineract.integrationtests.common.commands.MakercheckersHelper;
|
import org.apache.fineract.integrationtests.common.commands.MakercheckersHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.organisation.StaffHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.savings.SavingsProductHelper;
|
||||||
|
import org.apache.fineract.integrationtests.useradministration.roles.RolesHelper;
|
||||||
|
import org.apache.fineract.integrationtests.useradministration.users.UserHelper;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -38,6 +52,12 @@ public class MakercheckerTest {
|
|||||||
private ResponseSpecification responseSpec;
|
private ResponseSpecification responseSpec;
|
||||||
private RequestSpecification requestSpec;
|
private RequestSpecification requestSpec;
|
||||||
private MakercheckersHelper makercheckersHelper;
|
private MakercheckersHelper makercheckersHelper;
|
||||||
|
private RolesHelper rolesHelper;
|
||||||
|
private AuditHelper auditHelper;
|
||||||
|
private SavingsProductHelper savingsProductHelper;
|
||||||
|
private SavingsAccountHelper savingsAccountHelper;
|
||||||
|
private static final String START_DATE_STRING = "03 June 2023";
|
||||||
|
private static final String TRANSACTION_DATE_STRING = "05 June 2023";
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -46,14 +66,151 @@ public class MakercheckerTest {
|
|||||||
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||||
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||||
this.makercheckersHelper = new MakercheckersHelper(this.requestSpec, this.responseSpec);
|
this.makercheckersHelper = new MakercheckersHelper(this.requestSpec, this.responseSpec);
|
||||||
|
this.rolesHelper = new RolesHelper();
|
||||||
|
this.auditHelper = new AuditHelper(requestSpec, responseSpec);
|
||||||
|
this.savingsProductHelper = new SavingsProductHelper();
|
||||||
|
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMakerchekerInboxList() {
|
public void testMakercheckerInboxList() {
|
||||||
// given
|
// given
|
||||||
// when
|
// when
|
||||||
final ArrayList<GetMakerCheckerResponse> makerCheckerList = this.makercheckersHelper.getMakerCheckerList();
|
List<Map<String, Object>> makerCheckerList = this.makercheckersHelper.getMakerCheckerList(null);
|
||||||
|
|
||||||
assertNotNull(makerCheckerList);
|
assertNotNull(makerCheckerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMakerCheckerOn() {
|
||||||
|
GlobalConfigurationPropertyData mcConfig = GlobalConfigurationHelper.getGlobalConfigurationByName(requestSpec, responseSpec,
|
||||||
|
"maker-checker");
|
||||||
|
Long mcConfigId = mcConfig.getId();
|
||||||
|
boolean mcConfigUpdate = false;
|
||||||
|
if (!Boolean.TRUE.equals(mcConfig.getEnabled())) {
|
||||||
|
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, mcConfigId, true);
|
||||||
|
mcConfigUpdate = true;
|
||||||
|
}
|
||||||
|
GlobalConfigurationPropertyData sameMcConfig = GlobalConfigurationHelper.getGlobalConfigurationByName(requestSpec, responseSpec,
|
||||||
|
"enable-same-maker-checker");
|
||||||
|
Long sameMcConfigId = mcConfig.getId();
|
||||||
|
boolean sameMcConfigUpdate = false;
|
||||||
|
if (Boolean.TRUE.equals(sameMcConfig.getEnabled())) {
|
||||||
|
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, sameMcConfigId, false);
|
||||||
|
sameMcConfigUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// client permission - maker-checker disabled
|
||||||
|
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("CREATE_CLIENT", false);
|
||||||
|
rolesHelper.updatePermissions(putPermissionsRequest);
|
||||||
|
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("ACTIVATE_CLIENT", false);
|
||||||
|
rolesHelper.updatePermissions(putPermissionsRequest);
|
||||||
|
|
||||||
|
Integer roleId = RolesHelper.createRole(requestSpec, responseSpec);
|
||||||
|
Map<String, Boolean> permissionMap = Map.of("CREATE_CLIENT", true, "CREATE_CLIENT_CHECKER", true, "ACTIVATE_CLIENT", true,
|
||||||
|
"ACTIVATE_CLIENT_CHECKER", true, "WITHDRAWAL_SAVINGSACCOUNT", true, "WITHDRAWAL_SAVINGSACCOUNT_CHECKER", true);
|
||||||
|
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
|
||||||
|
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
|
||||||
|
// create maker user
|
||||||
|
String maker = Utils.uniqueRandomStringGenerator("user", 8);
|
||||||
|
final Integer makerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, maker,
|
||||||
|
"P4ssw0rd", "resourceId");
|
||||||
|
|
||||||
|
// create client - maker-checker disabled
|
||||||
|
RequestSpecification makerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
|
||||||
|
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(maker, "P4ssw0rd"));
|
||||||
|
Integer clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
|
||||||
|
assertNotNull(clientId);
|
||||||
|
ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId);
|
||||||
|
|
||||||
|
final Integer savingsId = createApproveActivateSavingsAccountDailyPosting(clientId, START_DATE_STRING);
|
||||||
|
assertNotNull(savingsId);
|
||||||
|
Integer transactionId = (Integer) savingsAccountHelper.depositToSavingsAccount(savingsId, "1000", TRANSACTION_DATE_STRING,
|
||||||
|
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||||
|
assertNotNull(transactionId);
|
||||||
|
|
||||||
|
// client and saving permission - maker-checker enabled
|
||||||
|
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("ACTIVATE_CLIENT", true);
|
||||||
|
rolesHelper.updatePermissions(putPermissionsRequest);
|
||||||
|
putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("WITHDRAWAL_SAVINGSACCOUNT", true);
|
||||||
|
rolesHelper.updatePermissions(putPermissionsRequest);
|
||||||
|
|
||||||
|
// create client - maker-checker enabled
|
||||||
|
clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
|
||||||
|
assertNull(clientId, "Client is created on the server");
|
||||||
|
|
||||||
|
List<Map<String, Object>> auditDetails = makercheckersHelper
|
||||||
|
.getMakerCheckerList(Map.of("actionName", "CREATE", "entityName", "CLIENT", "makerId", makerUserId.toString()));
|
||||||
|
assertEquals(1, auditDetails.size(), "More than one command exists");
|
||||||
|
Long clientCommandId = ((Double) auditDetails.get(0).get("id")).longValue();
|
||||||
|
|
||||||
|
// savings withdrawal - maker-checker enabled
|
||||||
|
SavingsAccountHelper makerSavingsHelper = new SavingsAccountHelper(makerRequestSpec, this.responseSpec);
|
||||||
|
Integer withdrawalId = (Integer) makerSavingsHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE_STRING,
|
||||||
|
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||||
|
assertNull(withdrawalId, "Withdrawal performed on the server");
|
||||||
|
|
||||||
|
auditDetails = makercheckersHelper.getMakerCheckerList(
|
||||||
|
Map.of("actionName", "WITHDRAWAL", "entityName", "SAVINGSACCOUNT", "makerId", makerUserId.toString()));
|
||||||
|
assertEquals(1, auditDetails.size(), "More than one command exists");
|
||||||
|
Long savingCommandId = ((Double) auditDetails.get(0).get("id")).longValue();
|
||||||
|
|
||||||
|
// check by the same user should fail
|
||||||
|
ResponseSpecification failedResponseSpec = new ResponseSpecBuilder().expectStatusCode(400).build();
|
||||||
|
MakercheckersHelper.approveMakerCheckerEntry(makerRequestSpec, failedResponseSpec, clientCommandId);
|
||||||
|
MakercheckersHelper.approveMakerCheckerEntry(makerRequestSpec, failedResponseSpec, savingCommandId);
|
||||||
|
|
||||||
|
// create checker user
|
||||||
|
String checker = Utils.uniqueRandomStringGenerator("user", 8);
|
||||||
|
final Integer checkerUserId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, roleId, staffId, checker,
|
||||||
|
"P4ssw0rd", "resourceId");
|
||||||
|
RequestSpecification checkerRequestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build()
|
||||||
|
.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(checker, "P4ssw0rd"));
|
||||||
|
|
||||||
|
// check by another checker user should succeed
|
||||||
|
HashMap<?, ?> response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, clientCommandId);
|
||||||
|
assertNotNull(response);
|
||||||
|
clientId = (Integer) response.get("clientId");
|
||||||
|
assertNotNull(clientId);
|
||||||
|
ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientId);
|
||||||
|
|
||||||
|
response = MakercheckersHelper.approveMakerCheckerEntry(checkerRequestSpec, responseSpec, savingCommandId);
|
||||||
|
assertNotNull(response);
|
||||||
|
withdrawalId = (Integer) response.get("resourceId");
|
||||||
|
assertNotNull(withdrawalId);
|
||||||
|
|
||||||
|
// add checker superuser permission - actions are performed in one step
|
||||||
|
permissionMap = Map.of("CHECKER_SUPER_USER", true);
|
||||||
|
RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissionMap);
|
||||||
|
clientId = ClientHelper.createClient(makerRequestSpec, this.responseSpec);
|
||||||
|
assertNotNull(clientId);
|
||||||
|
ClientHelper.verifyClientCreatedOnServer(requestSpec, this.responseSpec, clientId);
|
||||||
|
|
||||||
|
withdrawalId = (Integer) makerSavingsHelper.withdrawalFromSavingsAccount(savingsId, "100", TRANSACTION_DATE_STRING,
|
||||||
|
CommonConstants.RESPONSE_RESOURCE_ID);
|
||||||
|
assertNotNull(withdrawalId);
|
||||||
|
} finally {
|
||||||
|
if (mcConfigUpdate) {
|
||||||
|
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, mcConfigId, false);
|
||||||
|
}
|
||||||
|
if (sameMcConfigUpdate) {
|
||||||
|
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, sameMcConfigId, true);
|
||||||
|
}
|
||||||
|
PutPermissionsRequest putPermissionsRequest = new PutPermissionsRequest().putPermissionsItem("WITHDRAWAL_SAVINGSACCOUNT",
|
||||||
|
false);
|
||||||
|
rolesHelper.updatePermissions(putPermissionsRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createSavingsProductDailyPosting() {
|
||||||
|
final String savingsProductJSON = this.savingsProductHelper.withInterestCompoundingPeriodTypeAsDaily()
|
||||||
|
.withInterestPostingPeriodTypeAsDaily().withInterestCalculationPeriodTypeAsDailyBalance().build();
|
||||||
|
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createApproveActivateSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
|
||||||
|
final Integer savingsProductID = createSavingsProductDailyPosting();
|
||||||
|
assertNotNull(savingsProductID);
|
||||||
|
return savingsAccountHelper.createApproveActivateSavingsAccount(clientID, savingsProductID, startDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-36
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.integrationtests;
|
package org.apache.fineract.integrationtests;
|
||||||
|
|
||||||
|
import static org.apache.fineract.integrationtests.common.CommonConstants.RESPONSE_RESOURCE_ID;
|
||||||
import static org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper.PAYMENT_TYPE_ID;
|
import static org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper.PAYMENT_TYPE_ID;
|
||||||
import static org.apache.fineract.integrationtests.common.system.DatatableHelper.addDatatableColumn;
|
import static org.apache.fineract.integrationtests.common.system.DatatableHelper.addDatatableColumn;
|
||||||
import static org.apache.http.HttpStatus.SC_CONFLICT;
|
import static org.apache.http.HttpStatus.SC_CONFLICT;
|
||||||
@@ -60,7 +61,6 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
|
|||||||
import org.apache.fineract.integrationtests.common.BatchHelper;
|
import org.apache.fineract.integrationtests.common.BatchHelper;
|
||||||
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
import org.apache.fineract.integrationtests.common.CommonConstants;
|
|
||||||
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
||||||
@@ -118,7 +118,7 @@ public class SavingsAccountTransactionTest {
|
|||||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDateString);
|
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDateString);
|
||||||
assertNotNull(clientID);
|
assertNotNull(clientID);
|
||||||
|
|
||||||
final Integer savingsId = createSavingsAccountDailyPosting(clientID, startDateString);
|
final Integer savingsId = createApproveActivateSavingsAccountDailyPosting(clientID, startDateString);
|
||||||
assertNotNull(savingsId);
|
assertNotNull(savingsId);
|
||||||
|
|
||||||
performSavingsTransaction(savingsId, "100", depositDate, true);
|
performSavingsTransaction(savingsId, "100", depositDate, true);
|
||||||
@@ -176,7 +176,7 @@ public class SavingsAccountTransactionTest {
|
|||||||
|
|
||||||
// creating datatable for client entity
|
// creating datatable for client entity
|
||||||
final HashMap<String, Object> columnMap = new HashMap<>();
|
final HashMap<String, Object> columnMap = new HashMap<>();
|
||||||
String datatableName = Utils.uniqueRandomStringGenerator("savings_transaction" + "_", 5).toLowerCase();
|
String datatableName = Utils.uniqueRandomStringGenerator("dt_savings_transaction_", 5).toLowerCase();
|
||||||
columnMap.put("datatableName", datatableName);
|
columnMap.put("datatableName", datatableName);
|
||||||
columnMap.put("apptableName", "m_savings_account_transaction");
|
columnMap.put("apptableName", "m_savings_account_transaction");
|
||||||
columnMap.put("multiRow", false);
|
columnMap.put("multiRow", false);
|
||||||
@@ -284,10 +284,9 @@ public class SavingsAccountTransactionTest {
|
|||||||
private void performSavingsTransaction(Integer savingsId, String amount, LocalDate transactionDate, boolean isDeposit) {
|
private void performSavingsTransaction(Integer savingsId, String amount, LocalDate transactionDate, boolean isDeposit) {
|
||||||
String transactionType = isDeposit ? "Deposit" : "Withdrawal";
|
String transactionType = isDeposit ? "Deposit" : "Withdrawal";
|
||||||
Integer transactionId = isDeposit
|
Integer transactionId = isDeposit
|
||||||
? (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, amount, depositDateString,
|
? (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, amount, depositDateString, RESPONSE_RESOURCE_ID)
|
||||||
CommonConstants.RESPONSE_RESOURCE_ID)
|
|
||||||
: (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, amount, withdrawDateString,
|
: (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, amount, withdrawDateString,
|
||||||
CommonConstants.RESPONSE_RESOURCE_ID);
|
RESPONSE_RESOURCE_ID);
|
||||||
|
|
||||||
assertNotNull(transactionId);
|
assertNotNull(transactionId);
|
||||||
|
|
||||||
@@ -311,17 +310,10 @@ public class SavingsAccountTransactionTest {
|
|||||||
return extractedDate;
|
return extractedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer createSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
|
private Integer createApproveActivateSavingsAccountDailyPosting(final Integer clientID, final String startDate) {
|
||||||
final Integer savingsProductID = createSavingsProductDailyPosting();
|
final Integer savingsProductID = createSavingsProductDailyPosting();
|
||||||
assertNotNull(savingsProductID);
|
assertNotNull(savingsProductID);
|
||||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID, savingsProductID,
|
return savingsAccountHelper.createApproveActivateSavingsAccount(clientID, savingsProductID, startDate);
|
||||||
ACCOUNT_TYPE_INDIVIDUAL, startDate);
|
|
||||||
assertNotNull(savingsId);
|
|
||||||
HashMap savingsStatusHashMap = this.savingsAccountHelper.approveSavingsOnDate(savingsId, startDate);
|
|
||||||
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
|
||||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavingsAccount(savingsId, startDate);
|
|
||||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
|
||||||
return savingsId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer createSavingsProductDailyPosting() {
|
private Integer createSavingsProductDailyPosting() {
|
||||||
@@ -382,28 +374,31 @@ public class SavingsAccountTransactionTest {
|
|||||||
final List<BatchResponse> responses = enclosingTransaction
|
final List<BatchResponse> responses = enclosingTransaction
|
||||||
? BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json)
|
? BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json)
|
||||||
: BatchHelper.postBatchRequestsWithoutEnclosingTransaction(requestSpec, responseSpec, json);
|
: BatchHelper.postBatchRequestsWithoutEnclosingTransaction(requestSpec, responseSpec, json);
|
||||||
assertNotNull(responses);
|
assertNotNull(responses, "Responses");
|
||||||
if (enclosingTransaction) {
|
if (enclosingTransaction) {
|
||||||
Integer statusCode1 = responses.get(0).getStatusCode();
|
Integer statusCode1 = responses.get(0).getStatusCode();
|
||||||
assertNotNull(statusCode1);
|
assertNotNull(statusCode1, "First enlosingTransaction response status code");
|
||||||
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1, "Status code: " + statusCode1);
|
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1, "Status code: " + statusCode1);
|
||||||
if (SC_OK == statusCode1) {
|
if (SC_OK == statusCode1) {
|
||||||
assertEquals(4, responses.size());
|
assertEquals(4, responses.size(), "Response size for enlosingTransaction OK response");
|
||||||
Integer statusCode4 = responses.get(3).getStatusCode();
|
Integer statusCode4 = responses.get(3).getStatusCode();
|
||||||
assertNotNull(statusCode4);
|
assertNotNull(statusCode4, "Last enlosingTransaction OK response status code");
|
||||||
assertEquals(SC_OK, statusCode4);
|
assertEquals(SC_OK, statusCode4, "Last enlosingTransaction OK response status code");
|
||||||
} else {
|
} else {
|
||||||
assertEquals(1, responses.size());
|
assertEquals(1, responses.size(), "Response size for enlosingTransaction failed response");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assertEquals(4, responses.size());
|
assertEquals(4, responses.size(), "Response size for without-enlosingTransaction response");
|
||||||
Integer statusCode1 = responses.get(0).getStatusCode();
|
Integer statusCode1 = responses.get(0).getStatusCode();
|
||||||
assertNotNull(statusCode1);
|
assertNotNull(statusCode1, "First without-enlosingTransaction response status code");
|
||||||
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1, "Status code: " + statusCode1);
|
assertTrue(SC_OK == statusCode1 || SC_CONFLICT == statusCode1,
|
||||||
|
"First without-enlosingTransaction response status code: " + statusCode1);
|
||||||
Integer statusCode4 = responses.get(3).getStatusCode();
|
Integer statusCode4 = responses.get(3).getStatusCode();
|
||||||
assertNotNull(statusCode4);
|
assertNotNull(statusCode4, "Last without-enlosingTransaction response status code");
|
||||||
assertTrue(SC_OK == statusCode1 ? (SC_OK == statusCode4 || SC_CONFLICT == statusCode4)
|
assertTrue(
|
||||||
: (SC_FORBIDDEN == statusCode4 || SC_CONFLICT == statusCode4), "Status code: " + statusCode4);
|
SC_OK == statusCode1 ? (SC_OK == statusCode4 || SC_CONFLICT == statusCode4)
|
||||||
|
: (SC_FORBIDDEN == statusCode4 || SC_CONFLICT == statusCode4),
|
||||||
|
"Last without-enlosingTransaction response status code: " + statusCode4);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String json = transactionData.getJson();
|
String json = transactionData.getJson();
|
||||||
@@ -417,14 +412,14 @@ public class SavingsAccountTransactionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkConcurrentResponse(String response) {
|
private static boolean checkConcurrentResponse(String response) {
|
||||||
assertNotNull(response);
|
assertNotNull(response, "Single response");
|
||||||
JsonPath res = JsonPath.from(response);
|
JsonPath res = JsonPath.from(response);
|
||||||
String statusCode = res.get("httpStatusCode");
|
String statusCode = res.get("httpStatusCode");
|
||||||
if (statusCode == null) {
|
if (statusCode == null) {
|
||||||
assertNotNull(res.get(CommonConstants.RESPONSE_RESOURCE_ID));
|
assertNotNull(res.get(RESPONSE_RESOURCE_ID), "Single response " + RESPONSE_RESOURCE_ID);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
assertEquals(String.valueOf(SC_CONFLICT), statusCode);
|
assertEquals(String.valueOf(SC_CONFLICT), statusCode, "Single response status code");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,22 +434,22 @@ public class SavingsAccountTransactionTest {
|
|||||||
RequestSpecification requestSpec = savingsHelper.getRequestSpec();
|
RequestSpecification requestSpec = savingsHelper.getRequestSpec();
|
||||||
ResponseSpecification responseSpec = savingsHelper.getResponseSpec();
|
ResponseSpecification responseSpec = savingsHelper.getResponseSpec();
|
||||||
final List<BatchResponse> responses = BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json);
|
final List<BatchResponse> responses = BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, json);
|
||||||
assertNotNull(responses);
|
assertNotNull(responses, "Responses");
|
||||||
BatchResponse response1 = responses.get(0);
|
BatchResponse response1 = responses.get(0);
|
||||||
Integer statusCode = response1.getStatusCode();
|
Integer statusCode = response1.getStatusCode();
|
||||||
String msg = Strings.nullToEmpty(response1.getBody());
|
String msg = Strings.nullToEmpty(response1.getBody());
|
||||||
assertNotNull(statusCode);
|
assertNotNull(statusCode, "First response status code");
|
||||||
assertTrue(
|
assertTrue(
|
||||||
SC_OK == statusCode || SC_CONFLICT == statusCode
|
SC_OK == statusCode || SC_CONFLICT == statusCode
|
||||||
|| (SC_FORBIDDEN == statusCode && msg.contains("Cannot add or update a child row")),
|
|| (SC_FORBIDDEN == statusCode && msg.contains("Cannot add or update a child row")),
|
||||||
"Status code: " + statusCode + ", message: " + msg);
|
"Status code: " + statusCode + ", message: " + msg);
|
||||||
if (SC_OK == statusCode) {
|
if (SC_OK == statusCode) {
|
||||||
assertEquals(4, responses.size());
|
assertEquals(4, responses.size(), "Response size for OK response");
|
||||||
Integer statusCode4 = responses.get(3).getStatusCode();
|
Integer statusCode4 = responses.get(3).getStatusCode();
|
||||||
assertNotNull(statusCode4);
|
assertNotNull(statusCode4, "Last OK response status code");
|
||||||
assertEquals(SC_OK, statusCode4);
|
assertEquals(SC_OK, statusCode4, "Last OK response status code");
|
||||||
} else {
|
} else {
|
||||||
assertEquals(1, responses.size());
|
assertEquals(1, responses.size(), "Response size for failed response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -27,6 +28,7 @@ import java.util.Comparator;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -38,13 +40,15 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
public class AuditHelper {
|
public class AuditHelper {
|
||||||
|
|
||||||
private ResponseSpecification responseSpec;
|
|
||||||
private RequestSpecification requestSpec;
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(AuditHelper.class);
|
private static final Logger LOG = LoggerFactory.getLogger(AuditHelper.class);
|
||||||
private static final String AUDIT_BASE_URL = "/fineract-provider/api/v1/audits?" + Utils.TENANT_IDENTIFIER;
|
private static final String AUDIT_BASE_URL = "/fineract-provider/api/v1/audits?" + Utils.TENANT_IDENTIFIER;
|
||||||
private static final String AUDITSEARCH_BASE_URL = "/fineract-provider/api/v1/audits/searchtemplate?" + Utils.TENANT_IDENTIFIER;
|
private static final String AUDITSEARCH_BASE_URL = "/fineract-provider/api/v1/audits/searchtemplate?" + Utils.TENANT_IDENTIFIER;
|
||||||
|
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
|
private ResponseSpecification responseSpec;
|
||||||
|
private RequestSpecification requestSpec;
|
||||||
|
|
||||||
public AuditHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
|
public AuditHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
|
||||||
this.requestSpec = requestSpec;
|
this.requestSpec = requestSpec;
|
||||||
this.responseSpec = responseSpec;
|
this.responseSpec = responseSpec;
|
||||||
|
|||||||
+10
-3
@@ -119,8 +119,8 @@ public class GlobalConfigurationHelper {
|
|||||||
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
|
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
|
||||||
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
|
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
|
||||||
|
|
||||||
Assertions.assertEquals(52, expectedGlobalConfigurations.size());
|
Assertions.assertEquals(53, expectedGlobalConfigurations.size());
|
||||||
Assertions.assertEquals(52, actualGlobalConfigurations.size());
|
Assertions.assertEquals(53, actualGlobalConfigurations.size());
|
||||||
|
|
||||||
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
|
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
|
||||||
|
|
||||||
@@ -571,9 +571,16 @@ public class GlobalConfigurationHelper {
|
|||||||
assetExternalizationOfNonActiveLoans.put("value", 0);
|
assetExternalizationOfNonActiveLoans.put("value", 0);
|
||||||
assetExternalizationOfNonActiveLoans.put("enabled", true);
|
assetExternalizationOfNonActiveLoans.put("enabled", true);
|
||||||
assetExternalizationOfNonActiveLoans.put("trapDoor", false);
|
assetExternalizationOfNonActiveLoans.put("trapDoor", false);
|
||||||
assetExternalizationOfNonActiveLoans.put("string_value", "due-date");
|
|
||||||
defaults.add(assetExternalizationOfNonActiveLoans);
|
defaults.add(assetExternalizationOfNonActiveLoans);
|
||||||
|
|
||||||
|
HashMap<String, Object> enableSameMakerChecker = new HashMap<>();
|
||||||
|
enableSameMakerChecker.put("id", 58);
|
||||||
|
enableSameMakerChecker.put("name", "enable-same-maker-checker");
|
||||||
|
enableSameMakerChecker.put("value", 0);
|
||||||
|
enableSameMakerChecker.put("enabled", false);
|
||||||
|
enableSameMakerChecker.put("trapDoor", false);
|
||||||
|
defaults.add(enableSameMakerChecker);
|
||||||
|
|
||||||
return defaults;
|
return defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-6
@@ -23,8 +23,9 @@ import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
|
|||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import org.apache.fineract.client.models.GetMakerCheckerResponse;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.fineract.client.util.JSON;
|
import org.apache.fineract.client.util.JSON;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ public class MakercheckersHelper {
|
|||||||
|
|
||||||
private static final Gson GSON = new JSON().getGson();
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
private static final String MAKERCHECKER_URL = "/fineract-provider/api/v1/makercheckers?" + Utils.TENANT_IDENTIFIER;
|
private static final String MAKERCHECKER_URL = "/fineract-provider/api/v1/makercheckers";
|
||||||
|
|
||||||
private final RequestSpecification requestSpec;
|
private final RequestSpecification requestSpec;
|
||||||
private final ResponseSpecification responseSpec;
|
private final ResponseSpecification responseSpec;
|
||||||
@@ -42,10 +43,25 @@ public class MakercheckersHelper {
|
|||||||
this.responseSpec = responseSpec;
|
this.responseSpec = responseSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<GetMakerCheckerResponse> getMakerCheckerList() {
|
public List<Map<String, Object>> getMakerCheckerList(Map<String, String> queryParams) {
|
||||||
final String response = Utils.performServerGet(this.requestSpec, this.responseSpec, MAKERCHECKER_URL);
|
StringBuilder url = new StringBuilder(MAKERCHECKER_URL).append("?").append(Utils.TENANT_IDENTIFIER);
|
||||||
Type makerCheckerList = new TypeToken<ArrayList<GetMakerCheckerResponse>>() {}.getType();
|
if (queryParams != null) {
|
||||||
|
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
|
||||||
|
url.append("&").append(entry.getKey()).append("=").append(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final String response = Utils.performServerGet(this.requestSpec, this.responseSpec, url.toString());
|
||||||
|
Type makerCheckerList = new TypeToken<List<Map<String, Object>>>() {}.getType();
|
||||||
return GSON.fromJson(response, makerCheckerList);
|
return GSON.fromJson(response, makerCheckerList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void approveMakerCheckerEntry(Long auditId) {
|
||||||
|
approveMakerCheckerEntry(this.requestSpec, this.responseSpec, auditId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HashMap<?, ?> approveMakerCheckerEntry(RequestSpecification requestSpec, ResponseSpecification responseSpec,
|
||||||
|
Long auditId) {
|
||||||
|
String url = MAKERCHECKER_URL + "/" + auditId + "?command=approve&" + Utils.TENANT_IDENTIFIER;
|
||||||
|
return Utils.performServerPost(requestSpec, responseSpec, url, "", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common.savings;
|
|||||||
|
|
||||||
import static org.apache.fineract.integrationtests.common.Utils.DEFAULT_TENANT;
|
import static org.apache.fineract.integrationtests.common.Utils.DEFAULT_TENANT;
|
||||||
import static org.apache.fineract.integrationtests.common.Utils.TENANT_PARAM_NAME;
|
import static org.apache.fineract.integrationtests.common.Utils.TENANT_PARAM_NAME;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -174,6 +175,16 @@ public class SavingsAccountHelper extends IntegrationTest {
|
|||||||
savingsApplicationJSON, responseAttribute);
|
savingsApplicationJSON, responseAttribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer createApproveActivateSavingsAccount(final Integer clientId, Integer savingsProductId, final String startDate) {
|
||||||
|
final Integer savingsId = applyForSavingsApplicationOnDate(clientId, savingsProductId, ACCOUNT_TYPE_INDIVIDUAL, startDate);
|
||||||
|
assertNotNull(savingsId);
|
||||||
|
HashMap savingsStatusHashMap = approveSavingsOnDate(savingsId, startDate);
|
||||||
|
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
||||||
|
savingsStatusHashMap = activateSavingsAccount(savingsId, startDate);
|
||||||
|
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||||
|
return savingsId;
|
||||||
|
}
|
||||||
|
|
||||||
public HashMap updateSavingsAccount(final Integer id, final Integer savingsProductID, final Integer savingsId,
|
public HashMap updateSavingsAccount(final Integer id, final Integer savingsProductID, final Integer savingsId,
|
||||||
final String accountType) {
|
final String accountType) {
|
||||||
final String savingsApplicationJSON = new SavingsApplicationTestBuilder() //
|
final String savingsApplicationJSON = new SavingsApplicationTestBuilder() //
|
||||||
|
|||||||
+29
-6
@@ -19,24 +19,36 @@
|
|||||||
package org.apache.fineract.integrationtests.useradministration.roles;
|
package org.apache.fineract.integrationtests.useradministration.roles;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
import io.restassured.specification.RequestSpecification;
|
import io.restassured.specification.RequestSpecification;
|
||||||
import io.restassured.specification.ResponseSpecification;
|
import io.restassured.specification.ResponseSpecification;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.fineract.client.models.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.client.models.PutPermissionsRequest;
|
||||||
|
import org.apache.fineract.client.util.JSON;
|
||||||
|
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||||
import org.apache.fineract.integrationtests.common.Utils;
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
|
import org.apache.fineract.useradministration.data.PermissionData;
|
||||||
|
|
||||||
public final class RolesHelper {
|
public final class RolesHelper extends IntegrationTest {
|
||||||
|
|
||||||
public static final long SUPER_USER_ROLE_ID = 1L; // This is hardcoded into the initial Liquibase migration
|
public static final long SUPER_USER_ROLE_ID = 1L; // This is hardcoded into the initial Liquibase migration
|
||||||
|
|
||||||
private RolesHelper() {
|
public RolesHelper() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String CREATE_ROLE_URL = "/fineract-provider/api/v1/roles?" + Utils.TENANT_IDENTIFIER;
|
private static final String CREATE_ROLE_URL = "/fineract-provider/api/v1/roles?" + Utils.TENANT_IDENTIFIER;
|
||||||
private static final String ROLE_URL = "/fineract-provider/api/v1/roles";
|
private static final String ROLE_URL = "/fineract-provider/api/v1/roles";
|
||||||
|
private static final String PERMISSIONS_URL = "/fineract-provider/api/v1/permissions";
|
||||||
private static final String DISABLE_ROLE_COMMAND = "disable";
|
private static final String DISABLE_ROLE_COMMAND = "disable";
|
||||||
private static final String ENABLE_ROLE_COMMAND = "enable";
|
private static final String ENABLE_ROLE_COMMAND = "enable";
|
||||||
|
|
||||||
|
private static final Gson GSON = new JSON().getGson();
|
||||||
|
|
||||||
public static Integer createRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
|
public static Integer createRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
|
||||||
return Utils.performServerPost(requestSpec, responseSpec, CREATE_ROLE_URL, getTestCreateRoleAsJSON(), "resourceId");
|
return Utils.performServerPost(requestSpec, responseSpec, CREATE_ROLE_URL, getTestCreateRoleAsJSON(), "resourceId");
|
||||||
}
|
}
|
||||||
@@ -70,13 +82,25 @@ public final class RolesHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String addPermissionsToRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
public static String addPermissionsToRole(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||||
final Integer roleId, final HashMap<String, Boolean> permissionMap) {
|
final Integer roleId, final Map<String, Boolean> permissionMap) {
|
||||||
return Utils.performServerPut(requestSpec, responseSpec, ROLE_URL + "/" + roleId + "/permissions?" + Utils.TENANT_IDENTIFIER,
|
return Utils.performServerPut(requestSpec, responseSpec, ROLE_URL + "/" + roleId + "/permissions?" + Utils.TENANT_IDENTIFIER,
|
||||||
getAddPermissionsToRoleJSON(permissionMap));
|
getAddPermissionsToRoleJSON(permissionMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getAddPermissionsToRoleJSON(HashMap<String, Boolean> permissionMap) {
|
public static List<PermissionData> getPermissions(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||||
final HashMap<String, HashMap<String, Boolean>> map = new HashMap<>();
|
boolean makerCheckerable) {
|
||||||
|
String response = Utils.performServerGet(requestSpec, responseSpec,
|
||||||
|
PERMISSIONS_URL + "?" + makerCheckerable + "=" + makerCheckerable);
|
||||||
|
final Type listType = new TypeToken<List<PermissionData>>() {}.getType();
|
||||||
|
return GSON.fromJson(response, listType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandProcessingResult updatePermissions(PutPermissionsRequest request) {
|
||||||
|
return ok(fineract().permissions.updatePermissionsDetails(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getAddPermissionsToRoleJSON(Map<String, Boolean> permissionMap) {
|
||||||
|
final HashMap<String, Map<String, Boolean>> map = new HashMap<>();
|
||||||
map.put("permissions", permissionMap);
|
map.put("permissions", permissionMap);
|
||||||
return new Gson().toJson(map);
|
return new Gson().toJson(map);
|
||||||
}
|
}
|
||||||
@@ -84,5 +108,4 @@ public final class RolesHelper {
|
|||||||
private static String createRoleOperationURL(final String command, final Integer roleId) {
|
private static String createRoleOperationURL(final String command, final Integer roleId) {
|
||||||
return ROLE_URL + "/" + roleId + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
|
return ROLE_URL + "/" + roleId + "?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user