feat: implement maker-checker for product creation, add app user preferences, and introduce base interest rate management services.
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
This commit is contained in:
+11
-6
@@ -29,6 +29,10 @@ import jakarta.ws.rs.core.MediaType;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
@@ -42,6 +46,7 @@ public class FixedDepositProductsBaseInterestRatesApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final FdBaseInterestRateReadPlatformService fdBaseInterestRateReadPlatformService;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(LocalDate.class,
|
||||
(JsonSerializer<LocalDate>) (src, typeOfSrc, ctx) -> new JsonPrimitive(src.toString()))
|
||||
@@ -77,11 +82,11 @@ public class FixedDepositProductsBaseInterestRatesApiResource {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Save new FD base interest rate version", description = "Creates a new FD CBS base chart version for the given fdType and deactivates the previous active version.")
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String saveInterestRates(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final FdInterestRateSaveRequest request = gson.fromJson(apiRequestBodyAsJson, FdInterestRateSaveRequest.class);
|
||||
final Long createdById = this.context.authenticatedUser().getId();
|
||||
final FdInterestRateEffectiveData saved = this.fdBaseInterestRateReadPlatformService.saveInterestRates(request, createdById);
|
||||
return gson.toJson(saved);
|
||||
public CommandProcessingResult saveInterestRates(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder()
|
||||
.createCbsBaseInterestRate()
|
||||
.withJson(apiRequestBodyAsJson)
|
||||
.build();
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "CBSBASEINTERESTRATE", action = "CREATE")
|
||||
@RequiredArgsConstructor
|
||||
public class CreateCbsBaseInterestRateCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final FdBaseInterestRateWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.saveInterestRates(command);
|
||||
}
|
||||
}
|
||||
+128
-1
@@ -11,10 +11,16 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateSlabData;
|
||||
@@ -51,7 +57,9 @@ public class FdBaseInterestRateReadPlatformServiceImpl implements FdBaseInterest
|
||||
@Override
|
||||
@Transactional
|
||||
public FdInterestRateEffectiveData saveInterestRates(FdInterestRateSaveRequest request, Long createdById) {
|
||||
final String fdType = request.getFdType();
|
||||
validateRequest(request);
|
||||
|
||||
final String fdType = request.getFdType().toUpperCase();
|
||||
final LocalDate today = LocalDate.now(DateUtils.getDateTimeZoneOfTenant());
|
||||
|
||||
final List<FdBaseInterestRateEffective> activeVersions = effectiveRepository
|
||||
@@ -85,6 +93,125 @@ public class FdBaseInterestRateReadPlatformServiceImpl implements FdBaseInterest
|
||||
return toData(newVersion);
|
||||
}
|
||||
|
||||
private void validateRequest(final FdInterestRateSaveRequest request) {
|
||||
final List<ApiParameterError> errors = new ArrayList<>();
|
||||
final DataValidatorBuilder validator = new DataValidatorBuilder(errors).resource("FD_BASE_INTEREST_RATE_VERSION");
|
||||
|
||||
if (request == null) {
|
||||
validator.failWithCodeNoParameterAddedToErrorCode("request.cannot.be.null");
|
||||
throwExceptionIfValidationWarningsExist(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
final String fdType = request.getFdType();
|
||||
if (fdType == null || fdType.isBlank()) {
|
||||
validator.parameter("fdType").failWithCode("cannot.be.blank");
|
||||
} else if (!List.of("SINGLE", "DOUBLE", "SPECIAL").contains(fdType.toUpperCase())) {
|
||||
validator.parameter("fdType").value(fdType).failWithCode("invalid.fd.type");
|
||||
}
|
||||
|
||||
if (request.getSlabs() == null || request.getSlabs().isEmpty()) {
|
||||
validator.parameter("slabs").failWithCode("cannot.be.blank");
|
||||
}
|
||||
|
||||
if (request.getVersionLabel() != null && request.getVersionLabel().length() > 100) {
|
||||
validator.parameter("versionLabel").value(request.getVersionLabel()).failWithCode("exceeds.max.length");
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(errors);
|
||||
validateSlabs(request.getSlabs());
|
||||
}
|
||||
|
||||
private void validateSlabs(final List<FdInterestRateSaveRequest.SlabRequest> slabs) {
|
||||
final List<ApiParameterError> errors = new ArrayList<>();
|
||||
final DataValidatorBuilder validator = new DataValidatorBuilder(errors).resource("FD_BASE_INTEREST_RATE_VERSION");
|
||||
|
||||
if (slabs == null || slabs.isEmpty()) {
|
||||
validator.parameter("slabs").failWithCode("cannot.be.blank");
|
||||
throwExceptionIfValidationWarningsExist(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<FdInterestRateSaveRequest.SlabRequest> sorted = new ArrayList<>(slabs);
|
||||
sorted.sort(Comparator.comparing((FdInterestRateSaveRequest.SlabRequest slab) -> slab.getSrNo() == null ? Integer.MAX_VALUE : slab.getSrNo())
|
||||
.thenComparing(slab -> slab.getFromPeriod() == null ? Integer.MAX_VALUE : slab.getFromPeriod()));
|
||||
|
||||
final Integer expectedPeriodType = sorted.get(0).getPeriodTypeEnum();
|
||||
Integer expectedFrom = 1;
|
||||
|
||||
for (int i = 0; i < sorted.size(); i++) {
|
||||
final FdInterestRateSaveRequest.SlabRequest slab = sorted.get(i);
|
||||
final int srNo = slab.getSrNo() == null ? i + 1 : slab.getSrNo();
|
||||
final String slabPrefix = "slabs[" + srNo + "].";
|
||||
|
||||
if (slab.getPeriodTypeEnum() == null) {
|
||||
validator.parameter(slabPrefix + "periodTypeEnum").failWithCode("cannot.be.blank");
|
||||
} else if (!slab.getPeriodTypeEnum().equals(expectedPeriodType)) {
|
||||
validator.parameter(slabPrefix + "periodTypeEnum").value(slab.getPeriodTypeEnum())
|
||||
.failWithCode("must.be.consistent.across.all.slabs");
|
||||
}
|
||||
|
||||
final Integer fromPeriod = slab.getFromPeriod();
|
||||
if (fromPeriod == null) {
|
||||
validator.parameter(slabPrefix + "fromPeriod").failWithCode("cannot.be.blank");
|
||||
} else if (fromPeriod < 0) {
|
||||
validator.parameter(slabPrefix + "fromPeriod").value(fromPeriod).failWithCode("must.be.non.negative");
|
||||
} else if (!fromPeriod.equals(expectedFrom)) {
|
||||
if (i == 0) {
|
||||
validator.parameter(slabPrefix + "fromPeriod").value(fromPeriod).failWithCode("first.slab.must.start.at.one");
|
||||
} else if (fromPeriod < expectedFrom) {
|
||||
validator.parameter(slabPrefix + "fromPeriod").value(fromPeriod).failWithCode("must.not.overlap.previous.range");
|
||||
} else {
|
||||
validator.parameter(slabPrefix + "fromPeriod").value(fromPeriod).failWithCode("must.be.continuous.with.previous.range");
|
||||
}
|
||||
}
|
||||
|
||||
final Integer toPeriod = slab.getToPeriod();
|
||||
if (i < sorted.size() - 1) {
|
||||
if (toPeriod == null) {
|
||||
validator.parameter(slabPrefix + "toPeriod").failWithCode("cannot.be.blank.for.intermediate.slab");
|
||||
} else {
|
||||
if (toPeriod < 0) {
|
||||
validator.parameter(slabPrefix + "toPeriod").value(toPeriod).failWithCode("must.be.non.negative");
|
||||
}
|
||||
if (fromPeriod != null && toPeriod < fromPeriod) {
|
||||
validator.parameter(slabPrefix + "toPeriod").value(toPeriod).failWithCode("cannot.be.less.than.fromPeriod");
|
||||
}
|
||||
expectedFrom = toPeriod + 1;
|
||||
}
|
||||
} else {
|
||||
if (toPeriod != null) {
|
||||
if (toPeriod < 0) {
|
||||
validator.parameter(slabPrefix + "toPeriod").value(toPeriod).failWithCode("must.be.non.negative");
|
||||
}
|
||||
if (fromPeriod != null && toPeriod < fromPeriod) {
|
||||
validator.parameter(slabPrefix + "toPeriod").value(toPeriod).failWithCode("cannot.be.less.than.fromPeriod");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final BigDecimal annualRate = slab.getAnnualInterestRate();
|
||||
if (annualRate == null) {
|
||||
validator.parameter(slabPrefix + "annualInterestRate").failWithCode("cannot.be.blank");
|
||||
} else if (annualRate.compareTo(BigDecimal.ZERO) < 0) {
|
||||
validator.parameter(slabPrefix + "annualInterestRate").value(annualRate).failWithCode("must.be.non.negative");
|
||||
}
|
||||
|
||||
final BigDecimal seniorRate = slab.getSeniorCitizenRate();
|
||||
if (seniorRate != null && seniorRate.compareTo(BigDecimal.ZERO) < 0) {
|
||||
validator.parameter(slabPrefix + "seniorCitizenRate").value(seniorRate).failWithCode("must.be.non.negative");
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(errors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private FdInterestRateEffectiveData toData(FdBaseInterestRateEffective e) {
|
||||
List<FdInterestRateSlabData> slabs = slabRepository.findByEffectiveIdOrderBySrNo(e.getId()).stream()
|
||||
.map(s -> FdInterestRateSlabData.builder()
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface FdBaseInterestRateWritePlatformService {
|
||||
|
||||
CommandProcessingResult saveInterestRates(JsonCommand command);
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FdBaseInterestRateWritePlatformServiceImpl implements FdBaseInterestRateWritePlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final FdBaseInterestRateReadPlatformService readPlatformService;
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult saveInterestRates(final JsonCommand command) {
|
||||
final FdInterestRateSaveRequest request = gson.fromJson(command.json(), FdInterestRateSaveRequest.class);
|
||||
final Long createdById = this.context.authenticatedUser().getId();
|
||||
final FdInterestRateEffectiveData saved = this.readPlatformService.saveInterestRates(request, createdById);
|
||||
return new CommandProcessingResultBuilder()
|
||||
.withCommandId(command.commandId())
|
||||
.withEntityId(saved.getId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+10
@@ -169,6 +169,8 @@ import org.apache.fineract.portfolio.savings.service.RdBaseInterestRateReadPlatf
|
||||
import org.apache.fineract.portfolio.savings.service.RdBaseInterestRateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateWritePlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPoster;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPosterTask;
|
||||
import org.apache.fineract.portfolio.savings.service.search.SavingsAccountTransactionSearchService;
|
||||
@@ -200,6 +202,14 @@ public class SavingsConfiguration {
|
||||
return new FdBaseInterestRateReadPlatformServiceImpl(effectiveRepository, slabRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(FdBaseInterestRateWritePlatformService.class)
|
||||
public FdBaseInterestRateWritePlatformService fdBaseInterestRateWritePlatformService(
|
||||
PlatformSecurityContext context,
|
||||
FdBaseInterestRateReadPlatformService readPlatformService) {
|
||||
return new FdBaseInterestRateWritePlatformServiceImpl(context, readPlatformService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SavingsAccountTransactionSearchService.class)
|
||||
public SavingsAccountTransactionSearchService savingsAccountTransactionSearchService(PlatformSecurityContext context,
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package org.apache.fineract.useradministration.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.useradministration.data.AppUserPreferenceData;
|
||||
import org.apache.fineract.useradministration.service.AppUserPreferenceReadPlatformService;
|
||||
import org.apache.fineract.useradministration.service.AppUserPreferenceWritePlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/users/{userId}/preferences")
|
||||
@Component
|
||||
@Tag(name = "User Preferences", description = "API to manage user specific preferences.")
|
||||
@RequiredArgsConstructor
|
||||
public class AppUserPreferencesApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final AppUserPreferenceReadPlatformService readPlatformService;
|
||||
private final AppUserPreferenceWritePlatformService writePlatformService;
|
||||
|
||||
private void validateUserAuthorization(Long userId) {
|
||||
if (!context.authenticatedUser().getId().equals(userId)) {
|
||||
throw new NoAuthorizationException("Not authorized to access or modify preferences for another user.");
|
||||
}
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{preferenceName}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve user preference", description = "Retrieves a specific preference for the user.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = AppUserPreferenceData.class))) })
|
||||
public AppUserPreferenceData getPreference(@PathParam("userId") @Parameter(description = "userId") final Long userId,
|
||||
@PathParam("preferenceName") @Parameter(description = "preferenceName") final String preferenceName) {
|
||||
|
||||
validateUserAuthorization(userId);
|
||||
String value = readPlatformService.getPreferenceValue(userId, preferenceName);
|
||||
return new AppUserPreferenceData(preferenceName, value);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{preferenceName}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update user preference", description = "Updates or creates a specific preference for the user.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = AppUserPreferenceData.class)))
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public AppUserPreferenceData updatePreference(@PathParam("userId") @Parameter(description = "userId") final Long userId,
|
||||
@PathParam("preferenceName") @Parameter(description = "preferenceName") final String preferenceName,
|
||||
final AppUserPreferenceData preferenceData) {
|
||||
|
||||
validateUserAuthorization(userId);
|
||||
|
||||
// Ensure the path parameter matches the request body if the request body contains a name
|
||||
String valueToSave = preferenceData != null ? preferenceData.getValue() : null;
|
||||
if (valueToSave == null) {
|
||||
throw new IllegalArgumentException("Preference value cannot be null");
|
||||
}
|
||||
|
||||
writePlatformService.updatePreference(userId, preferenceName, valueToSave);
|
||||
return new AppUserPreferenceData(preferenceName, valueToSave);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package org.apache.fineract.useradministration.data;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AppUserPreferenceData {
|
||||
private String name;
|
||||
private String value;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package org.apache.fineract.useradministration.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_appuser_preference")
|
||||
public class AppUserPreference extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "appuser_id", nullable = false)
|
||||
private AppUser appUser;
|
||||
|
||||
@Column(name = "name", length = 100, nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(name = "value", nullable = false)
|
||||
private String value;
|
||||
|
||||
protected AppUserPreference() {
|
||||
//
|
||||
}
|
||||
|
||||
private AppUserPreference(final AppUser appUser, final String name, final String value) {
|
||||
this.appUser = appUser;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static AppUserPreference create(final AppUser appUser, final String name, final String value) {
|
||||
return new AppUserPreference(appUser, name, value);
|
||||
}
|
||||
|
||||
public void updateValue(final String newValue) {
|
||||
this.value = newValue;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public AppUser getAppUser() {
|
||||
return this.appUser;
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.apache.fineract.useradministration.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface AppUserPreferenceRepository extends JpaRepository<AppUserPreference, Long> {
|
||||
|
||||
Optional<AppUserPreference> findByAppUserIdAndName(Long appUserId, String name);
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.apache.fineract.useradministration.service;
|
||||
|
||||
public interface AppUserPreferenceReadPlatformService {
|
||||
String getPreferenceValue(Long appUserId, String name);
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.apache.fineract.useradministration.service;
|
||||
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.useradministration.domain.AppUserPreference;
|
||||
import org.apache.fineract.useradministration.domain.AppUserPreferenceRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AppUserPreferenceReadPlatformServiceImpl implements AppUserPreferenceReadPlatformService {
|
||||
|
||||
private final AppUserPreferenceRepository appUserPreferenceRepository;
|
||||
|
||||
@Override
|
||||
public String getPreferenceValue(Long appUserId, String name) {
|
||||
Optional<AppUserPreference> pref = appUserPreferenceRepository.findByAppUserIdAndName(appUserId, name);
|
||||
return pref.map(AppUserPreference::getValue).orElse(null);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.apache.fineract.useradministration.service;
|
||||
|
||||
public interface AppUserPreferenceWritePlatformService {
|
||||
void updatePreference(Long appUserId, String name, String value);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.apache.fineract.useradministration.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.apache.fineract.useradministration.domain.AppUserPreference;
|
||||
import org.apache.fineract.useradministration.domain.AppUserPreferenceRepository;
|
||||
import org.apache.fineract.useradministration.domain.AppUserRepository;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AppUserPreferenceWritePlatformServiceImpl implements AppUserPreferenceWritePlatformService {
|
||||
|
||||
private final AppUserPreferenceRepository appUserPreferenceRepository;
|
||||
private final AppUserRepository appUserRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updatePreference(Long appUserId, String name, String value) {
|
||||
AppUserPreference preference = appUserPreferenceRepository.findByAppUserIdAndName(appUserId, name).orElse(null);
|
||||
if (preference == null) {
|
||||
AppUser appUser = appUserRepository.findById(appUserId)
|
||||
.orElseThrow(() -> new PlatformDataIntegrityException("error.msg.user.id.invalid", "User not found"));
|
||||
preference = AppUserPreference.create(appUser, name, value);
|
||||
} else {
|
||||
preference.updateValue(value);
|
||||
}
|
||||
appUserPreferenceRepository.saveAndFlush(preference);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ fineract.security.oauth2.client.registrations.frontend-client.require-authorizat
|
||||
fineract.tenant.host=${FINERACT_DEFAULT_TENANTDB_HOSTNAME:localhost}
|
||||
fineract.tenant.port=${FINERACT_DEFAULT_TENANTDB_PORT:5432}
|
||||
fineract.tenant.username=${FINERACT_DEFAULT_TENANTDB_UID:postgres}
|
||||
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:313863}
|
||||
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:anshul@9009}
|
||||
fineract.tenant.parameters=${FINERACT_DEFAULT_TENANTDB_CONN_PARAMS:}
|
||||
fineract.tenant.timezone=${FINERACT_DEFAULT_TENANTDB_TIMEZONE:Asia/Kolkata}
|
||||
fineract.tenant.identifier=${FINERACT_DEFAULT_TENANTDB_IDENTIFIER:default}
|
||||
@@ -407,7 +407,7 @@ server.tomcat.mbeanregistry.enabled=${FINERACT_SERVER_TOMCAT_MBEANREGISTRY_ENABL
|
||||
spring.datasource.hikari.driverClassName=${FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME:org.postgresql.Driver}
|
||||
spring.datasource.hikari.jdbcUrl=${FINERACT_HIKARI_JDBC_URL:jdbc:postgresql://localhost:5432/fineract_tenants}
|
||||
spring.datasource.hikari.username=${FINERACT_HIKARI_USERNAME:postgres}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:313863}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:anshul@9009}
|
||||
spring.datasource.hikari.minimumIdle=${FINERACT_HIKARI_MINIMUM_IDLE:3}
|
||||
spring.datasource.hikari.maximumPoolSize=${FINERACT_HIKARI_MAXIMUM_POOL_SIZE:10}
|
||||
spring.datasource.hikari.idleTimeout=${FINERACT_HIKARI_IDLE_TIMEOUT:60000}
|
||||
|
||||
@@ -537,4 +537,10 @@
|
||||
<include file="parts/0467_add_welcome_kit_return_tracking.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0468_add_address_id_to_welcome_kit_dispatch.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0469_create_database_export_request.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0466_create_m_appuser_preference.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0467_enable_glaccount_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0470_enable_cbs_base_interest_rate_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0471_enable_charge_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0472_enable_product_creation_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0474_enable_fixed_deposit_product_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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.3.xsd">
|
||||
<changeSet id="0466_create_m_appuser_preference" author="fineract">
|
||||
<preConditions onFail="MARK_RAN"><not><tableExists tableName="m_appuser_preference"/></not></preConditions>
|
||||
<createTable tableName="m_appuser_preference">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="appuser_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="value" type="TEXT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="m_appuser_preference" baseColumnNames="appuser_id" constraintName="fk_m_appuser_preference_appuser_id" referencedTableName="m_appuser" referencedColumnNames="id"/>
|
||||
<addUniqueConstraint tableName="m_appuser_preference" columnNames="appuser_id, name" constraintName="uq_appuser_preference_name"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 id="0467_enable_glaccount_maker_checker" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="HALT">
|
||||
<sqlCheck expectedResult="3">
|
||||
SELECT COUNT(*)
|
||||
FROM m_permission
|
||||
WHERE entity_name = 'GLACCOUNT'
|
||||
AND action_name IN ('CREATE', 'UPDATE', 'DELETE')
|
||||
</sqlCheck>
|
||||
</preConditions>
|
||||
<sql>
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE entity_name = 'GLACCOUNT'
|
||||
AND action_name IN ('CREATE', 'UPDATE', 'DELETE');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+1
@@ -7,6 +7,7 @@
|
||||
address as verified or not verified once the outcome is known. Deliberately a plain column rather than
|
||||
a foreign key: the dispatch is a historical record and must survive the address being edited or removed. -->
|
||||
<changeSet id="0468_add_address_id_to_welcome_kit_dispatch" author="CBS" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<columnExists tableName="m_welcome_kit_dispatch" columnName="address_id"/>
|
||||
|
||||
+2
@@ -7,6 +7,7 @@
|
||||
person's authority. The requester states a reason, an admin approves or rejects, and only an approved
|
||||
request can produce a dump. Every step is stamped so the trail survives the file itself. -->
|
||||
<changeSet id="0469_create_database_export_request" author="CBS" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<createTable tableName="m_database_export_request">
|
||||
<column name="id" type="BIGSERIAL">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
@@ -50,6 +51,7 @@
|
||||
<!-- Requesting an export and approving one are deliberately separate permissions: the whole control
|
||||
depends on no single user holding both. -->
|
||||
<changeSet id="0469_database_export_permissions" author="CBS" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'authorisation', 'CREATE_DATABASEEXPORT', 'DATABASEEXPORT', 'CREATE', false
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 id="0470_cbs_base_interest_rate_maker_checker_permissions" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CBSBASEINTERESTRATE', 'CBSBASEINTERESTRATE', 'CREATE', true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CBSBASEINTERESTRATE');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CBSBASEINTERESTRATE_CHECKER', 'CBSBASEINTERESTRATE', 'CREATE_CHECKER', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CBSBASEINTERESTRATE_CHECKER');
|
||||
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE entity_name = 'CBSBASEINTERESTRATE'
|
||||
AND action_name = 'CREATE';
|
||||
|
||||
UPDATE m_permission
|
||||
SET action_name = 'CREATE_CHECKER'
|
||||
WHERE entity_name = 'CBSBASEINTERESTRATE'
|
||||
AND code = 'CREATE_CBSBASEINTERESTRATE_CHECKER';
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0470_grant_cbs_base_interest_rate_permissions_to_roles" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE r.name = 'Super user'
|
||||
AND p.code IN ('CREATE_CBSBASEINTERESTRATE', 'CREATE_CBSBASEINTERESTRATE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT ur.role_id, p.id
|
||||
FROM m_appuser u
|
||||
JOIN m_appuser_role ur ON ur.appuser_id = u.id
|
||||
CROSS JOIN m_permission p
|
||||
WHERE u.username = 'bankadmin'
|
||||
AND p.code IN ('CREATE_CBSBASEINTERESTRATE', 'CREATE_CBSBASEINTERESTRATE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = ur.role_id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE LOWER(r.name) = 'clerk'
|
||||
AND p.code IN ('CREATE_CBSBASEINTERESTRATE', 'CREATE_CBSBASEINTERESTRATE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 id="0471_enable_charge_maker_checker" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="HALT">
|
||||
<sqlCheck expectedResult="1">
|
||||
SELECT COUNT(*)
|
||||
FROM m_permission
|
||||
WHERE entity_name = 'CHARGE'
|
||||
AND action_name = 'CREATE'
|
||||
</sqlCheck>
|
||||
</preConditions>
|
||||
<sql>
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE entity_name = 'CHARGE'
|
||||
AND action_name = 'CREATE';
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0471_grant_charge_maker_checker_permissions_to_roles" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE r.name = 'Super user'
|
||||
AND p.code IN ('CREATE_CHARGE', 'CREATE_CHARGE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT ur.role_id, p.id
|
||||
FROM m_appuser u
|
||||
JOIN m_appuser_role ur ON ur.appuser_id = u.id
|
||||
CROSS JOIN m_permission p
|
||||
WHERE u.username = 'bankadmin'
|
||||
AND p.code IN ('CREATE_CHARGE', 'CREATE_CHARGE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = ur.role_id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE LOWER(r.name) = 'clerk'
|
||||
AND p.code IN ('CREATE_CHARGE', 'CREATE_CHARGE_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 id="0472_add_shareproduct_checker_permission_if_not_exists" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'SHAREPRODUCT', 'CREATE_SHAREPRODUCT_CHECKER', 'SHAREPRODUCT', 'CREATE_CHECKER', FALSE
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM m_permission WHERE code = 'CREATE_SHAREPRODUCT_CHECKER'
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0472_enable_product_creation_maker_checker" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="HALT">
|
||||
<sqlCheck expectedResult="4">
|
||||
SELECT COUNT(*)
|
||||
FROM m_permission
|
||||
WHERE code IN ('CREATE_LOANPRODUCT', 'CREATE_SAVINGSPRODUCT', 'CREATE_CURRENTPRODUCT', 'CREATE_SHAREPRODUCT')
|
||||
</sqlCheck>
|
||||
</preConditions>
|
||||
<sql>
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE code IN ('CREATE_LOANPRODUCT', 'CREATE_SAVINGSPRODUCT', 'CREATE_CURRENTPRODUCT', 'CREATE_SHAREPRODUCT');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0472_grant_product_creation_maker_checker_permissions_to_roles" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE r.name = 'Super user'
|
||||
AND p.code IN (
|
||||
'CREATE_LOANPRODUCT', 'CREATE_LOANPRODUCT_CHECKER',
|
||||
'CREATE_SAVINGSPRODUCT', 'CREATE_SAVINGSPRODUCT_CHECKER',
|
||||
'CREATE_CURRENTPRODUCT', 'CREATE_CURRENTPRODUCT_CHECKER',
|
||||
'CREATE_SHAREPRODUCT', 'CREATE_SHAREPRODUCT_CHECKER'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT ur.role_id, p.id
|
||||
FROM m_appuser u
|
||||
JOIN m_appuser_role ur ON ur.appuser_id = u.id
|
||||
CROSS JOIN m_permission p
|
||||
WHERE u.username = 'bankadmin'
|
||||
AND p.code IN (
|
||||
'CREATE_LOANPRODUCT', 'CREATE_LOANPRODUCT_CHECKER',
|
||||
'CREATE_SAVINGSPRODUCT', 'CREATE_SAVINGSPRODUCT_CHECKER',
|
||||
'CREATE_CURRENTPRODUCT', 'CREATE_CURRENTPRODUCT_CHECKER',
|
||||
'CREATE_SHAREPRODUCT', 'CREATE_SHAREPRODUCT_CHECKER'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = ur.role_id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE LOWER(r.name) = 'clerk'
|
||||
AND p.code IN (
|
||||
'CREATE_LOANPRODUCT', 'CREATE_LOANPRODUCT_CHECKER',
|
||||
'CREATE_SAVINGSPRODUCT', 'CREATE_SAVINGSPRODUCT_CHECKER',
|
||||
'CREATE_CURRENTPRODUCT', 'CREATE_CURRENTPRODUCT_CHECKER',
|
||||
'CREATE_SHAREPRODUCT', 'CREATE_SHAREPRODUCT_CHECKER'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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 id="0474_add_fixeddepositproduct_checker_permission_if_not_exists" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_FIXEDDEPOSITPRODUCT_CHECKER', 'FIXEDDEPOSITPRODUCT', 'CREATE_CHECKER', FALSE
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM m_permission WHERE code = 'CREATE_FIXEDDEPOSITPRODUCT_CHECKER'
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0474_enable_fixed_deposit_product_creation_maker_checker" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="HALT">
|
||||
<sqlCheck expectedResult="1">
|
||||
SELECT COUNT(*)
|
||||
FROM m_permission
|
||||
WHERE code = 'CREATE_FIXEDDEPOSITPRODUCT'
|
||||
</sqlCheck>
|
||||
</preConditions>
|
||||
<sql>
|
||||
UPDATE m_permission
|
||||
SET can_maker_checker = TRUE
|
||||
WHERE code = 'CREATE_FIXEDDEPOSITPRODUCT';
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0474_grant_fixed_deposit_product_creation_maker_checker_permissions_to_roles" author="fineract" runOnChange="false">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE r.name = 'Super user'
|
||||
AND p.code IN ('CREATE_FIXEDDEPOSITPRODUCT', 'CREATE_FIXEDDEPOSITPRODUCT_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT ur.role_id, p.id
|
||||
FROM m_appuser u
|
||||
JOIN m_appuser_role ur ON ur.appuser_id = u.id
|
||||
CROSS JOIN m_permission p
|
||||
WHERE u.username = 'bankadmin'
|
||||
AND p.code IN ('CREATE_FIXEDDEPOSITPRODUCT', 'CREATE_FIXEDDEPOSITPRODUCT_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = ur.role_id AND rp.permission_id = p.id
|
||||
);
|
||||
|
||||
INSERT INTO m_role_permission (role_id, permission_id)
|
||||
SELECT r.id, p.id
|
||||
FROM m_role r
|
||||
CROSS JOIN m_permission p
|
||||
WHERE LOWER(r.name) = 'clerk'
|
||||
AND p.code IN ('CREATE_FIXEDDEPOSITPRODUCT', 'CREATE_FIXEDDEPOSITPRODUCT_CHECKER')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_role_permission rp
|
||||
WHERE rp.role_id = r.id AND rp.permission_id = p.id
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+392
@@ -28,6 +28,7 @@ import org.apache.fineract.batch.exception.ErrorInfo;
|
||||
import org.apache.fineract.commands.domain.CommandSource;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.codes.exception.CodeNotFoundException;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
@@ -113,4 +114,395 @@ public class CommandSourceServiceTest {
|
||||
Assertions.assertEquals(1001, result.getErrorCode());
|
||||
Assertions.assertTrue(result.getMessage().contains("Code with name `foo` does not exist"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_NonGLAccount_SuperUser_BypassesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("WITHDRAW_SAVINGSACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("SAVINGSACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("WITHDRAW");
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("WITHDRAW_SAVINGSACCOUNT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult result = underTest.processCommand(handler, jsonCommand,
|
||||
commandSource, superUser, false);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Mockito.verify(commandSource).markAsChecked(superUser);
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsAwaitingApproval();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_GLAccount_SuperUser_EnforcesMakerChecker_Create() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_GLACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("GLACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(100L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(200L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_GLACCOUNT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_GLAccount_SuperUser_EnforcesMakerChecker_Update_And_Disable() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("UPDATE_GLACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("GLACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("UPDATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(101L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(201L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_GLACCOUNT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_GLAccount_SuperUser_EnforcesMakerChecker_Delete() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("DELETE_GLACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("GLACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("DELETE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(102L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(202L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("DELETE_GLACCOUNT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_GLAccount_CheckerApproval_ExecutesSuccessfully() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser checkerUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("UPDATE_GLACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("GLACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("UPDATE");
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_GLACCOUNT")).thenReturn(true);
|
||||
Mockito.when(checkerUser.isCheckerSuperUser()).thenReturn(false);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult result = underTest.processCommand(handler, jsonCommand,
|
||||
commandSource, checkerUser, true);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Mockito.verify(commandSource).markAsChecked(checkerUser);
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsAwaitingApproval();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_GLAccount_NonSuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser regularUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_GLACCOUNT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("GLACCOUNT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(103L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(203L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_GLACCOUNT")).thenReturn(true);
|
||||
Mockito.when(regularUser.isCheckerSuperUser()).thenReturn(false);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, regularUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_CBSBaseInterestRate_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_CBSBASEINTERESTRATE");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("CBSBASEINTERESTRATE");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(104L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(204L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CBSBASEINTERESTRATE")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_CBSBaseInterestRate_CheckerApproval_MarksAsChecked() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser checkerUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_CBSBASEINTERESTRATE");
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CBSBASEINTERESTRATE")).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult result = underTest.processCommand(handler, jsonCommand,
|
||||
commandSource, checkerUser, true);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Mockito.verify(commandSource).markAsChecked(checkerUser);
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsAwaitingApproval();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_Charge_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_CHARGE");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("CHARGE");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(105L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(205L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CHARGE")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_Charge_NonSuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser regularUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_CHARGE");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("CHARGE");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(106L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(206L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CHARGE")).thenReturn(true);
|
||||
Mockito.when(regularUser.isCheckerSuperUser()).thenReturn(false);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, regularUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_LoanProduct_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_LOANPRODUCT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("LOANPRODUCT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(110L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(210L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_LOANPRODUCT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_SavingsProduct_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_SAVINGSPRODUCT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("SAVINGSPRODUCT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(111L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(211L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_SAVINGSPRODUCT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_CurrentProduct_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_CURRENTPRODUCT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("CURRENTPRODUCT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(112L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(212L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CURRENTPRODUCT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_ShareProduct_SuperUser_EnforcesMakerChecker() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser superUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_SHAREPRODUCT");
|
||||
Mockito.when(commandSource.getEntityName()).thenReturn("SHAREPRODUCT");
|
||||
Mockito.when(commandSource.getActionName()).thenReturn("CREATE");
|
||||
Mockito.when(commandSource.getId()).thenReturn(113L);
|
||||
Mockito.when(commandSource.getResourceId()).thenReturn(213L);
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_SHAREPRODUCT")).thenReturn(true);
|
||||
Mockito.when(superUser.isCheckerSuperUser()).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
Assertions.assertThrows(org.apache.fineract.commands.exception.RollbackTransactionNotApprovedException.class, () -> {
|
||||
underTest.processCommand(handler, jsonCommand, commandSource, superUser, false);
|
||||
});
|
||||
|
||||
Mockito.verify(commandSource).markAsAwaitingApproval();
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsChecked(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommand_Products_CheckerApproval_MarksAsChecked() {
|
||||
NewCommandSourceHandler handler = Mockito.mock(NewCommandSourceHandler.class);
|
||||
JsonCommand jsonCommand = Mockito.mock(JsonCommand.class);
|
||||
CommandSource commandSource = Mockito.mock(CommandSource.class);
|
||||
AppUser checkerUser = Mockito.mock(AppUser.class);
|
||||
|
||||
Mockito.when(commandSource.getPermissionCode()).thenReturn("CREATE_LOANPRODUCT");
|
||||
Mockito.when(configurationDomainService.isMakerCheckerEnabledForTask("CREATE_LOANPRODUCT")).thenReturn(true);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult dummyResult = new org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder()
|
||||
.withCommandId(1L).build();
|
||||
Mockito.when(handler.processCommand(jsonCommand)).thenReturn(dummyResult);
|
||||
|
||||
org.apache.fineract.infrastructure.core.data.CommandProcessingResult result = underTest.processCommand(handler, jsonCommand,
|
||||
commandSource, checkerUser, true);
|
||||
|
||||
Assertions.assertNotNull(result);
|
||||
Mockito.verify(commandSource).markAsChecked(checkerUser);
|
||||
Mockito.verify(commandSource, Mockito.never()).markAsAwaitingApproval();
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateChargeDefinitionCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private ChargeWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateChargeDefinitionCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(101L)
|
||||
.withEntityId(201L)
|
||||
.build();
|
||||
when(writePlatformService.createCharge(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).createCharge(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanproduct.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.loanproduct.service.LoanProductWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateLoanProductCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private LoanProductWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateLoanProductCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(101L)
|
||||
.withEntityId(201L)
|
||||
.build();
|
||||
when(writePlatformService.createLoanProduct(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).createLoanProduct(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateCbsBaseInterestRateCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private FdBaseInterestRateWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateCbsBaseInterestRateCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(100L)
|
||||
.withEntityId(200L)
|
||||
.build();
|
||||
when(writePlatformService.saveInterestRates(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).saveInterestRates(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateSavingsProductCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private SavingsProductWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateSavingsProductCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(102L)
|
||||
.withEntityId(202L)
|
||||
.build();
|
||||
when(writePlatformService.create(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).create(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.handler.current;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateCurrentProductCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private CurrentProductWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateCurrentProductCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(103L)
|
||||
.withEntityId(203L)
|
||||
.build();
|
||||
when(writePlatformService.create(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).create(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateEffective;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateEffectiveRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateSlabHistoryRepository;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class FdBaseInterestRateReadPlatformServiceImplTest {
|
||||
|
||||
@Mock
|
||||
private FdBaseInterestRateEffectiveRepository effectiveRepository;
|
||||
|
||||
@Mock
|
||||
private FdBaseInterestRateSlabHistoryRepository slabRepository;
|
||||
|
||||
@InjectMocks
|
||||
private FdBaseInterestRateReadPlatformServiceImpl service;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
ThreadLocalContextUtil.setTenant(null);
|
||||
}
|
||||
|
||||
private FdInterestRateSaveRequest.SlabRequest createSlab(int srNo, String desc, int periodType, int from, Integer to, double rate, double seniorRate) {
|
||||
FdInterestRateSaveRequest.SlabRequest s = new FdInterestRateSaveRequest.SlabRequest();
|
||||
s.setSrNo(srNo);
|
||||
s.setDescription(desc);
|
||||
s.setPeriodTypeEnum(periodType);
|
||||
s.setFromPeriod(from);
|
||||
s.setToPeriod(to);
|
||||
s.setAnnualInterestRate(BigDecimal.valueOf(rate));
|
||||
s.setSeniorCitizenRate(BigDecimal.valueOf(seniorRate));
|
||||
return s;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidSingleDepositSlabs() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
request.setVersionLabel("v1.0");
|
||||
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, 5.0),
|
||||
createSlab(2, "30 to 89 Days", 0, 30, 89, 5.0, 5.5),
|
||||
createSlab(3, "90 to 179 Days", 0, 90, 179, 5.5, 6.0),
|
||||
createSlab(4, "180+ Days", 0, 180, null, 6.0, 6.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
when(effectiveRepository.findByFdTypeAndIsActiveTrueOrderByEffectiveFromDateDesc("SINGLE"))
|
||||
.thenReturn(Collections.emptyList());
|
||||
when(effectiveRepository.saveAndFlush(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
assertDoesNotThrow(() -> service.saveInterestRates(request, 1L));
|
||||
verify(effectiveRepository).saveAndFlush(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidDoubleDepositSlabs() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("DOUBLE");
|
||||
request.setVersionLabel("v1.0");
|
||||
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 2 Years", 3, 1, 2, 6.5, 7.0),
|
||||
createSlab(2, "3 to 5 Years", 3, 3, 5, 6.75, 7.25),
|
||||
createSlab(3, "6 to 10 Years", 3, 6, 10, 7.0, 7.5),
|
||||
createSlab(4, "11+ Years", 3, 11, null, 7.25, 7.75)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
when(effectiveRepository.findByFdTypeAndIsActiveTrueOrderByEffectiveFromDateDesc("DOUBLE"))
|
||||
.thenReturn(Collections.emptyList());
|
||||
when(effectiveRepository.saveAndFlush(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
assertDoesNotThrow(() -> service.saveInterestRates(request, 1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidFirstSlabDoesNotStartAtOne() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "2 to 29 Days", 0, 2, 29, 4.5, 5.0),
|
||||
createSlab(2, "30+ Days", 0, 30, null, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals(1, ex.getErrors().size());
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[1].fromPeriod.first.slab.must.start.at.one",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidOverlapRanges() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, 5.0),
|
||||
createSlab(2, "20 to 50 Days", 0, 20, 50, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[2].fromPeriod.must.not.overlap.previous.range",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidGapBetweenRanges() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, 5.0),
|
||||
createSlab(2, "35 to 89 Days", 0, 35, 89, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[2].fromPeriod.must.be.continuous.with.previous.range",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidDuplicateRanges() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, 5.0),
|
||||
createSlab(2, "1 to 29 Days duplicate", 0, 1, 29, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[2].fromPeriod.must.not.overlap.previous.range",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidFromGreaterThanTo() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 20 Days", 0, 1, 20, 4.5, 5.0),
|
||||
createSlab(2, "21 to 10 Days", 0, 21, 10, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[2].toPeriod.cannot.be.less.than.fromPeriod",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidBlankToPeriodOnIntermediateSlab() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to null Days", 0, 1, null, 4.5, 5.0),
|
||||
createSlab(2, "30+ Days", 0, 30, null, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[1].toPeriod.cannot.be.blank.for.intermediate.slab",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidMixedPeriodTypes() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, 5.0),
|
||||
createSlab(2, "30 to 89 Months", 2, 30, 89, 5.0, 5.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[2].periodTypeEnum.must.be.consistent.across.all.slabs",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidNegativeInterestRate() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, -1.0, 5.0)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[1].annualInterestRate.must.be.non.negative",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidNegativeSeniorRate() {
|
||||
FdInterestRateSaveRequest request = new FdInterestRateSaveRequest();
|
||||
request.setFdType("SINGLE");
|
||||
List<FdInterestRateSaveRequest.SlabRequest> slabs = List.of(
|
||||
createSlab(1, "1 to 29 Days", 0, 1, 29, 4.5, -0.5)
|
||||
);
|
||||
request.setSlabs(slabs);
|
||||
|
||||
PlatformApiDataValidationException ex = assertThrows(PlatformApiDataValidationException.class,
|
||||
() -> service.saveInterestRates(request, 1L));
|
||||
assertEquals("validation.msg.FD_BASE_INTEREST_RATE_VERSION.slabs[1].seniorCitizenRate.must.be.non.negative",
|
||||
ex.getErrors().get(0).getUserMessageGlobalisationCode());
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class FdBaseInterestRateWritePlatformServiceImplTest {
|
||||
|
||||
@Mock
|
||||
private PlatformSecurityContext context;
|
||||
|
||||
@Mock
|
||||
private FdBaseInterestRateReadPlatformService readPlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@Mock
|
||||
private AppUser appUser;
|
||||
|
||||
@InjectMocks
|
||||
private FdBaseInterestRateWritePlatformServiceImpl writePlatformService;
|
||||
|
||||
@Test
|
||||
void shouldParseJsonAndSaveInterestRates() {
|
||||
String jsonPayload = "{\"fdType\":\"SINGLE\",\"versionLabel\":\"v1.0\",\"slabs\":[{\"srNo\":1,\"description\":\"1 to 29 Days\",\"periodTypeEnum\":0,\"fromPeriod\":1,\"toPeriod\":29,\"annualInterestRate\":5.0,\"seniorCitizenRate\":5.5}]}";
|
||||
when(command.json()).thenReturn(jsonPayload);
|
||||
when(command.commandId()).thenReturn(789L);
|
||||
when(context.authenticatedUser()).thenReturn(appUser);
|
||||
when(appUser.getId()).thenReturn(1L);
|
||||
|
||||
FdInterestRateEffectiveData savedData = FdInterestRateEffectiveData.builder()
|
||||
.id(10L)
|
||||
.fdType("SINGLE")
|
||||
.versionLabel("v1.0")
|
||||
.build();
|
||||
when(readPlatformService.saveInterestRates(any(FdInterestRateSaveRequest.class), eq(1L))).thenReturn(savedData);
|
||||
|
||||
CommandProcessingResult result = writePlatformService.saveInterestRates(command);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(789L, result.getCommandId());
|
||||
assertEquals(10L, result.getResourceId());
|
||||
verify(readPlatformService).saveInterestRates(any(FdInterestRateSaveRequest.class), eq(1L));
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.shareproducts.handler;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.portfolio.shareproducts.service.ShareProductWritePlatformService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CreateShareProductCommandHandlerTest {
|
||||
|
||||
@Mock
|
||||
private ShareProductWritePlatformService writePlatformService;
|
||||
|
||||
@Mock
|
||||
private JsonCommand command;
|
||||
|
||||
@InjectMocks
|
||||
private CreateShareProductCommandHandler underTest;
|
||||
|
||||
@Test
|
||||
void shouldDelegateToWritePlatformServiceAndReturnResult() {
|
||||
CommandProcessingResult expectedResult = new CommandProcessingResultBuilder()
|
||||
.withCommandId(104L)
|
||||
.withEntityId(204L)
|
||||
.build();
|
||||
when(writePlatformService.createShareProduct(command)).thenReturn(expectedResult);
|
||||
|
||||
CommandProcessingResult actualResult = underTest.processCommand(command);
|
||||
|
||||
verify(writePlatformService).createShareProduct(command);
|
||||
assertEquals(expectedResult, actualResult);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user