FINERACT-2181: Fix fully paid check on EmiModel

This commit is contained in:
Adam Saghy
2025-05-21 17:16:02 +02:00
parent 4861ad19fd
commit 15c968bc1b
16 changed files with 326 additions and 199 deletions
@@ -108,6 +108,8 @@ final class LoanTransactionsApiResourceSwagger {
public List<GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions;
public List<GetPaymentTypeOptions> paymentTypeOptions;
@Schema(example = "200.000000")
public Double netDisbursalAmount;
}
public static final class GetLoanCurrency {
@@ -30,6 +30,7 @@ import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
@@ -1025,7 +1026,7 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
}
public void copyFrom(final LoanRepaymentScheduleInstallment installment) {
if (getId().equals(installment.getId())) {
if (nonNullAndEqual(getId(), installment.getId())) {
return;
}
// Reset balances
@@ -1149,4 +1150,8 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
}
setLoanTransactionToRepaymentScheduleMappings(retainedTransactionRepaymentScheduleMapping);
}
private static boolean nonNullAndEqual(Object a, Object b) {
return a != null && b != null && Objects.equals(a, b);
}
}
@@ -253,7 +253,7 @@ public final class RepaymentPeriod {
}
public boolean isFullyPaid() {
return getEmi().isEqualTo(getTotalPaidAmount());
return getEmiPlusChargeback().isEqualTo(getTotalPaidAmount());
}
/**
@@ -18,12 +18,6 @@
*/
package org.apache.fineract.portfolio.loanaccount.api;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY;
import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE;
import com.google.gson.Gson;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
@@ -33,17 +27,13 @@ import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
@@ -62,12 +52,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
private final LoanRepositoryWrapper loanRepositoryWrapper;
private final LoanTransactionRepository loanTransactionRepository;
private final ToApiJsonSerializer<Map> toApiJsonSerializerForMap;
private final ToApiJsonSerializer<List> toApiJsonSerializerForList;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final AdvancedPaymentDataMapper advancedPaymentDataMapper;
private final LoanAccountDomainService loanAccountDomainService;
private final Gson gson = new Gson();
@Override
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
@@ -87,7 +73,7 @@ public class InternalLoanInformationApiResource implements InitializingBean {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public String getLoanAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId) {
public AuditData getLoanAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("Fetching loan with {}", loanId);
@@ -95,11 +81,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
log.warn("------------------------------------------------------------");
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
Map<String, Object> auditFields = new HashMap<>(
Map.of(CREATED_BY, loan.getCreatedBy().orElse(null), CREATED_DATE, loan.getCreatedDate().orElse(null), LAST_MODIFIED_BY,
loan.getLastModifiedBy().orElse(null), LAST_MODIFIED_DATE, loan.getLastModifiedDate().orElse(null)));
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
return new AuditData(loan.getCreatedBy().orElse(null), loan.getCreatedDate().orElse(null), loan.getLastModifiedBy().orElse(null),
loan.getLastModifiedDate().orElse(null));
}
@GET
@@ -107,7 +90,7 @@ public class InternalLoanInformationApiResource implements InitializingBean {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public String getLoanTransactionAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId,
public AuditData getLoanTransactionAuditFields(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId,
@PathParam("transactionId") Long transactionId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
@@ -116,11 +99,8 @@ public class InternalLoanInformationApiResource implements InitializingBean {
log.warn("------------------------------------------------------------");
final LoanTransaction transaction = loanTransactionRepository.findById(transactionId).orElseThrow();
Map<String, Object> auditFields = new HashMap<>(Map.of(CREATED_BY, transaction.getCreatedBy().orElse(null), CREATED_DATE,
transaction.getCreatedDate().orElse(null), LAST_MODIFIED_BY, transaction.getLastModifiedBy().orElse(null),
LAST_MODIFIED_DATE, transaction.getLastModifiedDate().orElse(null)));
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializerForMap.serialize(settings, auditFields);
return new AuditData(transaction.getCreatedBy().orElse(null), transaction.getCreatedDate().orElse(null),
transaction.getLastModifiedBy().orElse(null), transaction.getLastModifiedDate().orElse(null));
}
@GET
@@ -128,16 +108,14 @@ public class InternalLoanInformationApiResource implements InitializingBean {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
public String getLoansByStatus(@Context final UriInfo uriInfo, @PathParam("statusId") Integer statusId) {
public List<Long> getLoansByStatus(@Context final UriInfo uriInfo, @PathParam("statusId") Integer statusId) {
log.warn("------------------------------------------------------------");
log.warn(" ");
log.warn("Fetching loans by status {}", statusId);
log.warn(" ");
log.warn("------------------------------------------------------------");
final List<Long> loanIds = loanRepositoryWrapper.findLoanIdsByStatusId(statusId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializerForList.serialize(settings, loanIds);
return loanRepositoryWrapper.findLoanIdsByStatusId(statusId);
}
@GET
@@ -156,4 +134,7 @@ public class InternalLoanInformationApiResource implements InitializingBean {
final Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
return advancedPaymentDataMapper.mapLoanPaymentAllocationRule(loan.getPaymentAllocationRules());
}
private record AuditData(Long createdBy, OffsetDateTime createdDate, Long lastModifiedBy, OffsetDateTime lastModifiedDate) {
}
}
@@ -279,7 +279,7 @@ public class LoanAdjustmentServiceImpl implements LoanAdjustmentService {
writeOffTransaction.reverse();
}
if (newTransactionDetail.isRepaymentLikeType() || newTransactionDetail.isInterestWaiver()) {
if (newTransactionDetail.isRepaymentLikeType() || newTransactionDetail.isWaiver()) {
loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, newTransactionDetail, transactionForAdjustment,
scheduleGeneratorDTO);
}
@@ -345,8 +345,8 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest {
.isInterestRecalculationEnabled(true)//
.interestRecalculationCompoundingMethod(0)//
.rescheduleStrategyMethod(RescheduleStrategyMethod.ADJUST_LAST_UNPAID_PERIOD)//
.recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT_PERIOD)//
.recalculationRestFrequencyInterval(0)//
.recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY)//
.recalculationRestFrequencyInterval(1)//
.isArrearsBasedOnOriginalSchedule(false)//
.isCompoundingToBePostedAsTransaction(false)//
.preClosureInterestCalculationStrategy(1)//
@@ -301,7 +301,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testUpdateInterestPauseByLoanId_overlapping_shouldFail3() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByLoanId("2023-01-02", "2023-01-06",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByLoanId("2023-01-03", "2023-01-06",
"yyyy-MM-dd", "en", loanId);
PostLoansLoanIdTransactionsResponse createResponse2 = LOAN_TRANSACTION_HELPER.createInterestPauseByLoanId("2023-01-07",
"2023-01-12", "yyyy-MM-dd", "en", loanId);
@@ -495,7 +495,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testUpdateInterestPauseByExternalId_overlapping_shouldFail3() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-02",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-03",
"2023-01-06", "yyyy-MM-dd", "en", externalId);
PostLoansLoanIdTransactionsResponse createResponse2 = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-07",
"2023-01-12", "yyyy-MM-dd", "en", externalId);
@@ -517,7 +517,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testUpdateInterestPauseByExternalId_endDateBeforeStartDate_shouldFail() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-01",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-03",
"2023-01-12", "yyyy-MM-dd", "en", externalId);
Assertions.assertNotNull(createResponse);
@@ -538,7 +538,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testUpdateInterestPauseByExternalId_startDateBeforeLoanStart_shouldFail() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-01",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-03",
"2023-01-12", "yyyy-MM-dd", "en", externalId);
Assertions.assertNotNull(createResponse);
@@ -559,7 +559,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testDeleteInterestPauseByExternalId_validRequest_shouldSucceed() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-01",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-03",
"2023-01-12", "yyyy-MM-dd", "en", externalId);
Assertions.assertNotNull(createResponse, "Create response should not be null");
@@ -591,7 +591,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testDeleteInterestPauseByExternalId_invalidExternalId_shouldFail() {
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-01",
PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTION_HELPER.createInterestPauseByExternalId("2023-01-03",
"2023-01-12", "yyyy-MM-dd", "en", externalId);
Assertions.assertNotNull(createResponse);
@@ -698,7 +698,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule);
String loanProductJSON = new LoanProductTestBuilder().withPrincipal(loanPrincipalAmount).withNumberOfRepayments(numberOfRepayments)
.withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod(interestRatePerPeriod)
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestTypeAsDecliningBalance()
.withInterestRateFrequencyTypeAsYear().withAmortizationTypeAsEqualInstallments().withInterestTypeAsDecliningBalance()
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).addAdvancedPaymentAllocation(defaultAllocation)
.withLoanScheduleType(LoanScheduleType.PROGRESSIVE).withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL)
@@ -719,10 +719,10 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsDays().withNumberOfRepayments(numberOfRepayments)
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod)
.withInterestTypeAsFlatBalance().withAmortizationTypeAsEqualPrincipalPayments()
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate(dateString)
.withSubmittedOnDate(dateString).withLoanType("individual").withExternalId(externalId)
.withRepaymentStrategy("advanced-payment-allocation-strategy").build(clientId.toString(), loanProductId.toString(), null);
.withInterestTypeAsDecliningBalance().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
.withExpectedDisbursementDate(dateString).withSubmittedOnDate(dateString).withLoanType("individual")
.withExternalId(externalId).withRepaymentStrategy("advanced-payment-allocation-strategy")
.build(clientId.toString(), loanProductId.toString(), null);
loanId = LOAN_TRANSACTION_HELPER.getLoanId(loanApplicationJSON);
@@ -455,7 +455,8 @@ public class LoanInterestRecalculationCOBTest extends BaseLoanIntegrationTest {
public void verifyLoanInstallmentRecalculatedIfThereIsOverdueInstallmentOn4IProgressiveLoanCOBStep() {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("1 January 2023", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(create4IProgressive());
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(
create4IProgressive().recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT_PERIOD));
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2023", 8000.0, 10.0,
4, null);
@@ -532,7 +533,8 @@ public class LoanInterestRecalculationCOBTest extends BaseLoanIntegrationTest {
public void verifyLoanInstallmentRecalculatedIfThereIsOverdueInstallmentOn4IProgressiveLoanCOBStepLatePaidPaidOnTimeLatePaidPayoffOnTime() {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("1 January 2023", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(create4IProgressive());
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(
create4IProgressive().recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT_PERIOD));
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2023", 8000.0, 10.0,
4, null);
@@ -875,7 +877,8 @@ public class LoanInterestRecalculationCOBTest extends BaseLoanIntegrationTest {
public void verifyLoanInstallmentRecalculatedIfThereIsOverdueInstallmentOn4IProgressiveLoanCOBStepOnePaid() {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("1 January 2023", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(create4IProgressive());
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(
create4IProgressive().recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT_PERIOD));
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2023", 8000.0, 10.0,
4, null);
@@ -997,7 +1000,8 @@ public class LoanInterestRecalculationCOBTest extends BaseLoanIntegrationTest {
public void verifyLoanInstallmentRecalculatedIfThereIsOverdueInstallmentOnProgressiveLoanJob() {
AtomicReference<Long> loanIdRef = new AtomicReference<>();
runAt("1 January 2023", () -> {
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(create4IProgressive());
PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(
create4IProgressive().recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT_PERIOD));
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProduct.getResourceId(), "1 January 2023", 8000.0, 10.0,
4, null);
@@ -265,7 +265,7 @@ public class LoanRescheduleRequestTest extends BaseLoanIntegrationTest {
runAt("15 February 2023", () -> {
loanResponse.set(applyForLoanApplication(client.getClientId(), commonLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023"));
BigDecimal.TEN, "01 January 2023", "01 January 2023"));
loanTransactionHelper.approveLoan(loanResponse.get().getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -469,7 +469,7 @@ public final class BatchHelper {
final String dateString = LocalDate.now(Utils.getZoneIdOfTenant()).format(DateTimeFormatter.ofPattern(dateFormat));
final String body = String.format(
"{\"chargeId\": \"%d\", \"locale\": \"en\", \"amount\": \"11.15\", " + "\"dateFormat\": \"%s\", \"dueDate\": \"%s\"}",
"{\"chargeId\": \"%d\", \"locale\": \"en\", \"amount\": \"100.0\", " + "\"dateFormat\": \"%s\", \"dueDate\": \"%s\"}",
chargeId, dateFormat, dateString);
br.setBody(body);
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.integrationtests.common;
import static org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
import com.google.gson.Gson;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
@@ -28,13 +30,16 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.BusinessDateData;
import org.apache.fineract.client.models.BusinessDateRequest;
import org.apache.fineract.client.models.BusinessDateResponse;
import org.apache.fineract.client.models.PutGlobalConfigurationsRequest;
import org.apache.fineract.client.util.Calls;
import org.apache.fineract.client.util.JSON;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants;
@Slf4j
public final class BusinessDateHelper {
private static final String DATETIME_PATTERN = "dd MMMM yyyy";
private static final Gson GSON = new JSON().getGson();
public BusinessDateHelper() {}
@@ -51,7 +56,7 @@ public final class BusinessDateHelper {
return Utils.performServerPost(requestSpec, responseSpec, BUSINESS_DATE_API, buildBusinessDateRequest(type, date), "changes");
}
public BusinessDateResponse updateBusinessDate(final BusinessDateRequest request) {
public static BusinessDateResponse updateBusinessDate(final BusinessDateRequest request) {
log.info("------------------UPDATE BUSINESS DATE----------------------");
log.info("------------------Type: {}, date: {}----------------------", request.getType(), request.getDate());
return Calls.ok(FineractClientHelper.getFineractClient().businessDateManagement.updateBusinessDate(request));
@@ -91,4 +96,17 @@ public final class BusinessDateHelper {
return new Gson().toJson(map);
}
public static void runAt(String date, Runnable runnable) {
try {
new GlobalConfigurationHelper().updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(true));
updateBusinessDate(
new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
runnable.run();
} finally {
new GlobalConfigurationHelper().updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE,
new PutGlobalConfigurationsRequest().enabled(false));
}
}
}
@@ -127,8 +127,8 @@ public class LoanProductTestBuilder {
private String interestRecalculationCompoundingMethod = "0";
private String preCloseInterestCalculationStrategy = INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE;
private String rescheduleStrategyMethod = "1";
private String recalculationRestFrequencyType = "1";
private String recalculationRestFrequencyInterval = "0";
private String recalculationRestFrequencyType = "2";
private String recalculationRestFrequencyInterval = "1";
private String recalculationCompoundingFrequencyType = null;
private String recalculationCompoundingFrequencyInterval = null;
private String minimumDaysBetweenDisbursalAndFirstRepayment = null;
@@ -18,62 +18,73 @@
*/
package org.apache.fineract.integrationtests.common.loans;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.HashMap;
import java.util.List;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTemplateResponse;
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.util.Calls;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.FineractClientHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
public class LoanTestLifecycleExtension implements AfterEachCallback {
private ResponseSpecification responseSpec;
private RequestSpecification requestSpec;
private LoanTransactionHelper loanTransactionHelper;
private DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
public static final String DATE_FORMAT = "dd MMMM yyyy";
private final DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().appendPattern(DATE_FORMAT).toFormatter();
@Override
public void afterEach(ExtensionContext context) {
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
this.requestSpec.header("Fineract-Platform-TenantId", "default");
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
BusinessDateHelper.runAt(DateTimeFormatter.ofPattern(DATE_FORMAT).format(Utils.getLocalDateOfTenant()), () -> {
this.loanTransactionHelper = new LoanTransactionHelper(null, null);
// Fully repay ACTIVE loans, so it will not be picked up by any jobs
List<Integer> loanIds = LoanTransactionHelper.getLoanIdsByStatusId(requestSpec, responseSpec, 300);
loanIds.forEach(loanId -> {
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanId);
LocalDate transactionDate = LocalDate.of((Integer) ((List) prepayDetail.get("date")).get(0),
(Integer) ((List) prepayDetail.get("date")).get(1), (Integer) ((List) prepayDetail.get("date")).get(2));
Double amount = Double.parseDouble(String.valueOf(prepayDetail.get("amount")));
Double netDisbursalAmount = Double.parseDouble(String.valueOf(prepayDetail.get("netDisbursalAmount")));
Double repayAmount = Double.compare(amount, 0.0) > 0 ? amount : netDisbursalAmount;
loanTransactionHelper.makeLoanRepayment((long) loanId, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
.transactionDate(dateFormatter.format(transactionDate)).locale("en").transactionAmount(repayAmount));
});
// Undo APPROVED loans, so the next step can REJECT them, so it will not be picked up by any jobs
loanIds = LoanTransactionHelper.getLoanIdsByStatusId(requestSpec, responseSpec, 200);
loanIds.forEach(loanId -> {
loanTransactionHelper.undoApproval(loanId);
});
// Mark SUBMITTED loans, as REJECTED, so it will not be picked up by any jobs
loanIds = LoanTransactionHelper.getLoanIdsByStatusId(requestSpec, responseSpec, 100);
loanIds.forEach(loanId -> {
GetLoansLoanIdResponse details = loanTransactionHelper.getLoanDetails((long) loanId);
loanTransactionHelper.rejectLoan((long) loanId,
new PostLoansLoanIdRequest().rejectedOnDate(dateFormatter.format(details.getTimeline().getSubmittedOnDate()))
.locale("en").dateFormat("dd MMMM yyyy"));
// Fully repay ACTIVE loans, so it will not be picked up by any jobs
List<Long> loanIds = LoanTransactionHelper.getLoanIdsByStatusId(300);
loanIds.forEach(loanId -> {
GetLoansLoanIdResponse loanResponse = Calls
.ok(FineractClientHelper.getFineractClient().loans.retrieveLoan((long) loanId, null, "all", null, null));
loanResponse.getDisbursementDetails().forEach(disbursementDetail -> {
if (disbursementDetail.getActualDisbursementDate() == null) {
loanTransactionHelper.disburseLoan((long) loanId,
new PostLoansLoanIdRequest()
.actualDisbursementDate(dateFormatter.format(disbursementDetail.getExpectedDisbursementDate()))
.dateFormat(DATE_FORMAT).locale("en")
.transactionAmount(BigDecimal.valueOf(disbursementDetail.getPrincipal())));
}
});
loanResponse = Calls
.ok(FineractClientHelper.getFineractClient().loans.retrieveLoan((long) loanId, null, "all", null, null));
GetLoansLoanIdTransactionsTemplateResponse prepayDetail = this.loanTransactionHelper.getPrepaymentAmount(loanId,
dateFormatter.format(Utils.getLocalDateOfTenant()), DATE_FORMAT);
LocalDate transactionDate = prepayDetail.getDate();
Double amount = prepayDetail.getAmount();
Double netDisbursalAmount = prepayDetail.getNetDisbursalAmount();
Double repayAmount = Double.compare(amount, 0.0) > 0 ? amount : netDisbursalAmount;
loanTransactionHelper.makeLoanRepayment(loanId, new PostLoansLoanIdTransactionsRequest().dateFormat(DATE_FORMAT)
.transactionDate(dateFormatter.format(transactionDate)).locale("en").transactionAmount(repayAmount));
});
// Undo APPROVED loans, so the next step can REJECT them, so it will not be picked up by any jobs
loanIds = LoanTransactionHelper.getLoanIdsByStatusId(200);
loanIds.forEach(loanId -> {
loanTransactionHelper.undoApprovalForLoan(loanId, new PostLoansLoanIdRequest());
});
// Mark SUBMITTED loans, as REJECTED, so it will not be picked up by any jobs
loanIds = LoanTransactionHelper.getLoanIdsByStatusId(100);
loanIds.forEach(loanId -> {
GetLoansLoanIdResponse details = loanTransactionHelper.getLoanDetails((long) loanId);
loanTransactionHelper.rejectLoan(loanId,
new PostLoansLoanIdRequest().rejectedOnDate(dateFormatter.format(details.getTimeline().getSubmittedOnDate()))
.locale("en").dateFormat(DATE_FORMAT));
});
// loanIds = LoanTransactionHelper.getLoanIdsByStatusId(300);
// assertEquals(0, loanIds.size());
});
}
}
@@ -2983,6 +2983,10 @@ public class LoanTransactionHelper {
return new Gson().fromJson(get, new TypeToken<ArrayList<Integer>>() {}.getType());
}
public static List<Long> getLoanIdsByStatusId(Integer statusId) {
return Calls.ok(FineractClientHelper.getFineractClient().legacy.getLoansByStatus(statusId));
}
public PutLoanProductsProductIdResponse updateLoanProduct(Long id, PutLoanProductsProductIdRequest requestModifyLoan) {
return Calls.ok(FineractClientHelper.getFineractClient().loanProducts.updateLoanProduct(id, requestModifyLoan));
}
@@ -30,6 +30,7 @@ import io.restassured.specification.ResponseSpecification;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.Utils;
import org.junit.jupiter.api.BeforeEach;
@@ -42,7 +43,6 @@ import org.mockserver.model.MediaType;
@ExtendWith(MockServerExtension.class)
@MockServerSettings(ports = { 9191 })
public class CampaignsTest {
private RequestSpecification requestSpec;
@@ -93,145 +93,155 @@ public class CampaignsTest {
@Test
public void testSupportedActionsForCampaignWithTriggerTypeAsDirect() {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
BusinessDateHelper.runAt(DateTimeFormatter.ofPattern(DATE_FORMAT).format(Utils.getLocalDateOfTenant()), () -> {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId, CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
});
}
@Test
public void testSupportedActionsForCampaignWithTriggerTypeAsScheduled() {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, SCHEDULED_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
BusinessDateHelper.runAt(DateTimeFormatter.ofPattern(DATE_FORMAT).format(Utils.getLocalDateOfTenant()), () -> {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, SCHEDULED_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
NON_TRIGGERED_REPORT_NAME, SCHEDULED_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
NON_TRIGGERED_REPORT_NAME, SCHEDULED_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId, CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
});
}
@Test
public void testSupportedActionsForCampaignWithTriggerTypeAsTriggered() {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(TRIGGERED_REPORT_NAME, TRIGGERED_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
BusinessDateHelper.runAt(DateTimeFormatter.ofPattern(DATE_FORMAT).format(Utils.getLocalDateOfTenant()), () -> {
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(TRIGGERED_REPORT_NAME, TRIGGERED_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
TRIGGERED_REPORT_NAME, TRIGGERED_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// updating campaign
Integer updatedCampaignId = this.campaignsHelper.updateCampaign(this.requestSpec, this.responseSpec, campaignId,
TRIGGERED_REPORT_NAME, TRIGGERED_TRIGGER_TYPE);
assertEquals(campaignId, updatedCampaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// reactivating campaign
Integer reactivateCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
REACTIVATE_COMMAND);
assertEquals(reactivateCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId, CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// closing campaign again for deletion
closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
});
}
@SuppressWarnings("unchecked")
@Test
public void testSupportedActionsForCampaignWithError() {
final ResponseSpecification responseSpecWithError = new ResponseSpecBuilder().expectStatusCode(400).build();
CampaignsHelper campaignsHelperWithError = new CampaignsHelper(this.requestSpec, responseSpecWithError);
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
BusinessDateHelper.runAt(DateTimeFormatter.ofPattern(DATE_FORMAT).format(Utils.getLocalDateOfTenant()), () -> {
final ResponseSpecification responseSpecWithError = new ResponseSpecBuilder().expectStatusCode(400).build();
CampaignsHelper campaignsHelperWithError = new CampaignsHelper(this.requestSpec, responseSpecWithError);
// creating new campaign
Integer campaignId = this.campaignsHelper.createCampaign(NON_TRIGGERED_REPORT_NAME, DIRECT_TRIGGER_TYPE);
this.campaignsHelper.verifyCampaignCreatedOnServer(this.requestSpec, this.responseSpec, campaignId);
// activating campaign with failure
ArrayList<HashMap<String, Object>> campaignDateValidationData = (ArrayList<HashMap<String, Object>>) campaignsHelperWithError
.performActionsOnCampaignWithFailure(campaignId, ACTIVATE_COMMAND,
Utils.getLocalDateOfTenant().plusDays(1).format(DateTimeFormatter.ofPattern(DATE_FORMAT)),
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.campaign.activationDate.in.the.future",
campaignDateValidationData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
// activating campaign with failure
ArrayList<HashMap<String, Object>> campaignDateValidationData = (ArrayList<HashMap<String, Object>>) campaignsHelperWithError
.performActionsOnCampaignWithFailure(campaignId, ACTIVATE_COMMAND,
Utils.getLocalDateOfTenant().plusDays(1).format(DateTimeFormatter.ofPattern(DATE_FORMAT)),
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.campaign.activationDate.in.the.future",
campaignDateValidationData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// activating campaign
Integer activatedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
ACTIVATE_COMMAND);
assertEquals(activatedCampaignId, campaignId);
// activating campaign with failure
ArrayList<HashMap<String, Object>> campaignErrorData = (ArrayList<HashMap<String, Object>>) campaignsHelperWithError
.performActionsOnCampaignWithFailure(activatedCampaignId, ACTIVATE_COMMAND,
Utils.getLocalDateOfTenant().format(DateTimeFormatter.ofPattern(DATE_FORMAT)), CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.campaign.already.active", campaignErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
// activating campaign with failure
ArrayList<HashMap<String, Object>> campaignErrorData = (ArrayList<HashMap<String, Object>>) campaignsHelperWithError
.performActionsOnCampaignWithFailure(activatedCampaignId, ACTIVATE_COMMAND,
Utils.getLocalDateOfTenant().format(DateTimeFormatter.ofPattern(DATE_FORMAT)), CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.campaign.already.active", campaignErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
// closing campaign again for deletion
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
// closing campaign again for deletion
Integer closedCampaignId = this.campaignsHelper.performActionsOnCampaign(this.requestSpec, this.responseSpec, campaignId,
CLOSE_COMMAND);
assertEquals(closedCampaignId, campaignId);
// deleting campaign
Integer deletedCampaignId = this.campaignsHelper.deleteCampaign(this.requestSpec, this.responseSpec, campaignId);
assertEquals(deletedCampaignId, campaignId);
});
}
}
@@ -0,0 +1,92 @@
#
# 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.
#
additionalProperties=Additional properties are not allowed: {0}
allOf=One or more conditions in allOf failed: {0}
anyOf=Value does not match any of the required schemas: {0}
const=Value must be exactly: {0}
contains=Array does not contain required item: {0}
crossEdits=Cross edits are not allowed: {0}
dependencies=Missing dependencies: {0}
dependentRequired=Missing dependent properties: {0}
edits=Invalid edits: {0}
enum=Value {0} is not allowed. Allowed values are: {1}
exclusiveMaximum=Value {0} must be less than (exclusive): {1}
exclusiveMinimum=Value {0} must be greater than (exclusive): {1}
format=Value {0} does not match required format: {1}
items=Invalid item in array: {0}
maxItems=Array has too many items: {0}, maximum: {1}
maxLength=String is too long: {0}, maximum length: {1}
maxProperties=Too many properties: {0}, maximum allowed: {1}
maximum=Value {0} exceeds maximum: {1}
minItems=Array has too few items: {0}, minimum: {1}
minLength=String is too short: {0}, minimum length: {1}
minProperties=Too few properties: {0}, minimum required: {1}
minimum=Value {0} is below minimum: {1}
multipleOf=Value {0} is not a multiple of {1}
not=Value matches schema when it should not: {0}
notAllowed=The value is not allowed: {0}
oneOf=Value matches more than one schema in oneOf: {0}
pattern=String does not match pattern: {0}
prefixItems=Array does not match prefixItems validation rules: {0}
properties=Invalid property: {0}
propertyNames=Invalid property name: {0}
readOnly=Property is read-only: {0}
required=Required field is missing: {0}
then='then' schema failed validation
type=Expected type: {0}, found: {1}
unionType=Value does not match any of the expected types: {0}
uniqueItems=Array has duplicate items: {0}
writeOnly=Property is write-only: {0}
$ref=Reference {0} could not be resolved or is invalid
if=Condition 'if' failed
else='else' schema failed validation
allErrors=Multiple validation errors occurred: {0}
default=Validation failed for value: {0}
patternProperties=Pattern property not matched: {0}
# Format-specific
date=Value does not match date format: {0}
dateTime=Value does not match date-time format: {0}
time=Value does not match time format: {0}
email=Value is not a valid email address: {0}
hostname=Value is not a valid hostname: {0}
ipv4=Value is not a valid IPv4 address: {0}
ipv6=Value is not a valid IPv6 address: {0}
uri=Value is not a valid URI: {0}
uuid=Value is not a valid UUID: {0}
uriReference=Value is not a valid URI reference: {0}
iri=Value is not a valid IRI: {0}
iriReference=Value is not a valid IRI reference: {0}
jsonPointer=Value is not a valid JSON Pointer: {0}
relativeJsonPointer=Value is not a valid Relative JSON Pointer: {0}
regex=Value is not a valid regular expression: {0}
byte=Value is not a valid base64 string: {0}
int32=Value is not a valid 32-bit integer: {0}
int64=Value is not a valid 64-bit integer: {0}
float=Value is not a valid float: {0}
double=Value is not a valid double: {0}
binary=Value is not a valid binary: {0}
password=Password format validation failed
contentEncoding=Value does not match expected encoding: {0}
contentMediaType=Value does not match expected media type: {0}
id=Invalid ID value: {0}
false=Schema explicitly disallows all values
dependentSchemas=Object does not satisfy dependent schemas: {0}
unevaluatedProperties=Object has unevaluated properties that are not allowed: {0}