diff --git a/fineract-e2e-tests-core/build.gradle b/fineract-e2e-tests-core/build.gradle index 79032d3e884..ff966ae345d 100644 --- a/fineract-e2e-tests-core/build.gradle +++ b/fineract-e2e-tests-core/build.gradle @@ -62,3 +62,7 @@ dependencies { testImplementation 'org.apache.commons:commons-collections4:4.4' } + +tasks.withType(JavaCompile).configureEach { + options.compilerArgs.add("-parameters") +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java index db857635529..9fd37335ae0 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/api/ApiConfiguration.java @@ -18,9 +18,40 @@ */ package org.apache.fineract.test.api; +import org.apache.fineract.client.services.BatchApiApi; +import org.apache.fineract.client.services.BusinessDateManagementApi; +import org.apache.fineract.client.services.BusinessStepConfigurationApi; +import org.apache.fineract.client.services.ChargesApi; import org.apache.fineract.client.services.ClientApi; import org.apache.fineract.client.services.CodeValuesApi; import org.apache.fineract.client.services.CodesApi; +import org.apache.fineract.client.services.CurrencyApi; +import org.apache.fineract.client.services.DataTablesApi; +import org.apache.fineract.client.services.DefaultApi; +import org.apache.fineract.client.services.DelinquencyRangeAndBucketsManagementApi; +import org.apache.fineract.client.services.ExternalAssetOwnersApi; +import org.apache.fineract.client.services.ExternalEventConfigurationApi; +import org.apache.fineract.client.services.FundsApi; +import org.apache.fineract.client.services.GeneralLedgerAccountApi; +import org.apache.fineract.client.services.GlobalConfigurationApi; +import org.apache.fineract.client.services.InlineJobApi; +import org.apache.fineract.client.services.JournalEntriesApi; +import org.apache.fineract.client.services.LoanAccountLockApi; +import org.apache.fineract.client.services.LoanChargesApi; +import org.apache.fineract.client.services.LoanCobCatchUpApi; +import org.apache.fineract.client.services.LoanProductsApi; +import org.apache.fineract.client.services.LoanTransactionsApi; +import org.apache.fineract.client.services.LoansApi; +import org.apache.fineract.client.services.MappingFinancialActivitiesToAccountsApi; +import org.apache.fineract.client.services.PaymentTypeApi; +import org.apache.fineract.client.services.RescheduleLoansApi; +import org.apache.fineract.client.services.RolesApi; +import org.apache.fineract.client.services.SavingsAccountApi; +import org.apache.fineract.client.services.SavingsAccountTransactionsApi; +import org.apache.fineract.client.services.SavingsProductApi; +import org.apache.fineract.client.services.SchedulerApi; +import org.apache.fineract.client.services.SchedulerJobApi; +import org.apache.fineract.client.services.UsersApi; import org.apache.fineract.client.util.FineractClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -33,8 +64,53 @@ public class ApiConfiguration { private FineractClient fineractClient; @Bean - public ClientApi clientApi() { - return fineractClient.createService(ClientApi.class); + public SchedulerApi schedulerApi() { + return fineractClient.createService(SchedulerApi.class); + } + + @Bean + public SchedulerJobApi schedulerJobApi() { + return fineractClient.createService(SchedulerJobApi.class); + } + + @Bean + public CurrencyApi currencyApi() { + return fineractClient.createService(CurrencyApi.class); + } + + @Bean + public DataTablesApi dataTablesApi() { + return fineractClient.createService(DataTablesApi.class); + } + + @Bean + public ChargesApi chargesApi() { + return fineractClient.createService(ChargesApi.class); + } + + @Bean + public GeneralLedgerAccountApi generalLedgerAccountApi() { + return fineractClient.createService(GeneralLedgerAccountApi.class); + } + + @Bean + public LoanProductsApi loanProductsApi() { + return fineractClient.createService(LoanProductsApi.class); + } + + @Bean + public SavingsProductApi savingsProductApi() { + return fineractClient.createService(SavingsProductApi.class); + } + + @Bean + public SavingsAccountTransactionsApi savingsAccountTransactionsApi() { + return fineractClient.createService(SavingsAccountTransactionsApi.class); + } + + @Bean + public SavingsAccountApi savingsAccountApi() { + return fineractClient.createService(SavingsAccountApi.class); } @Bean @@ -46,4 +122,114 @@ public CodesApi codesApi() { public CodeValuesApi codeValuesApi() { return fineractClient.createService(CodeValuesApi.class); } + + @Bean + public DelinquencyRangeAndBucketsManagementApi delinquencyRangeAndBucketsManagementApi() { + return fineractClient.createService(DelinquencyRangeAndBucketsManagementApi.class); + } + + @Bean + public FundsApi fundsApi() { + return fineractClient.createService(FundsApi.class); + } + + @Bean + public GlobalConfigurationApi globalConfigurationApi() { + return fineractClient.createService(GlobalConfigurationApi.class); + } + + @Bean + public PaymentTypeApi paymentTypeApi() { + return fineractClient.createService(PaymentTypeApi.class); + } + + @Bean + public BusinessDateManagementApi businessDateManagementApi() { + return fineractClient.createService(BusinessDateManagementApi.class); + } + + @Bean + public ClientApi clientApi() { + return fineractClient.createService(ClientApi.class); + } + + @Bean + public BatchApiApi batchApiApi() { + return fineractClient.createService(BatchApiApi.class); + } + + @Bean + public LoansApi loansApi() { + return fineractClient.createService(LoansApi.class); + } + + @Bean + public JournalEntriesApi journalEntriesApi() { + return fineractClient.createService(JournalEntriesApi.class); + } + + @Bean + public InlineJobApi inlineJobApi() { + return fineractClient.createService(InlineJobApi.class); + } + + @Bean + public LoanTransactionsApi loanTransactionsApi() { + return fineractClient.createService(LoanTransactionsApi.class); + } + + @Bean + public LoanChargesApi loanChargesApi() { + return fineractClient.createService(LoanChargesApi.class); + } + + @Bean + public ExternalEventConfigurationApi externalEventConfigurationApi() { + return fineractClient.createService(ExternalEventConfigurationApi.class); + } + + @Bean + public LoanCobCatchUpApi loanCobCatchUpApi() { + return fineractClient.createService(LoanCobCatchUpApi.class); + } + + @Bean + public RolesApi rolesApi() { + return fineractClient.createService(RolesApi.class); + } + + @Bean + public UsersApi usersApi() { + return fineractClient.createService(UsersApi.class); + } + + @Bean + public ExternalAssetOwnersApi externalAssetOwnersApi() { + return fineractClient.createService(ExternalAssetOwnersApi.class); + } + + @Bean + public BusinessStepConfigurationApi businessStepConfigurationApi() { + return fineractClient.createService(BusinessStepConfigurationApi.class); + } + + @Bean + public MappingFinancialActivitiesToAccountsApi mappingFinancialActivitiesToAccountsApi() { + return fineractClient.createService(MappingFinancialActivitiesToAccountsApi.class); + } + + @Bean + public LoanAccountLockApi loanAccountLockApi() { + return fineractClient.createService(LoanAccountLockApi.class); + } + + @Bean + public DefaultApi defaultApi() { + return fineractClient.createService(DefaultApi.class); + } + + @Bean + public RescheduleLoansApi rescheduleLoansApi() { + return fineractClient.createService(RescheduleLoansApi.class); + } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/CacheConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/CacheConfiguration.java new file mode 100644 index 00000000000..4465782c05f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/config/CacheConfiguration.java @@ -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.test.config; + +import java.util.List; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCache; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +public class CacheConfiguration { + + @Bean + public CacheManager cacheManager() { + SimpleCacheManager simpleCacheManager = new SimpleCacheManager(); + simpleCacheManager.setCaches(List.of(new ConcurrentMapCache("paymentTypesByName"), // + new ConcurrentMapCache("jobsByName"), // + new ConcurrentMapCache("loanProductsByName"), // + new ConcurrentMapCache("accountTypesByName")));// + return simpleCacheManager; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeAssetOptions.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeAssetOptions.java new file mode 100644 index 00000000000..5f9d4af5efb --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeAssetOptions.java @@ -0,0 +1,32 @@ +/** + * 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.test.data; + +public enum AccountTypeAssetOptions { + + LOANS_RECEIVABLE(1), INTEREST_FEE_RECEIVABLE(2), OTHER_RECEIVABLES(3), UNC_RECEIVABLE(4), FUND_RECEIVABLES( + 18), TRANSFER_IN_SUSPENSE_ACCOUNT(14), GOODWILL_TRANSFER_ACCOUNT(19); + + public final Integer value; + + AccountTypeAssetOptions(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeExpenseOptions.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeExpenseOptions.java new file mode 100644 index 00000000000..a0229ff4267 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeExpenseOptions.java @@ -0,0 +1,31 @@ +/** + * 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.test.data; + +public enum AccountTypeExpenseOptions { + + CREDIT_LOSS_BAD_DEBT(12), CREDIT_LOSS_BAD_DEBT_FRAUD(13), WRITTEN_OFF(16); + + public final Integer value; + + AccountTypeExpenseOptions(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeIncomeOptions.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeIncomeOptions.java new file mode 100644 index 00000000000..b9b80c3d4f9 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeIncomeOptions.java @@ -0,0 +1,32 @@ +/** + * 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.test.data; + +public enum AccountTypeIncomeOptions { + + DEFERRED_INTEREST_REVENUE(7), RETAINED_EARNINGS_PRIOR_YEAR(8), INTEREST_INCOME(9), FEE_INCOME(10), FEE_CHARGE_OFF(11), RECOVERIES( + 15), INTEREST_INCOME_CHARGE_OFF(20); + + public final Integer value; + + AccountTypeIncomeOptions(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeLiabilityOptions.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeLiabilityOptions.java new file mode 100644 index 00000000000..7378028ffc1 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountTypeLiabilityOptions.java @@ -0,0 +1,31 @@ +/** + * 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.test.data; + +public enum AccountTypeLiabilityOptions { + + AA_SUSPENSE_BALANCE(5), SUSPENSE_CLEARING_ACCOUNT(6), OVERPAYMENT_ACCOUNT(17); + + public final Integer value; + + AccountTypeLiabilityOptions(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountingRule.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountingRule.java new file mode 100644 index 00000000000..49667ba9f8e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AccountingRule.java @@ -0,0 +1,31 @@ +/** + * 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.test.data; + +public enum AccountingRule { + + NONE(1), CASH_BASED(2), ACCRUAL_PERIODIC(3), ACCRUAL_UPFRONT(4); + + public final Integer value; + + AccountingRule(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AdvancePaymentsAdjustmentType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AdvancePaymentsAdjustmentType.java new file mode 100644 index 00000000000..6b194bfcb7e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AdvancePaymentsAdjustmentType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum AdvancePaymentsAdjustmentType { + + RESCHEDULE_NEXT_REPAYMENTS(1), REDUCE_NUMBER_OF_INSTALLMENTS(2), REDUCE_EMI_AMOUNT(3); + + public final Integer value; + + AdvancePaymentsAdjustmentType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AmortizationType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AmortizationType.java new file mode 100644 index 00000000000..98ce1ad8bcd --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AmortizationType.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum AmortizationType { + + EQUAL_PRINCIPAL_PAYMENTS(0), EQUAL_INSTALLMENTS(1); + + public final Integer value; + + AmortizationType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationErrorMessage.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationErrorMessage.java new file mode 100644 index 00000000000..eb58e92d5cb --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationErrorMessage.java @@ -0,0 +1,40 @@ +/** + * 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.test.data; + +public enum AssetExternalizationErrorMessage { + + LOAN_NOT_ACTIVE("Loan is not in active status"), ASSET_OWNED_CANNOT_BE_SOLD( + "This loan cannot be sold, because it is owned by an external asset owner"), ASSET_NOT_OWNED_CANNOT_BE_BOUGHT( + "This loan cannot be bought back, it is not owned by an external asset owner"), BUYBACK_ALREADY_IN_PROGRESS_CANNOT_BE_BOUGHT( + "This loan cannot be bought back, external asset owner buyback transfer is already in progress"), ALREADY_PENDING( + "External asset owner transfer is already in PENDING state for this loan"), SETTLEMENT_DATE_IN_THE_PAST( + "Settlement date cannot be in the past"), INVALID_REQUEST( + "The request was invalid. This typically will happen due to validation errors which are provided."); + + public final String value; + + AssetExternalizationErrorMessage(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatus.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatus.java new file mode 100644 index 00000000000..576121109e7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatus.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum AssetExternalizationTransferStatus { + + EXECUTED("EXECUTED"), CANCELLED("CANCELLED"), DECLINED("DECLINED"); + + public final String value; + + AssetExternalizationTransferStatus(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatusReason.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatusReason.java new file mode 100644 index 00000000000..c416d72e79f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/AssetExternalizationTransferStatusReason.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum AssetExternalizationTransferStatusReason { + + BALANCE_ZERO("BALANCE_ZERO"), BALANCE_NEGATIVE("BALANCE_NEGATIVE"), SAMEDAY_TRANSFERS("SAMEDAY_TRANSFERS"); + + public final String value; + + AssetExternalizationTransferStatusReason(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeCalculationType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeCalculationType.java new file mode 100644 index 00000000000..8124bd2d9b8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeCalculationType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum ChargeCalculationType { + + FLAT(1), PERCENTAGE_AMOUNT(2), PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST(3), PERCENTAGE_INTEREST(4), PERCENTAGE_DISBURSEMENT_AMOUNT(5); + + public final Integer value; + + ChargeCalculationType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargePaymentMode.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargePaymentMode.java new file mode 100644 index 00000000000..28e5995750b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargePaymentMode.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum ChargePaymentMode { + + REGULAR(0), ACCOUNT_TRANSFER(1); + + public final Integer value; + + ChargePaymentMode(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductAppliesTo.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductAppliesTo.java new file mode 100644 index 00000000000..e083693d0af --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductAppliesTo.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum ChargeProductAppliesTo { + + LOAN(1), SAVINGS(2), CLIENT(3), SHARES(4); + + public final Integer value; + + ChargeProductAppliesTo(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductType.java new file mode 100644 index 00000000000..4ff43ef8a8f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeProductType.java @@ -0,0 +1,37 @@ +/** + * 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.test.data; + +public enum ChargeProductType { + + LOAN_PERCENTAGE_LATE_FEE(1L), LOAN_PERCENTAGE_PROCESSING_FEE(2L), LOAN_FIXED_LATE_FEE(3L), LOAN_FIXED_RETURNED_PAYMENT_FEE( + 4L), LOAN_SNOOZE_FEE(5L), LOAN_NSF_FEE(6L), LOAN_DISBURSEMENT_PERCENTAGE_FEE( + 7L), LOAN_TRANCHE_DISBURSEMENT_PERCENTAGE_FEE(8L), LOAN_INSTALLMENT_PERCENTAGE_FEE( + 9L), LOAN_PERCENTAGE_LATE_FEE_AMOUNT_PLUS_INTEREST(10L), CLIENT_TEST_CHARGE_FEE(11L); + + public final Long value; + + ChargeProductType(Long value) { + this.value = value; + } + + public Long getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeTimeType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeTimeType.java new file mode 100644 index 00000000000..38fabb1f5b5 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ChargeTimeType.java @@ -0,0 +1,32 @@ +/** + * 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.test.data; + +public enum ChargeTimeType { + + DISBURSEMENT(1), SPECIFIED_DUE_DATE(2), SAVINGS_ACTIVATION(3), WITHDRAWAL_FEE(5), ANNUAL_FEE(6), MONTHLY_FEE(7), INSTALLMENT_FEE( + 8), OVERDUE_FEES(9), OVERDRAFT_FEE(10), WEEKLY_FEE(11), TRANCHE_DISBURSEMENT( + 12), SHARE_ACCOUNT_ACTIVATE(13), SHARE_PURCHASE(14), SHARE_REDEEM(15), SAVING_NO_ACTIVITY_FEE(16); + + public final Integer value; + + ChargeTimeType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/CurrencyOptions.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/CurrencyOptions.java new file mode 100644 index 00000000000..ed289ea47d6 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/CurrencyOptions.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum CurrencyOptions { + + EUR("EUR"), USD("USD"); + + public final String value; + + CurrencyOptions(String value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInMonthType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInMonthType.java new file mode 100644 index 00000000000..ea49c1f86a8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInMonthType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum DaysInMonthType { + + ACTUAL(1), DAYS30(30); + + public final Integer value; + + DaysInMonthType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInYearType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInYearType.java new file mode 100644 index 00000000000..3a3986cd20d --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DaysInYearType.java @@ -0,0 +1,31 @@ +/** + * 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.test.data; + +public enum DaysInYearType { + + ACTUAL(1), DAYS360(360), DAYS364(364), DAYS365(365); + + public final Integer value; + + DaysInYearType(Integer value) { + this.value = value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyBucket.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyBucket.java new file mode 100644 index 00000000000..a089092558d --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyBucket.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum DelinquencyBucket { + + BASIC_DELINQUENCY_BUCKET(1); + + public final Integer value; + + DelinquencyBucket(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyRange.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyRange.java new file mode 100644 index 00000000000..266fe06ebe8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/DelinquencyRange.java @@ -0,0 +1,38 @@ +/** + * 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.test.data; + +public enum DelinquencyRange { + + NO_DELINQUENCY("NO_DELINQUENCY"), RANGE_1("Delinquency range 1"), RANGE_3("Delinquency range 3"), RANGE_30( + "Delinquency range 30"), RANGE_60("Delinquency range 60"), RANGE_90("Delinquency range 90"), RANGE_120( + "Delinquency range 120"), RANGE_150("Delinquency range 150"), RANGE_180( + "Delinquency range 180"), RANGE_210("Delinquency range 210"), RANGE_240("Delinquency range 240"); + + public final String value; + + DelinquencyRange(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ErrorMessageType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ErrorMessageType.java new file mode 100644 index 00000000000..bca2508f1a7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/ErrorMessageType.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum ErrorMessageType { + + CHARGED_OFF("Adding charge to Loan: %s is not allowed. Loan Account is Charged-off"); + + public final String value; + + ErrorMessageType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/FundId.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/FundId.java new file mode 100644 index 00000000000..d8bb3541b8a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/FundId.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum FundId { + + LENDER_A(1L), LENDER_B(2L); + + public final Long value; + + FundId(Long value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAType.java new file mode 100644 index 00000000000..0f2b0645e66 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum GLAType { + + ASSET(1), LIABILITY(2), EQUITY(3), INCOME(4), EXPENSE(5); + + public final Integer value; + + GLAType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAUsage.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAUsage.java new file mode 100644 index 00000000000..b136fcedc0b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/GLAUsage.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum GLAUsage { + + DETAIL(1), HEADER(2); + + public final Integer value; + + GLAUsage(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestCalculationPeriodTime.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestCalculationPeriodTime.java new file mode 100644 index 00000000000..ee4b6b5c5a7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestCalculationPeriodTime.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum InterestCalculationPeriodTime { + + DAILY(0), SAME_AS_REPAYMENT_PERIOD(1); + + public final Integer value; + + InterestCalculationPeriodTime(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRateFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRateFrequencyType.java new file mode 100644 index 00000000000..686b0fae735 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRateFrequencyType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum InterestRateFrequencyType { + + DAY(1), MONTH(2), YEAR(3), WHOLE_TERM(4); + + public final Integer value; + + InterestRateFrequencyType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRecalculationCompoundingMethod.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRecalculationCompoundingMethod.java new file mode 100644 index 00000000000..19749c9e4ea --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestRecalculationCompoundingMethod.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum InterestRecalculationCompoundingMethod { + + NONE(0), INTEREST(1), FEE(2), FEE_AND_INTEREST(3); + + public final Integer value; + + InterestRecalculationCompoundingMethod(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestType.java new file mode 100644 index 00000000000..fea20c87cfc --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/InterestType.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum InterestType { + + DECLINING_BALANCE(0), FLAT(1); + + public final Integer value; + + InterestType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java new file mode 100644 index 00000000000..148cd2c83a5 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanRescheduleErrorMessage.java @@ -0,0 +1,35 @@ +/** + * 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.test.data; + +public enum LoanRescheduleErrorMessage { + + LOAN_CHARGED_OFF("Loan: %s reschedule installment is not allowed. Loan Account is Charged-off"), LOAN_LOCKED_BY_COB( + "Loan is locked by the COB job. Loan ID: %s"); + + public final String value; + + LoanRescheduleErrorMessage(String value) { + this.value = value; + } + + public String getValue(Object... params) { + return String.format(this.value, params); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanStatus.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanStatus.java new file mode 100644 index 00000000000..a90e101a9fe --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanStatus.java @@ -0,0 +1,51 @@ +/** + * 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.test.data; + +import java.util.HashMap; +import java.util.Map; + +public enum LoanStatus { + + NONE(0), SUBMITTED_AND_PENDING_APPROVAL(100), APPROVED(200), ACTIVE(300), CLOSED_OBLIGATIONS_MET(600), OVERPAID( + 700), CLOSED_WRITTEN_OFF(601); + + public final Integer value; + + LoanStatus(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + + public LoanStatus getStatusByValue(Integer value) { + return BY_VALUE.get(value); + + } + + private static final Map BY_VALUE = new HashMap<>(); + + static { + for (LoanStatus e : values()) { + BY_VALUE.put(e.value, e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanTermFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanTermFrequencyType.java new file mode 100644 index 00000000000..899f0b3053a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/LoanTermFrequencyType.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum LoanTermFrequencyType { + + DAYS(0), WEEKS(1), MONTHS(2), YEARS(4); + + public final Integer value; + + LoanTermFrequencyType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/PreClosureInterestCalculationRule.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/PreClosureInterestCalculationRule.java new file mode 100644 index 00000000000..53ad9c8b384 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/PreClosureInterestCalculationRule.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum PreClosureInterestCalculationRule { + + TILL_PRE_CLOSE_DATE(1), TILL_REST_FREQUENCY_DATE(2); + + public final Integer value; + + PreClosureInterestCalculationRule(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationCompoundingFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationCompoundingFrequencyType.java new file mode 100644 index 00000000000..5c88415958b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationCompoundingFrequencyType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum RecalculationCompoundingFrequencyType { + + SAME_AS_REPAYMENT(1), DAILY(2), WEEKLY(3), MONTHLY(4); + + public final Integer value; + + RecalculationCompoundingFrequencyType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationRestFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationRestFrequencyType.java new file mode 100644 index 00000000000..669be121768 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RecalculationRestFrequencyType.java @@ -0,0 +1,30 @@ +/** + * 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.test.data; + +public enum RecalculationRestFrequencyType { + + SAME_AS_REPAYMENT(1), DAILY(2), WEEKLY(3), MONTHLY(4); + + public final Integer value; + + RecalculationRestFrequencyType(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RepaymentFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RepaymentFrequencyType.java new file mode 100644 index 00000000000..54cdc407f28 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/RepaymentFrequencyType.java @@ -0,0 +1,34 @@ +/** + * 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.test.data; + +public enum RepaymentFrequencyType { + + DAYS(0), WEEKS(1), MONTHS(2); + + public final Integer value; + + RepaymentFrequencyType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategy.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategy.java new file mode 100644 index 00000000000..947b9cf5bfd --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategy.java @@ -0,0 +1,31 @@ +/** + * 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.test.data; + +public enum TransactionProcessingStrategy { + + PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER(1), HEAVENSFAMILY_UNIQUE(2), CREOCORE_UNIQUE(3), OVERDUE_DUE_FEE_INT_PRINCIPAL( + 4), PRINCIPAL_INTEREST_PENALTIES_FEES_ORDER(5), INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER(6), EARLY_REPAYMENT_STRATEGY(7); + + public final Integer value; + + TransactionProcessingStrategy(Integer value) { + this.value = value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategyCode.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategyCode.java new file mode 100644 index 00000000000..ca86c7145e7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionProcessingStrategyCode.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.data; + +public enum TransactionProcessingStrategyCode { + + PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER("mifos-standard-strategy"), HEAVENSFAMILY_UNIQUE("heavensfamily-strategy"), CREOCORE_UNIQUE( + "creocore-strategy"), OVERDUE_DUE_FEE_INT_PRINCIPAL("rbi-india-strategy"), PRINCIPAL_INTEREST_PENALTIES_FEES_ORDER( + "principal-interest-penalties-fees-order-strategy"), INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER( + "interest-principal-penalties-fees-order-strategy"), EARLY_REPAYMENT_STRATEGY( + "early-repayment-strategy"), DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST( + "due-penalty-fee-interest-principal-in-advance-principal-penalty-fee-interest-strategy"), DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE( + "due-penalty-interest-principal-fee-in-advance-penalty-interest-principal-fee-strategy"), ADVANCED_PAYMENT_ALLOCATION( + "advanced-payment-allocation-strategy"); + + public final String value; + + TransactionProcessingStrategyCode(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionType.java new file mode 100644 index 00000000000..127833e404f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/TransactionType.java @@ -0,0 +1,36 @@ +/** + * 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.test.data; + +public enum TransactionType { + + DISBURSEMENT("disbursement"), REPAYMENT("repayment"), DOWN_PAYMENT("downPayment"), GOODWILL_CREDIT("goodwillCredit"), PAYOUT_REFUND( + "payoutRefund"), REFUND_BY_CASH("refundByCash"), MERCHANT_ISSUED_REFUND("merchantIssuedRefund"), CREDIT_BALANCE_REFUND( + "creditBalanceRefund"), CHARGEBACK("chargeback"), ACCRUAL("accrual"), CHARGE_OFF("chargeOff"); + + public final String value; + + TransactionType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountType.java new file mode 100644 index 00000000000..ca77c868b9e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountType.java @@ -0,0 +1,24 @@ +/** + * 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.test.data.accounttype; + +public interface AccountType { + + String getName(); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountTypeResolver.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountTypeResolver.java new file mode 100644 index 00000000000..0788f7b9530 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/AccountTypeResolver.java @@ -0,0 +1,58 @@ +/** + * 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.test.data.accounttype; + +import java.io.IOException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.models.GetGLAccountsResponse; +import org.apache.fineract.client.services.GeneralLedgerAccountApi; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +@Slf4j +public class AccountTypeResolver { + + private final GeneralLedgerAccountApi glaApi; + + @Cacheable(key = "#accountType.getName()", value = "accountTypesByName") + public long resolve(AccountType accountType) { + try { + String accountTypeName = accountType.getName(); + log.debug("Resolving account type by name [{}]", accountTypeName); + Response> response = glaApi.retrieveAllAccounts(null, "", 1, true, false, false).execute(); + if (!response.isSuccessful()) { + throw new IllegalStateException("Unable to get account types. Status code was HTTP " + response.code()); + } + List accountTypeResponses = response.body(); + GetGLAccountsResponse foundAtr = accountTypeResponses.stream()// + .filter(atr -> accountTypeName.equals(atr.getName()))// + .findAny()// + .orElseThrow(() -> new IllegalArgumentException("Account type [%s] not found".formatted(accountTypeName)));// + + return foundAtr.getId(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/DefaultAccountType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/DefaultAccountType.java new file mode 100644 index 00000000000..b1841e5af2d --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/accounttype/DefaultAccountType.java @@ -0,0 +1,55 @@ +/** + * 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.test.data.accounttype; + +public enum DefaultAccountType implements AccountType { + + // Asset + LOANS_RECEIVABLE("Loans Receivable"), INTEREST_FEE_RECEIVABLE("Interest/Fee Receivable"), OTHER_RECEIVABLES( + "Other Receivables"), UNC_RECEIVABLE("UNC Receivable"), FUND_RECEIVABLES( + "Fund Receivables"), TRANSFER_IN_SUSPENSE_ACCOUNT("Transfer in suspense account"), ASSET_TRANSFER("Asset transfer"), + // Income + DEFERRED_INTEREST_REVENUE("Deferred Interest Revenue"), RETAINED_EARNINGS_PRIOR_YEAR("Retained Earnings Prior Year"), INTEREST_INCOME( + "Interest Income"), FEE_INCOME("Fee Income"), FEE_CHARGE_OFF( + "Fee Charge Off"), RECOVERIES("Recoveries"), INTEREST_INCOME_CHARGE_OFF("Interest Income Charge Off"), + // Liability + AA_SUSPENSE_BALANCE("AA Suspense Balance"), SUSPENSE_CLEARING_ACCOUNT("Suspense/Clearing account"), OVERPAYMENT_ACCOUNT( + "Overpayment account"), + // Expense + CREDIT_LOSS_BAD_DEBT("Credit Loss/Bad Debt"), CREDIT_LOSS_BAD_DEBT_FRAUD("Credit Loss/Bad Debt-Fraud"), GOODWILL_EXPENSE_ACCOUNT( + "Goodwill Expense Account"), WRITTEN_OFF("Written off"); + + private final String customName; + + DefaultAccountType() { + this(null); + } + + DefaultAccountType(String customName) { + this.customName = customName; + } + + @Override + public String getName() { + if (customName != null) { + return customName; + } + return name(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableColumnType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableColumnType.java new file mode 100644 index 00000000000..8503e086b9e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableColumnType.java @@ -0,0 +1,37 @@ +/** + * 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.test.data.datatable; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.test.support.EnumResolver; + +@RequiredArgsConstructor +@Getter +public enum DatatableColumnType { + + STRING("string"), NUMBER("number"), BOOLEAN("boolean"), DECIMAL("decimal"), DATE("date"), DATETIME("datetime"), TEXT("text"), DROPDOWN( + "dropdown"); + + private final String typeString; + + public static DatatableColumnType fromTypeString(String columnType) { + return EnumResolver.from(DatatableColumnType.class, columnType, DatatableColumnType::getTypeString); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableEntityType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableEntityType.java new file mode 100644 index 00000000000..81acddfb251 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableEntityType.java @@ -0,0 +1,36 @@ +/** + * 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.test.data.datatable; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.test.support.EnumResolver; + +@RequiredArgsConstructor +@Getter +public enum DatatableEntityType { + + LOAN("m_loan"); + + private final String referencedTableName; + + public static DatatableEntityType fromString(String entityType) { + return EnumResolver.fromString(DatatableEntityType.class, entityType); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableNameGenerator.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableNameGenerator.java new file mode 100644 index 00000000000..4f99baba39e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/datatable/DatatableNameGenerator.java @@ -0,0 +1,30 @@ +/** + * 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.test.data.datatable; + +import org.apache.fineract.test.helper.Utils; +import org.springframework.stereotype.Component; + +@Component +public class DatatableNameGenerator { + + public String generate(DatatableEntityType entityType) { + return Utils.randomStringGenerator("dt_%s_".formatted(entityType.getReferencedTableName()), 5).toLowerCase(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/DefaultJob.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/DefaultJob.java new file mode 100644 index 00000000000..cc80f2f3f1f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/DefaultJob.java @@ -0,0 +1,37 @@ +/** + * 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.test.data.job; + +public enum DefaultJob implements Job { + + ADD_ACCRUAL_TRANSACTIONS("Add Accrual Transactions"), ADD_PERIODIC_ACCRUAL_TRANSACTIONS( + "Add Periodic Accrual Transactions"), INCREASE_BUSINESS_DAY("Increase Business Date by 1 day"), LOAN_DELINQUENCY_CLASSIFICATION( + "Loan Delinquency Classification"), LOAN_COB("Loan COB"); + + private final String customName; + + DefaultJob(String customName) { + this.customName = customName; + } + + @Override + public String getName() { + return customName; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/Job.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/Job.java new file mode 100644 index 00000000000..76354b28239 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/Job.java @@ -0,0 +1,24 @@ +/** + * 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.test.data.job; + +public interface Job { + + String getName(); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/JobResolver.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/JobResolver.java new file mode 100644 index 00000000000..affecbc6f23 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/job/JobResolver.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.data.job; + +import java.io.IOException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.models.GetJobsResponse; +import org.apache.fineract.client.services.SchedulerJobApi; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +@Slf4j +public class JobResolver { + + private final SchedulerJobApi schedulerJobApi; + + @Cacheable(key = "#job.getName()", value = "jobsByName") + public long resolve(Job job) { + try { + String jobName = job.getName(); + log.debug("Resolving job by name [{}]", jobName); + Response> response = schedulerJobApi.retrieveAll8().execute(); + if (!response.isSuccessful()) { + throw new IllegalStateException("Unable to get jobs list. Status code was HTTP " + response.code()); + } + + List jobsResponses = response.body(); + GetJobsResponse foundJob = jobsResponses.stream().filter(j -> jobName.equals(j.getDisplayName())).findAny() + .orElseThrow(() -> new IllegalArgumentException("Job [%s] not found".formatted(jobName))); + return foundJob.getJobId(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java new file mode 100644 index 00000000000..9a4828a5954 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java @@ -0,0 +1,29 @@ +/** + * 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.test.data.loanproduct; + +public enum DefaultLoanProduct implements LoanProduct { + + PIN30, PIN30_DUE_DATE, PIN30_INTEREST_FLAT, PIN30_INTEREST_DECLINING_BALANCE_PERIOD_SAME_AS_PAYMENT, PIN30_INTEREST_DECLINING_BALANCE_PERIOD_DAILY, PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY, PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE, PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INST, PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_RESCH_NEXT_REP, PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE, PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTIDISB, PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE, PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT, PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE, PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT, PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT, PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST, PIN4_DOWNPAYMENT, PIN4_DOWNPAYMENT_AUTO, PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION, PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION, PIN4_DOWNPAYMENT_INTEREST, PIN4_DOWNPAYMENT_INTEREST_AUTO, PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL, PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY, PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION, PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH; + + @Override + public String getName() { + return name(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProduct.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProduct.java new file mode 100644 index 00000000000..4ffc3541af7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProduct.java @@ -0,0 +1,24 @@ +/** + * 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.test.data.loanproduct; + +public interface LoanProduct { + + String getName(); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java new file mode 100644 index 00000000000..3f62a675951 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.data.loanproduct; + +import java.io.IOException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.models.GetLoanProductsResponse; +import org.apache.fineract.client.services.LoanProductsApi; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +@Slf4j +public class LoanProductResolver { + + private final LoanProductsApi loanProductsApi; + + @Cacheable(key = "#loanProduct.getName()", value = "loanProductsByName") + public long resolve(LoanProduct loanProduct) { + try { + String loanProductName = loanProduct.getName(); + log.debug("Resolving loan product by name [{}]", loanProductName); + Response> response = loanProductsApi.retrieveAllLoanProducts().execute(); + if (!response.isSuccessful()) { + throw new IllegalStateException("Unable to get loan products. Status code was HTTP " + response.code()); + } + + List loanProductsResponses = response.body(); + GetLoanProductsResponse foundLpr = loanProductsResponses.stream().filter(lpr -> loanProductName.equals(lpr.getName())).findAny() + .orElseThrow(() -> new IllegalArgumentException("Loan product [%s] not found".formatted(loanProductName))); + return foundLpr.getId(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/DefaultPaymentType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/DefaultPaymentType.java new file mode 100644 index 00000000000..bc645facc21 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/DefaultPaymentType.java @@ -0,0 +1,44 @@ +/** + * 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.test.data.paymenttype; + +public enum DefaultPaymentType implements PaymentType { + + MONEY_TRANSFER("Money Transfer"), // This is how Fineract defines the payment type + REPAYMENT_ADJUSTMENT_CHARGEBACK("Repayment Adjustment Chargeback"), REPAYMENT_ADJUSTMENT_REFUND( + "Repayment Adjustment Refund"), AUTOPAY, DOWN_PAYMENT, REAL_TIME, SCHEDULED, CHECK_PAYMENT, OCA_PAYMENT; + + private final String customName; + + DefaultPaymentType() { + this(null); + } + + DefaultPaymentType(String customName) { + this.customName = customName; + } + + @Override + public String getName() { + if (customName != null) { + return customName; + } + return name(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentType.java new file mode 100644 index 00000000000..3e24e56d0b4 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentType.java @@ -0,0 +1,24 @@ +/** + * 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.test.data.paymenttype; + +public interface PaymentType { + + String getName(); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentTypeResolver.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentTypeResolver.java new file mode 100644 index 00000000000..4c69195456f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/paymenttype/PaymentTypeResolver.java @@ -0,0 +1,57 @@ +/** + * 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.test.data.paymenttype; + +import java.io.IOException; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.models.GetPaymentTypesResponse; +import org.apache.fineract.client.services.PaymentTypeApi; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +@Slf4j +public class PaymentTypeResolver { + + private final PaymentTypeApi paymentTypeApi; + + @Cacheable(key = "#paymentType.getName()", value = "paymentTypesByName") + public long resolve(PaymentType paymentType) { + try { + String paymentTypeName = paymentType.getName(); + log.debug("Resolving payment type by name [{}]", paymentTypeName); + Response> response = paymentTypeApi.getAllPaymentTypes(false).execute(); + if (!response.isSuccessful()) { + throw new IllegalStateException("Unable to get payment types. Status code was HTTP " + response.code()); + } + + List paymentTypesResponses = response.body(); + GetPaymentTypesResponse foundPtr = paymentTypesResponses.stream().filter(ptr -> paymentTypeName.equals(ptr.getName())).findAny() + .orElseThrow(() -> new IllegalArgumentException("Payment type [%s] not found".formatted(paymentTypeName))); + + return foundPtr.getId(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/GLAccountRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/GLAccountRequestFactory.java new file mode 100644 index 00000000000..30016b07eff --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/GLAccountRequestFactory.java @@ -0,0 +1,31 @@ +/** + * 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.test.factory; + +import org.apache.fineract.client.models.PostGLAccountsRequest; + +public final class GLAccountRequestFactory { + + private GLAccountRequestFactory() {} + + public static PostGLAccountsRequest defaultGLAccountRequest(String name, String glCode, Integer type, Integer usage, + Boolean manualEntriesAllowed) { + return new PostGLAccountsRequest().name(name).glCode(glCode).type(type).usage(usage).manualEntriesAllowed(manualEntriesAllowed); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanChargeRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanChargeRequestFactory.java new file mode 100644 index 00000000000..975b77db4fa --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanChargeRequestFactory.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.factory; + +import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest; +import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest; + +public final class LoanChargeRequestFactory { + + public static final String DEFAULT_DATE_FORMAT = "dd MMMM yyyy"; + public static final String DEFAULT_LOCALE = "en"; + public static final Long DEFAULT_CHARGE_ID = 1L; + public static final double DEFAULT_CHARGE_AMOUNT = 1; + + private LoanChargeRequestFactory() {} + + public static PostLoansLoanIdChargesRequest defaultLoanChargeRequest() { + return new PostLoansLoanIdChargesRequest().chargeId(DEFAULT_CHARGE_ID).amount(DEFAULT_CHARGE_AMOUNT).locale(DEFAULT_LOCALE) + .dateFormat(DEFAULT_DATE_FORMAT); + } + + public static PostLoansLoanIdChargesChargeIdRequest defaultLoanChargeWaiveRequest(String dueDate) { + return new PostLoansLoanIdChargesChargeIdRequest().dateFormat(DEFAULT_DATE_FORMAT).locale(DEFAULT_LOCALE).transactionDate(dueDate); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java new file mode 100644 index 00000000000..96ab1c5357e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanProductsRequestFactory.java @@ -0,0 +1,877 @@ +/** + * 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.test.factory; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.AllowAttributeOverrides; +import org.apache.fineract.client.models.ChargeData; +import org.apache.fineract.client.models.ChargeToGLAccountMapper; +import org.apache.fineract.client.models.GetLoanFeeToIncomeAccountMappings; +import org.apache.fineract.client.models.GetLoanPaymentChannelToFundSourceMappings; +import org.apache.fineract.client.models.PostLoanProductsRequest; +import org.apache.fineract.test.data.AccountingRule; +import org.apache.fineract.test.data.AdvancePaymentsAdjustmentType; +import org.apache.fineract.test.data.AmortizationType; +import org.apache.fineract.test.data.DaysInMonthType; +import org.apache.fineract.test.data.DaysInYearType; +import org.apache.fineract.test.data.DelinquencyBucket; +import org.apache.fineract.test.data.FundId; +import org.apache.fineract.test.data.InterestCalculationPeriodTime; +import org.apache.fineract.test.data.InterestRateFrequencyType; +import org.apache.fineract.test.data.InterestRecalculationCompoundingMethod; +import org.apache.fineract.test.data.InterestType; +import org.apache.fineract.test.data.PreClosureInterestCalculationRule; +import org.apache.fineract.test.data.RecalculationCompoundingFrequencyType; +import org.apache.fineract.test.data.RecalculationRestFrequencyType; +import org.apache.fineract.test.data.RepaymentFrequencyType; +import org.apache.fineract.test.data.TransactionProcessingStrategyCode; +import org.apache.fineract.test.data.accounttype.AccountTypeResolver; +import org.apache.fineract.test.data.accounttype.DefaultAccountType; +import org.apache.fineract.test.data.paymenttype.DefaultPaymentType; +import org.apache.fineract.test.data.paymenttype.PaymentTypeResolver; +import org.apache.fineract.test.helper.Utils; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class LoanProductsRequestFactory { + + private final PaymentTypeResolver paymentTypeResolver; + private final AccountTypeResolver accountTypeResolver; + + public static final String NAME_PREFIX = "Pin30-"; + public static final String NAME_PREFIX_PIN4 = "Pin4-"; + public static final String NAME_PREFIX_INTEREST_FLAT = "Pin30InterestFlat-"; + public static final String NAME_PREFIX_INTEREST_FLAT_PIN4 = "Pin4InterestFlat-"; + public static final String NAME_PREFIX_INTEREST_DECLINING = "Pin30InterestDeclining-"; + public static final String NAME_PREFIX_INTEREST_DECLINING_RECALCULATION = "Pin30InterestDecliningRecalculation-"; + public static final String SHORT_NAME_PREFIX = "p"; + public static final String SHORT_NAME_PREFIX_INTEREST = "i"; + public static final String DATE_FORMAT = "dd MMMM yyyy"; + public static final String LOCALE_EN = "en"; + public static final String DESCRIPTION = "Pay in 30 days product"; + public static final String DESCRIPTION_PIN4 = "Pay in 4 product"; + public static final String DESCRIPTION_INTEREST_FLAT = "Pay in 30 days product with 12% interest - FLAT"; + public static final String DESCRIPTION_INTEREST_FLAT_PIN4 = "Pay in 4 product with 12% interest - FLAT"; + public static final String DESCRIPTION_INTEREST_DECLINING = "Pay in 30 days product with 12% interest - DECLINING BALANCE"; + public static final String DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY = "PIN30-1MONTH with 12% DECLINING BALANCE interest, interest period: Daily, Interest recalculation-Monthly, Compounding:Interest"; + public static final String DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE = "PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest recalculation-Daily, Compounding:none"; + public static final Long FUND_ID = FundId.LENDER_A.value; + public static final String CURRENCY_CODE = "EUR"; + public static final Integer INTEREST_RATE_FREQUENCY_TYPE_MONTH = InterestRateFrequencyType.MONTH.value; + public static final Integer INTEREST_RATE_FREQUENCY_TYPE_YEAR = InterestRateFrequencyType.YEAR.value; + public static final Long REPAYMENT_FREQUENCY_TYPE_DAYS = RepaymentFrequencyType.DAYS.value.longValue(); + public static final Long REPAYMENT_FREQUENCY_TYPE_MONTHS = RepaymentFrequencyType.MONTHS.value.longValue(); + public static final Integer AMORTIZATION_TYPE = AmortizationType.EQUAL_INSTALLMENTS.value; + public static final Integer INTEREST_TYPE_DECLINING_BALANCE = InterestType.DECLINING_BALANCE.value; + public static final Integer INTEREST_TYPE_FLAT = InterestType.FLAT.value; + public static final Integer INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT = InterestCalculationPeriodTime.SAME_AS_REPAYMENT_PERIOD.value; + public static final Integer INTEREST_CALCULATION_PERIOD_TYPE_DAILY = InterestCalculationPeriodTime.DAILY.value; + public static final String TRANSACTION_PROCESSING_STRATEGY_CODE = TransactionProcessingStrategyCode.PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER.value; + public static final Integer DAYS_IN_YEAR_TYPE = DaysInYearType.ACTUAL.value; + public static final Integer DAYS_IN_MONTH_TYPE = DaysInMonthType.ACTUAL.value; + public static final Integer LOAN_ACCOUNTING_RULE = AccountingRule.ACCRUAL_PERIODIC.value; + public static final String OVER_APPLIED_CALCULATION_TYPE = "percentage"; + public static final Integer OVER_APPLIED_NUMBER = 50; + public static final Integer DELINQUENCY_BUCKET_ID = DelinquencyBucket.BASIC_DELINQUENCY_BUCKET.value; + public static final Integer PRE_CLOSURE_INTEREST_CALCULATION_RULE_TILL_PRE_CLOSE_DATE = PreClosureInterestCalculationRule.TILL_PRE_CLOSE_DATE.value; + public static final Integer ADVANCE_PAYMENT_ADJUSTMENT_TYPE_REDUCE_EMI_AMOUNT = AdvancePaymentsAdjustmentType.REDUCE_EMI_AMOUNT.value; + public static final Integer INTEREST_RECALCULATION_COMPOUND_METHOD_INTEREST = InterestRecalculationCompoundingMethod.INTEREST.value; + public static final Integer INTEREST_RECALCULATION_COMPOUND_METHOD_NONE = InterestRecalculationCompoundingMethod.NONE.value; + public static final Integer FREQUENCY_FOR_COMPOUNDING_SAME_AS_REPAYMENT = RecalculationCompoundingFrequencyType.SAME_AS_REPAYMENT.value; + public static final Integer FREQUENCY_FOR_COMPOUNDING_MONTHLY = RecalculationCompoundingFrequencyType.MONTHLY.value; + public static final Integer FREQUENCY_FOR_RECALCULATE_OUTSTANDING_PRINCIPAL_SAME_AS_REPAYMENT = RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value; + public static final Integer FREQUENCY_FOR_RECALCULATE_OUTSTANDING_DAILY = RecalculationRestFrequencyType.DAILY.value; + + public PostLoanProductsRequest defaultLoanProductsRequestPin30() { + String name = Utils.randomNameGenerator(NAME_PREFIX, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION)// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(0)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(1)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 0)// + .maxInterestRatePerPeriod((double) 0)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_MONTH)// + .repaymentEvery(30)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_DECLINING_BALANCE)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .isInterestRecalculationEnabled(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(true)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true))// + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(true)// + .allowApprovedDisbursedAmountsOverApplied(true)// + .overAppliedCalculationType(OVER_APPLIED_CALCULATION_TYPE)// + .overAppliedNumber(OVER_APPLIED_NUMBER)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin30InterestFlat() { + String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_FLAT, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_INTEREST_FLAT)// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(0)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(1)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 12)// + .maxInterestRatePerPeriod((double) 30)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_YEAR)// + .repaymentEvery(30)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_FLAT)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .isInterestRecalculationEnabled(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(false)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true)) + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(false)// + .allowApprovedDisbursedAmountsOverApplied(false)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin30InterestDeclining() { + String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_DECLINING, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_INTEREST_DECLINING)// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(0)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(1)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 12)// + .maxInterestRatePerPeriod((double) 30)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_YEAR)// + .repaymentEvery(30)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_DECLINING_BALANCE)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .isInterestRecalculationEnabled(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(false)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true)) + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(false)// + .allowApprovedDisbursedAmountsOverApplied(false)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin301MonthInterestDecliningBalanceDailyRecalculationCompoundingMonthly() { + String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_DECLINING_RECALCULATION, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY)// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(1)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(1)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 12)// + .maxInterestRatePerPeriod((double) 30)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_YEAR)// + .repaymentEvery(1)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_MONTHS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_DECLINING_BALANCE)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_DAILY)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(false)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true)) + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(false)// + .allowApprovedDisbursedAmountsOverApplied(false)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .isInterestRecalculationEnabled(true)// + .preClosureInterestCalculationStrategy(PRE_CLOSURE_INTEREST_CALCULATION_RULE_TILL_PRE_CLOSE_DATE)// + .rescheduleStrategyMethod(ADVANCE_PAYMENT_ADJUSTMENT_TYPE_REDUCE_EMI_AMOUNT)// + .interestRecalculationCompoundingMethod(INTEREST_RECALCULATION_COMPOUND_METHOD_INTEREST)// + .recalculationCompoundingFrequencyType(FREQUENCY_FOR_COMPOUNDING_MONTHLY)// + .recalculationRestFrequencyType(FREQUENCY_FOR_RECALCULATE_OUTSTANDING_DAILY)// + .recalculationRestFrequencyInterval(1)// + .recalculationCompoundingFrequencyInterval(1)// + .recalculationCompoundingFrequencyOnDayType(1);// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone() { + String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_DECLINING_RECALCULATION, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE)// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(1)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(1)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 12)// + .maxInterestRatePerPeriod((double) 30)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_YEAR)// + .repaymentEvery(30)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_DECLINING_BALANCE)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_DAILY)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(false)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true)) + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(false)// + .allowApprovedDisbursedAmountsOverApplied(false)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .isInterestRecalculationEnabled(true)// + .preClosureInterestCalculationStrategy(PRE_CLOSURE_INTEREST_CALCULATION_RULE_TILL_PRE_CLOSE_DATE)// + .rescheduleStrategyMethod(ADVANCE_PAYMENT_ADJUSTMENT_TYPE_REDUCE_EMI_AMOUNT)// + .interestRecalculationCompoundingMethod(INTEREST_RECALCULATION_COMPOUND_METHOD_NONE)// + .recalculationRestFrequencyType(FREQUENCY_FOR_RECALCULATE_OUTSTANDING_DAILY)// + .recalculationRestFrequencyInterval(1);// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin4() { + String name = Utils.randomNameGenerator(NAME_PREFIX_PIN4, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_PIN4)// + .enableDownPayment(true)// + .enableAutoRepaymentForDownPayment(true)// + .disbursedAmountPercentageForDownPayment(new BigDecimal(25))// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(0)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(3)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 0)// + .maxInterestRatePerPeriod((double) 0)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_MONTH)// + .repaymentEvery(15)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_DECLINING_BALANCE)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .isInterestRecalculationEnabled(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(true)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true))// + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(true)// + .allowApprovedDisbursedAmountsOverApplied(true)// + .overAppliedCalculationType(OVER_APPLIED_CALCULATION_TYPE)// + .overAppliedNumber(OVER_APPLIED_NUMBER)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));// + } + + public PostLoanProductsRequest defaultLoanProductsRequestPin4InterestFlat() { + String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_FLAT_PIN4, 4); + String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3); + + List principalVariationsForBorrowerCycle = new ArrayList<>(); + List numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>(); + List interestRateVariationsForBorrowerCycle = new ArrayList<>(); + List charges = new ArrayList<>(); + List penaltyToIncomeAccountMappings = new ArrayList<>(); + List feeToIncomeAccountMappings = new ArrayList<>(); + + List paymentChannelToFundSourceMappings = new ArrayList<>(); + GetLoanPaymentChannelToFundSourceMappings loanPaymentChannelToFundSourceMappings = new GetLoanPaymentChannelToFundSourceMappings(); + loanPaymentChannelToFundSourceMappings.fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.FUND_RECEIVABLES)); + loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeResolver.resolve(DefaultPaymentType.MONEY_TRANSFER)); + paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings); + + return new PostLoanProductsRequest()// + .name(name)// + .shortName(shortName)// + .description(DESCRIPTION_INTEREST_FLAT_PIN4)// + .enableDownPayment(true)// + .enableAutoRepaymentForDownPayment(true)// + .disbursedAmountPercentageForDownPayment(new BigDecimal(25))// + .fundId(FUND_ID)// + .startDate(null)// + .closeDate(null)// + .includeInBorrowerCycle(false)// + .currencyCode(CURRENCY_CODE)// + .digitsAfterDecimal(2)// + .inMultiplesOf(0)// + .installmentAmountInMultiplesOf(1)// + .useBorrowerCycle(false)// + .minPrincipal(100.0)// + .principal(1000.0)// + .maxPrincipal(10000.0)// + .minNumberOfRepayments(1)// + .numberOfRepayments(3)// + .maxNumberOfRepayments(30)// + .isLinkedToFloatingInterestRates(false)// + .minInterestRatePerPeriod((double) 0)// + .interestRatePerPeriod((double) 12)// + .maxInterestRatePerPeriod((double) 30)// + .interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_YEAR)// + .repaymentEvery(15)// + .repaymentFrequencyType(REPAYMENT_FREQUENCY_TYPE_DAYS)// + .principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)// + .numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)// + .interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)// + .amortizationType(AMORTIZATION_TYPE)// + .interestType(INTEREST_TYPE_FLAT)// + .isEqualAmortization(false)// + .interestCalculationPeriodType(INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT)// + .transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE)// + .daysInYearType(DAYS_IN_YEAR_TYPE)// + .daysInMonthType(DAYS_IN_MONTH_TYPE)// + .canDefineInstallmentAmount(true)// + .graceOnArrearsAgeing(3)// + .overdueDaysForNPA(179)// + .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)// + .principalThresholdForLastInstallment(50)// + .allowVariableInstallments(false)// + .canUseForTopup(false)// + .isInterestRecalculationEnabled(false)// + .holdGuaranteeFunds(false)// + .multiDisburseLoan(false)// + .allowAttributeOverrides(new AllowAttributeOverrides()// + .amortizationType(true)// + .interestType(true)// + .transactionProcessingStrategyCode(true)// + .interestCalculationPeriodType(true)// + .inArrearsTolerance(true)// + .repaymentEvery(true)// + .graceOnPrincipalAndInterestPayment(true)// + .graceOnArrearsAgeing(true)) + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0)// + .charges(charges)// + .accountingRule(LOAN_ACCOUNTING_RULE)// + .fundSourceAccountId(accountTypeResolver.resolve(DefaultAccountType.SUSPENSE_CLEARING_ACCOUNT))// + .loanPortfolioAccountId(accountTypeResolver.resolve(DefaultAccountType.LOANS_RECEIVABLE))// + .transfersInSuspenseAccountId(accountTypeResolver.resolve(DefaultAccountType.TRANSFER_IN_SUSPENSE_ACCOUNT))// + .interestOnLoanAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))// + .incomeFromFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_INCOME))// + .incomeFromRecoveryAccountId(accountTypeResolver.resolve(DefaultAccountType.RECOVERIES))// + .writeOffAccountId(accountTypeResolver.resolve(DefaultAccountType.WRITTEN_OFF))// + .overpaymentLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))// + .receivableInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivableFeeAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .receivablePenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_FEE_RECEIVABLE))// + .dateFormat(DATE_FORMAT)// + .locale(LOCALE_EN)// + .disallowExpectedDisbursements(false)// + .allowApprovedDisbursedAmountsOverApplied(false)// + .delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())// + .goodwillCreditAccountId(accountTypeResolver.resolve(DefaultAccountType.GOODWILL_EXPENSE_ACCOUNT))// + .incomeFromGoodwillCreditInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromGoodwillCreditFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .incomeFromGoodwillCreditPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)// + .penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)// + .feeToIncomeAccountMappings(feeToIncomeAccountMappings)// + .incomeFromChargeOffInterestAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME_CHARGE_OFF))// + .incomeFromChargeOffFeesAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF))// + .chargeOffExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT))// + .chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))// + .incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));// + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanRequestFactory.java new file mode 100644 index 00000000000..a8476fc6f5c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/LoanRequestFactory.java @@ -0,0 +1,267 @@ +/** + * 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.test.factory; + +import java.math.BigDecimal; +import java.time.Clock; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest; +import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest; +import org.apache.fineract.client.models.PostLoansLoanIdRequest; +import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; +import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest; +import org.apache.fineract.client.models.PostLoansRequest; +import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest; +import org.apache.fineract.client.models.PutLoansLoanIdRequest; +import org.apache.fineract.test.data.InterestCalculationPeriodTime; +import org.apache.fineract.test.data.InterestType; +import org.apache.fineract.test.data.LoanTermFrequencyType; +import org.apache.fineract.test.data.RepaymentFrequencyType; +import org.apache.fineract.test.data.TransactionProcessingStrategyCode; +import org.apache.fineract.test.data.loanproduct.DefaultLoanProduct; +import org.apache.fineract.test.data.loanproduct.LoanProductResolver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class LoanRequestFactory { + + @Autowired + private LoanProductResolver loanProductResolver; + + public static final String DATE_FORMAT = "dd MMMM yyyy"; + public static final String DEFAULT_LOCALE = "en"; + public static final DefaultLoanProduct DEFAULT_LOAN_PRODUCT = DefaultLoanProduct.valueOf("PIN30"); + public static final Double DEFAULT_PAYMENT_TRANSACTION_AMOUNT = 200.00; + public static final Double DEFAULT_UNDO_TRANSACTION_AMOUNT = 0.0; + public static final Double DEFAULT_REPAYMENT_TRANSACTION_AMOUNT = 200.00; + public static final Double DEFAULT_CHARGEBACK_TRANSACTION_AMOUNT = 250.00; + public static final Double DEFAULT_CHARGE_ADJUSTMENT_TRANSACTION_AMOUNT = 10.00; + public static final String DEFAULT_EXTERNAL_ID = ""; + public static final Long DEFAULT_PAYMENT_TYPE_ID = 4L; + public static final Long DEFAULT_PAYMENT_TYPE_ID_CHARGEBACK = 8L; + public static final BigDecimal DEFAULT_PRINCIPAL = BigDecimal.valueOf(1000L); + public static final BigDecimal DEFAULT_APPROVED_AMOUNT = BigDecimal.valueOf(1000L); + public static final BigDecimal DEFAULT_DISBURSED_AMOUNT = BigDecimal.valueOf(1000L); + public static final Integer DEFAULT_LOAN_TERM_FREQUENCY = 30; + public static final Integer DEFAULT_LOAN_TERM_FREQUENCY_TYPE = LoanTermFrequencyType.DAYS.value; + public static final Integer DEFAULT_REPAYMENT_FREQUENCY_TYPE = RepaymentFrequencyType.DAYS.value; + public static final Integer DEFAULT_REAGING_FREQUENCY_NUMBER = 1; + public static final String DEFAULT_REAGING_FREQUENCY_TYPE = "MONTHS"; + public static final BigDecimal DEFAULT_INTEREST_RATE_PER_PERIOD = new BigDecimal(0); + public static final Integer DEFAULT_INTEREST_TYPE = InterestType.FLAT.value; + public static final Integer DEFAULT_INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT_PERIOD = InterestCalculationPeriodTime.SAME_AS_REPAYMENT_PERIOD.value; + public static final Integer DEFAULT_AMORTIZATION_TYPE = 1; + public static final String DEFAULT_LOAN_TYPE = "individual"; + public static final Integer DEFAULT_NUMBER_OF_REPAYMENTS = 1; + public static final Integer DEFAULT_NUMBER_OF_INSTALLMENTS = 5; + public static final Integer DEFAULT_REPAYMENT_FREQUENCY = 30; + public static final String DEFAULT_TRANSACTION_PROCESSING_STRATEGY_CODE = TransactionProcessingStrategyCode.PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER.value; + + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT); + public static final String DATE_SUBMIT_STRING = FORMATTER.format(LocalDate.now(Clock.systemUTC()).minusMonths(1L)); + public static final String DEFAULT_TRANSACTION_DATE = FORMATTER.format(LocalDate.now(Clock.systemUTC()).minusMonths(1L)); + + public PostLoansRequest defaultLoansRequest(Long clientId) { + return new PostLoansRequest()// + .clientId(clientId)// + .productId(loanProductResolver.resolve(DEFAULT_LOAN_PRODUCT))// + .submittedOnDate(DATE_SUBMIT_STRING)// + .expectedDisbursementDate(DATE_SUBMIT_STRING)// + .principal(DEFAULT_PRINCIPAL)// + .locale(DEFAULT_LOCALE)// + .loanTermFrequency(DEFAULT_LOAN_TERM_FREQUENCY)// + .loanTermFrequencyType(DEFAULT_LOAN_TERM_FREQUENCY_TYPE)// + .loanType(DEFAULT_LOAN_TYPE)// + .numberOfRepayments(DEFAULT_NUMBER_OF_REPAYMENTS)// + .repaymentEvery(DEFAULT_REPAYMENT_FREQUENCY)// + .repaymentFrequencyType(DEFAULT_REPAYMENT_FREQUENCY_TYPE)// + .interestRatePerPeriod(DEFAULT_INTEREST_RATE_PER_PERIOD)// + .interestType(DEFAULT_INTEREST_TYPE)// + .interestCalculationPeriodType(DEFAULT_INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT_PERIOD)// + .amortizationType(DEFAULT_AMORTIZATION_TYPE)// + .transactionProcessingStrategyCode(DEFAULT_TRANSACTION_PROCESSING_STRATEGY_CODE)// + .dateFormat(DATE_FORMAT)// + .graceOnArrearsAgeing(3)// + .maxOutstandingLoanBalance(new BigDecimal(10000)); + } + + public PutLoansLoanIdRequest modifySubmittedOnDateOnLoan(Long clientId, String newSubmittedOnDate) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); + String dateDisburseStr = formatter.format(LocalDate.now(Clock.systemUTC())); + + return new PutLoansLoanIdRequest()// + .productId(loanProductResolver.resolve(DEFAULT_LOAN_PRODUCT))// + .submittedOnDate(newSubmittedOnDate)// + .expectedDisbursementDate(dateDisburseStr)// + .linkAccountId(null)// + .createStandingInstructionAtDisbursement(null)// + .loanTermFrequency(DEFAULT_LOAN_TERM_FREQUENCY)// + .loanTermFrequencyType(DEFAULT_LOAN_TERM_FREQUENCY_TYPE)// + .numberOfRepayments(DEFAULT_NUMBER_OF_REPAYMENTS)// + .repaymentEvery(DEFAULT_REPAYMENT_FREQUENCY)// + .repaymentFrequencyType(DEFAULT_REPAYMENT_FREQUENCY_TYPE)// + .repaymentFrequencyNthDayType(null)// + .repaymentFrequencyDayOfWeekType(null)// + .repaymentsStartingFromDate(null)// + .interestChargedFromDate(null)// + .interestRatePerPeriod(DEFAULT_INTEREST_RATE_PER_PERIOD)// + .interestType(DEFAULT_INTEREST_TYPE)// + .interestCalculationPeriodType(DEFAULT_INTEREST_CALCULATION_PERIOD_TYPE_SAME_AS_REPAYMENT_PERIOD)// + .amortizationType(DEFAULT_AMORTIZATION_TYPE)// + .isEqualAmortization(false)// + .transactionProcessingStrategyCode(DEFAULT_TRANSACTION_PROCESSING_STRATEGY_CODE)// + .graceOnArrearsAgeing(3)// + .loanIdToClose(null)// + .isTopup(null)// + .maxOutstandingLoanBalance(10000L)// + .charges(new ArrayList<>())// + .collateral(new ArrayList<>())// + .disbursementData(new ArrayList<>())// + .clientId(clientId)// + .dateFormat("dd MMMM yyyy")// + .locale("en")// + .loanType("individual")// + .principal(DEFAULT_PRINCIPAL.longValue());// + } + + public static PutLoansLoanIdRequest enableFraudFlag() { + return new PutLoansLoanIdRequest().fraud(true); + } + + public static PutLoansLoanIdRequest disableFraudFlag() { + return new PutLoansLoanIdRequest().fraud(false); + } + + public static PostLoansLoanIdRequest defaultLoanApproveRequest() { + return new PostLoansLoanIdRequest()// + .approvedOnDate(DATE_SUBMIT_STRING)// + .expectedDisbursementDate(DATE_SUBMIT_STRING)// + .approvedLoanAmount(DEFAULT_APPROVED_AMOUNT)// + .dateFormat(DATE_FORMAT)// + .locale(DEFAULT_LOCALE);// + } + + public static PostLoansLoanIdRequest defaultLoanDisburseRequest() { + return new PostLoansLoanIdRequest().actualDisbursementDate(DATE_SUBMIT_STRING).transactionAmount(DEFAULT_DISBURSED_AMOUNT) + .paymentTypeId(Math.toIntExact(DEFAULT_PAYMENT_TYPE_ID)).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsRequest defaultPaymentTransactionRequest() { + return new PostLoansLoanIdTransactionsRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_PAYMENT_TRANSACTION_AMOUNT).paymentTypeId(DEFAULT_PAYMENT_TYPE_ID).dateFormat(DATE_FORMAT) + .locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsRequest defaultRepaymentRequest() { + return new PostLoansLoanIdTransactionsRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_REPAYMENT_TRANSACTION_AMOUNT).paymentTypeId(DEFAULT_PAYMENT_TYPE_ID).dateFormat(DATE_FORMAT) + .locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsRequest defaultRefundRequest() { + return new PostLoansLoanIdTransactionsRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_REPAYMENT_TRANSACTION_AMOUNT).paymentTypeId(DEFAULT_PAYMENT_TYPE_ID).dateFormat(DATE_FORMAT) + .locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultRepaymentUndoRequest() { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_UNDO_TRANSACTION_AMOUNT).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultRepaymentAdjustRequest(double amount) { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(DEFAULT_TRANSACTION_DATE).transactionAmount(amount) + .dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultTransactionUndoRequest() { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_UNDO_TRANSACTION_AMOUNT).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultRefundUndoRequest() { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_UNDO_TRANSACTION_AMOUNT).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultChargebackRequest() { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionAmount(DEFAULT_CHARGEBACK_TRANSACTION_AMOUNT) + .locale(DEFAULT_LOCALE).paymentTypeId(DEFAULT_PAYMENT_TYPE_ID_CHARGEBACK); + } + + public static PostLoansLoanIdChargesChargeIdRequest defaultChargeAdjustmentRequest() { + return new PostLoansLoanIdChargesChargeIdRequest().amount(DEFAULT_CHARGE_ADJUSTMENT_TRANSACTION_AMOUNT) + .externalId(DEFAULT_EXTERNAL_ID); + } + + public static PostLoansLoanIdTransactionsTransactionIdRequest defaultChargeAdjustmentTransactionUndoRequest() { + return new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(DEFAULT_TRANSACTION_DATE) + .transactionAmount(DEFAULT_UNDO_TRANSACTION_AMOUNT).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsRequest defaultChargeOffRequest() { + return new PostLoansLoanIdTransactionsRequest().transactionDate(DEFAULT_TRANSACTION_DATE).dateFormat(DATE_FORMAT) + .locale(DEFAULT_LOCALE); + } + + public static PostLoansLoanIdTransactionsRequest defaultUndoChargeOffRequest() { + return new PostLoansLoanIdTransactionsRequest(); + } + + public static PostLoansLoanIdTransactionsRequest defaultReAgingRequest() { + return new PostLoansLoanIdTransactionsRequest()// + .dateFormat(DATE_FORMAT)// + .locale(DEFAULT_LOCALE)// + .frequencyNumber(DEFAULT_REAGING_FREQUENCY_NUMBER)// + .frequencyType(DEFAULT_REAGING_FREQUENCY_TYPE)// + .startDate(DEFAULT_TRANSACTION_DATE)// + .numberOfInstallments(DEFAULT_NUMBER_OF_INSTALLMENTS);// + } + + public static PostLoansLoanIdTransactionsRequest defaultLoanReAmortizationRequest() { + return new PostLoansLoanIdTransactionsRequest().dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } + + public static PostUpdateRescheduleLoansRequest defaultLoanRescheduleUpdateRequest() { + return new PostUpdateRescheduleLoansRequest()// + .locale(DEFAULT_LOCALE)// + .dateFormat(DATE_FORMAT); + } + + public static PostCreateRescheduleLoansRequest defaultLoanRescheduleCreateRequest(Long loanId, String fromDate, String toDate) { + return new PostCreateRescheduleLoansRequest()// + .submittedOnDate(DATE_SUBMIT_STRING)// + .rescheduleFromDate(fromDate)// + .adjustedDueDate(toDate)// + .rescheduleReasonId(1L)// + .loanId(loanId)// + .locale(DEFAULT_LOCALE)// + .dateFormat(DATE_FORMAT); + } + + public static PostLoansLoanIdTransactionsRequest defaultWriteOffRequest() { + return new PostLoansLoanIdTransactionsRequest().transactionDate(DEFAULT_TRANSACTION_DATE).dateFormat(DATE_FORMAT) + .locale(DEFAULT_LOCALE).note("Write Off"); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/PaymentTypesRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/PaymentTypesRequestFactory.java new file mode 100644 index 00000000000..dbde26e99a4 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/PaymentTypesRequestFactory.java @@ -0,0 +1,35 @@ +/** + * 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.test.factory; + +import org.apache.fineract.client.models.PostPaymentTypesRequest; + +public final class PaymentTypesRequestFactory { + + private PaymentTypesRequestFactory() {} + + public static PostPaymentTypesRequest defaultPaymentTypeRequest(String name, String description, Boolean isCashPayment, + Integer position) { + PostPaymentTypesRequest request = new PostPaymentTypesRequest(); + + request.name(name).description(description).isCashPayment(isCashPayment).position(position); + + return request; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/BusinessDateHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/BusinessDateHelper.java new file mode 100644 index 00000000000..5553b9a11ad --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/BusinessDateHelper.java @@ -0,0 +1,63 @@ +/** + * 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.test.helper; + +import java.io.IOException; +import java.time.Clock; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.BusinessDateRequest; +import org.apache.fineract.client.models.BusinessDateResponse; +import org.apache.fineract.client.services.BusinessDateManagementApi; +import org.apache.fineract.test.support.TestContext; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@RequiredArgsConstructor +@Component +public class BusinessDateHelper { + + public static final String DATE_FORMAT = "dd MMMM yyyy"; + public static final String DEFAULT_LOCALE = "en"; + public static final String BUSINESS_DATE = "BUSINESS_DATE"; + public static final String BUSINESS_DATE_REQUEST_TYPE = "BUSINESS_DATE"; + + private final BusinessDateManagementApi businessDateManagementApi; + + public void setBusinessDate(String businessDate) throws IOException { + BusinessDateRequest businessDateRequest = defaultBusinessDateRequest().date(businessDate); + + Response businessDateRequestResponse = businessDateManagementApi.updateBusinessDate(businessDateRequest) + .execute(); + ErrorHelper.checkSuccessfulApiCall(businessDateRequestResponse); + TestContext.INSTANCE.set(TestContextKey.BUSINESS_DATE_RESPONSE, businessDateRequestResponse); + } + + public void setBusinessDateToday() throws IOException { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); + String today = formatter.format(LocalDate.now(Clock.systemUTC())); + setBusinessDate(today); + } + + public BusinessDateRequest defaultBusinessDateRequest() { + return new BusinessDateRequest().type(BUSINESS_DATE_REQUEST_TYPE).dateFormat(DATE_FORMAT).locale(DEFAULT_LOCALE); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java index 5949023627a..ea27ebb005a 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorHelper.java @@ -21,6 +21,8 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.util.List; +import org.apache.fineract.client.models.BatchResponse; import retrofit2.Response; public final class ErrorHelper { @@ -34,4 +36,18 @@ public static void checkSuccessfulApiCall(Response response) throws IOException throw new AssertionError(ErrorMessageHelper.requestFailedWithCode(response)); } } + + public static void checkFailedApiCall(Response response, int requiredCode) throws IOException { + assertThat(!response.isSuccessful()).as(ErrorMessageHelper.requestFailed(response)).isTrue(); + + if (response.code() != requiredCode) { + throw new AssertionError("Request success but should fail with code: " + requiredCode); + } + } + + public static void checkSuccessfulBatchApiCall(Response> batchResponseList) { + batchResponseList.body().forEach(response -> { + assertThat(response.getStatusCode()).as(ErrorMessageHelper.batchRequestFailedWithCode(response)).isEqualTo(200); + }); + } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java index 76cc7f51acd..9b64527ecb2 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java @@ -19,10 +19,22 @@ package org.apache.fineract.test.helper; import java.io.IOException; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.client.models.BatchResponse; +import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse; +import org.apache.fineract.client.models.GetLoanAccountLockResponse; +import org.apache.fineract.client.models.Header; import retrofit2.Response; public final class ErrorMessageHelper { + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd MMMM yyyy"); + private ErrorMessageHelper() {} public static String requestFailed(Response response) throws IOException { @@ -32,4 +44,820 @@ public static String requestFailed(Response response) throws IOException { public static String requestFailedWithCode(Response response) { return String.format("Response has error code: %2d", response.code()); } + + public static String batchRequestFailedWithCode(BatchResponse response) { + return String.format("Response has error code: %2d in request: %2d", response.getStatusCode(), response.getRequestId()); + } + + public static String chargeAppliesToIsInvalid(Enum chargeAppliesTo) { + return String.format("%s is invalid input for charge applies to field", chargeAppliesTo); + } + + public static String dateFailureErrorCodeMsg() { + return "Loan has a wrong http status"; + } + + public static String disburseDateFailure(Integer loanId) { + String loanIdStr = parseLoanIdToString(loanId); + return String.format("The date on which a loan with identifier : %s is disbursed cannot be in the future.", loanIdStr); + } + + public static String disburseMaxAmountFailure() { + return "Loan disbursal amount can't be greater than maximum applied loan amount calculation. Total disbursed amount: [0-9]* Maximum disbursal amount: [0-9]*"; + } + + public static String loanSubmitDateInFutureFailureMsg() { + return "The date on which a loan is submitted cannot be in the future."; + } + + public static String loanApproveDateInFutureFailureMsg() { + return "The date on which a loan is approved cannot be in the future."; + } + + public static String loanApproveMaxAmountFailureMsg() { + return "Loan approved amount can't be greater than maximum applied loan amount calculation."; + } + + public static String loanFraudFlagModificationMsg(String loanId) { + return String.format("Loan Id: %s mark as fraud is not allowed as loan status is not active", loanId); + + } + + public static String transactionDateInFutureFailureMsg() { + return "The transaction date cannot be in the future."; + } + + public static String repaymentUndoFailureDueToChargeOff(Long loanId) { + String loanIdStr = String.valueOf(loanId); + return String.format("Loan transaction: %s adjustment is not allowed before or on the date when the loan got charged-off", + loanIdStr); + } + + public static String secondChargeOffFailure(Long loanId) { + String loanIdStr = String.valueOf(loanId); + return String.format("Loan: %s is already charged-off", loanIdStr); + } + + public static String repaymentUndoFailureDueToChargeOffCodeMsg() { + return "Undo not possible if the loan was charged-off"; + } + + public static String chargeOffUndoFailureCodeMsg() { + return "Charge-Off Undo is not possible before the last transaction date"; + } + + public static String chargeOffUndoFailure(Long loanId) { + String loanIdStr = String.valueOf(loanId); + return String.format("Loan: %s charge-off cannot be executed. User transaction was found after the charge-off transaction date!", + loanIdStr); + } + + public static String notChargedOffFailure(Long loanId) { + String loanIdStr = String.valueOf(loanId); + return String.format("Loan: %s is not charged-off", loanIdStr); + } + + public static String addChargeForChargeOffLoanCodeMsg() { + return "Adding charge to a Charged-Off loan is not allowed."; + } + + public static String addChargeForChargeOffLoanFailure(Long loanId) { + String loanIdStr = String.valueOf(loanId); + return String.format("Adding charge to Loan: %s is not allowed. Loan Account is Charged-off", loanIdStr); + } + + public static String wrongAmountInRepaymentSchedule(int line, BigDecimal actual, BigDecimal expected) { + String lineToStr = String.valueOf(line); + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule. Actual amount for line %s is: %s - But expected amount is: %s", lineToStr, + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentSchedulePrincipal(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Principal. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleInterest(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Interest. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleFees(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Fees. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInRepaymentSchedulePenalties(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Penalties. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleDue(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Due. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInRepaymentSchedulePaid(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Paid. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleInAdvance(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / In advance. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleLate(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Late. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleOutstanding(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Outstanding. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongAmountInRepaymentScheduleWaived(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Repayment schedule / Waived. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongDataInTransactionsTransactionType(String actual, String expected) { + return String.format("Wrong data in Transactions / Transaction type. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInTransactionsTransactionDate(String actual, String expected) { + return String.format("Wrong data in Transactions / Transaction date. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String transactionIsNotReversedError(Boolean actual, Boolean expected) { + return String.format("The transaction should be reversed, but it is not. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongAmountInTransactionsAmount(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Amount. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsPrincipal(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Principal. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsInterest(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Interest. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsFees(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Fees. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsPenalties(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Penalties. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsOverpayment(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Overpayment. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTransactionsBalance(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Transactions / Loan Balance. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongDataInChargesName(String actual, String expected) { + return String.format("Wrong data in Charges / Name. Actual value is: %s - But expected value is: %s", actual, expected); + } + + public static String wrongDataInChargesIsPenalty(String actual, String expected) { + return String.format("Wrong data in Charges / isPenalty. Actual value is: %s - But expected value is: %s", actual, expected); + } + + public static String wrongDataInChargesDueDate(String actual, String expected) { + return String.format("Wrong data in Charges / Due Date. Actual value is: %s - But expected value is: %s", actual, expected); + } + + public static String wrongDataInChargesAmountDue(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Charges / Due amount. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongDataInChargesAmountPaid(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Charges / Paid amount. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongDataInChargesAmountWaived(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Charges / Waived amount. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongDataInChargesAmountOutstanding(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Charges / Outstanding amount. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTotalOutstanding(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Loan total outstanding. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongAmountInTotalOverdue(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong amount in Loan total overdue. Actual amount is: %s - But expected amount is: %s", actualToStr, + expectedToStr); + } + + public static String wrongLastPaymentAmount(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong last payment amount. Actual last payment amount is: %s - But expected last payment amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongDataInDelinquentLastRepaymentAmount(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong amount in Loan details delinquent.lastRepaymentAmount. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongDataInDelinquentLastRepaymentDate(String actual, String expected) { + return String.format("Wrong amount in Loan details delinquent.lastRepaymentDate. Actual date is: %s - But expected date is: %s", + actual, expected); + } + + public static String wrongLoanStatus(Integer actual, Integer expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong Loan status ID. Actual ID is: %s - But expected ID is: %s", actualToStr, expectedToStr); + } + + public static String wrongFraudFlag(Boolean actualFraudStatus, Boolean expectedFraudStatus) { + return String.format("Wrong Loan fraud flag. Actual Fraud status is: %s - Expected Fraud status is: %s", actualFraudStatus, + expectedFraudStatus); + } + + public static String delinquencyRangeError(String actual, String expected) { + return String.format("Wrong Delinquency range. Actual range is: %s - Expected range is: %s", actual, expected); + } + + private static String parseLoanIdToString(Integer loanId) { + return StringUtils.repeat("0", 9 - loanId.toString().length()) + loanId.toString(); + } + + public static String loanRepaymentOnClosedLoanFailureMsg() { + return "Loan Repayment (or its types) or Waiver is not allowed. Loan Account is not active."; + } + + public static String noTransactionMetCriteria(String transactionType, String date) { + return String.format( + "There are no transaction in Transactions met the following criteria: Transaction type = %s, Transaction date = %s", + transactionType, date); + } + + public static String missingMatchInJournalEntries(Map entryPairs, + List entryDataList) { + String entryPairsStr = entryPairs.toString(); + String entryDataListStr = entryDataList.toString(); + return String.format("One or more entry pairs missing from Journal entries. Expected entry pairs: %s. Actual Journal entries: %s", + entryPairsStr, entryDataListStr); + } + + public static String wrongErrorCodeInFailedChargeAdjustment(Integer actual, Integer expected) { + return String.format("Not the expected error code in error body: Actual error message is: %s. Expected error code is: %s", + actual.toString(), expected.toString()); + } + + public static String wrongStatusCode(Integer actual, Integer expected) { + return String.format("Not the expected http status code: Actual code is: %s. Expected code is: %s", actual.toString(), + expected.toString()); + } + + public static String wrongErrorMessageInFailedChargeAdjustment(String actual, String expected) { + return String.format("Not the expected error message in error body: Actual error code is: %s. Expected error message is: %s", + actual, expected); + } + + public static String wrongErrorMessage(String actual, String expected) { + return String.format("Not the expected error message in error body: Actual error message is: %s. Expected error message is: %s", + actual, expected); + } + + public static String wrongValueInResponseHeader(String headerKey, String actual, String expected) { + return String.format("Not the expected value in header '%s': Actual value is: %s. Expected value is: %s", headerKey, actual, + expected); + } + + public static String wrongNrOfTransactions(String transactionType, int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format( + "Not the expected number of '%s' transactions in Transactions tab: Actual number of transactions: %s. Expected number of transactions: %s", + transactionType, actualStr, expectedStr); + } + + public static String wrongAmountInTransactionsResponse(Double actual, Double expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format("Wrong amount in Transactions response. Actual value is: %s - But expected value is: %s", actualStr, + expectedStr); + } + + public static String wrongClientIdInTransactionResponse(Long actual, Long expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format("Wrong Client ID in Transactions response. Actual value is: %s - But expected value is: %s", actualStr, + expectedStr); + } + + public static String wrongLoanIdInTransactionResponse(Long actual, Long expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format("Wrong Loan ID in Transactions response. Actual value is: %s - But expected value is: %s", actualStr, + expectedStr); + } + + public static String noHeaderKeyFound(List
headersList, String headerKey) { + return String.format("Header key: %s was not found in headers list: %s", headerKey, headersList.toString()); + } + + public static String idempotencyKeyNoMatch(String actual, String expected) { + return String.format("Idempotency key is not matching: Actual value is: %s - But expected value is: %s", actual, expected); + } + + public static String wrongNumberOfLinesInRepaymentSchedule(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format("Number of lines in Repayment schedule is not correct. Actual value is: %s - Expected value is: %s", actualStr, + expectedStr); + } + + public static String wrongValueInLineInRepaymentSchedule(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Repayment schedule tab line %s. %nActual values in line (with the same due date) are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String wrongValueInLineInTransactionsTab(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Transactions tab line %s. %nActual values in line (with the same date) are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String nrOfLinesWrongInTransactionsTab(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + + return String.format( + "%nNumber of lines does not match in Transactions tab and expected datatable. %nNumber of transaction tab lines: %s %nNumber of expected datatable lines: %s%n", + actualStr, expectedStr); + } + + public static String wrongValueInLineInChargesTab(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Charges tab line %s. %nActual values in line (with the same date) are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String wrongValueInLineInJournalEntries(int line, List>> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List> innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Journal entries line %s. %nActual values for the possible transactions in line (with the same date) are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String wrongDataInJournalEntriesGlAccountType(int line, String actual, String expected) { + return String.format("Wrong data in Journal entries, line %s / GL account type. Actual value is: %s - But expected value is: %s", + line, actual, expected); + } + + public static String wrongDataInJournalEntriesGlAccountCode(int line, String actual, String expected) { + return String.format("Wrong data in Journal entries, line %s / GL account code. Actual value is: %s - But expected value is: %s", + line, actual, expected); + } + + public static String wrongDataInJournalEntriesGlAccountName(int line, String actual, String expected) { + return String.format("Wrong data in Journal entries, line %s / GL account name. Actual value is: %s - But expected value is: %s", + line, actual, expected); + } + + public static String wrongDataInJournalEntriesDebit(int line, String actual, String expected) { + return String.format("Wrong data in Journal entries, line %s / Debit. Actual value is: %s - But expected value is: %s", line, + actual, expected); + } + + public static String wrongDataInJournalEntriesCredit(int line, String actual, String expected) { + return String.format("Wrong data in Journal entries, line %s / Credit. Actual value is: %s - But expected value is: %s", line, + actual, expected); + } + + public static String wrongDataInActualMaturityDate(String actual, String expected) { + return String.format("Wrong data in Loan details/Timeline/actualMaturityDate. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInExpectedMaturityDate(String actual, String expected) { + return String.format("Wrong data in Loan details/Timeline/expectedMaturityDate. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLastPaymentAmount(String actual, String expected) { + return String.format("Wrong data in Loan details/delinquent/lastPaymentAmount. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLastPaymentDate(String actual, String expected) { + return String.format("Wrong data in Loan details/delinquent/lastPaymentDate. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLastRepaymentAmount(String actual, String expected) { + return String.format("Wrong data in Loan details/delinquent/lastRepaymentAmount. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLastRepaymentDate(String actual, String expected) { + return String.format("Wrong data in Loan details/delinquent/lastRepaymentDate. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLoanDetailsLoanChargePaidByListAmount(String actual, String expected) { + return String.format("Wrong data in Loan details/loanChargePaidByList/amount. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLoanDetailsLoanChargePaidByListName(String actual, String expected) { + return String.format("Wrong data in Loan details/loanChargePaidByList/name. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLoanTransactionMakeRepaymentPostEventLoanChargePaidByListAmount(String actual, String expected) { + return String.format( + "Wrong data in LoanTransactionMakeRepaymentPostEvent/loanChargePaidByList/amount. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInLoanTransactionMakeRepaymentPostEventLoanChargePaidByListName(String actual, String expected) { + return String.format( + "Wrong data in LoanTransactionMakeRepaymentPostEvent/loanChargePaidByList/name. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongDataInDelinquencyHistoryClassification(String actual, String expected) { + return String.format("Wrong data in Delinquency History/classification. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInDelinquencyHistoryAddedOnDate(String actual, String expected) { + return String.format("Wrong data in Delinquency History/addedOnDate. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInDelinquencyHistoryLiftedOnDate(String actual, String expected) { + return String.format("Wrong data in Delinquency History/liftedOnDate. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInAssetExternalizationResponse(String actual, String expected) { + return String.format("Wrong data in Asset Externalization response. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInAssetExternalizationResponse(Long actual, Long expected) { + return String.format("Wrong data in Asset Externalization response. Actual value is: %s - But expected value is: %s", actual, + expected); + } + + public static String wrongDataInAssetExternalizationTransferExternalId(String actual, String expected) { + return String.format("Wrong data in Asset Externalization - transfer_external_id. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongData(String actual, String expected) { + return String.format("Wrong data. Actual value is: %s - But expected value is: %s", actual, expected); + } + + public static String wrongValueInExternalAssetDetails(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in External Asset details line %s. %nActual values in line are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String wrongTotalFilteredRecordsInAssetExternalizationDetails(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + + return String.format( + "%nNumber of totalFilteredRecords does not match in Asset Externalization details. %nActual number of totalFilteredRecords: %s %nExpected number of totalFilteredRecords: %s%n", + actualStr, expectedStr); + } + + public static String wrongValueInLineInAssetExternalizationJournalEntry(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Asset Externalization Journal Entry tab line %s. %nActual values in line are: %n%s %nExpected values in line: %n%s", + lineStr, sb.toString(), expectedStr); + } + + public static String wrongNumberOfLinesInAssetExternalizationJournalEntry(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format( + "Number of lines in Asset Externalization Journal Entry is not correct. Actual value is: %s - Expected value is: %s", + actualStr, expectedStr); + } + + public static String wrongErrorCode(Integer actual, Integer expected) { + return String.format("Not the expected error code in error body: Actual error code is: %s. Expected error code is: %s", + actual.toString(), expected.toString()); + } + + public static String idNull() { + return "The requested ID is null"; + } + + public static String wrongLastCOBProcessedLoanDate(LocalDate actual, LocalDate expected) { + String actualStr = FORMATTER.format(actual); + String expectedStr = FORMATTER.format(expected); + return String.format( + "Processed date of last loan processed by COB is wrong. Actual value is %s, but it should be earlier than %s. ", actualStr, + expectedStr); + } + + public static String listOfLockedLoansNotEmpty(Response response) { + String bodyStr = response.body().toString(); + return String.format("List of locked loan accounts is not empty. Actual response is: %n%s", bodyStr); + } + + public static String listOfLockedLoansContainsLoan(Long loanId, Response response) { + String bodyStr = response.body().toString(); + return String.format("List of locked loan accounts contains the loan with loanId %s. List of locked loans: %n%s", loanId, bodyStr); + } + + public static String wrongValueInLineDelinquencyActions(int line, List actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + String actualStr = actual.toString(); + + return String.format( + "%nWrong value in Delinquency actions response line %s. %nActual values in line are: %s %nExpected values in line: \s\s%s", + lineStr, actualStr, expectedStr); + } + + public static String wrongNumberOfLinesInDelinquencyActions(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + return String.format( + "Number of items (lines) in DelinquencyActions response is not correct. Actual value is: %s - Expected value is: %s", + actualStr, expectedStr); + } + + public static String wrongValueInPauseDelinquencyEventActive(int itemNr, Boolean actual, Boolean expected) { + return String.format( + "Wrong value in LoanAccountDelinquencyPauseChangedBusinessEvent/delinquent/delinquencyPausePeriods/active item Nr: %s . %nActual value is: %s - Expected value is: %s", + itemNr, actual, expected); + } + + public static String wrongValueInPauseDelinquencyEventStartDate(int itemNr, String actual, String expected) { + return String.format( + "Wrong value in LoanAccountDelinquencyPauseChangedBusinessEvent/delinquent/delinquencyPausePeriods/pausePeriodStart item Nr: %s . %nActual value is: %s - Expected value is: %s", + itemNr, actual, expected); + } + + public static String wrongValueInPauseDelinquencyEventEndDate(int itemNr, String actual, String expected) { + return String.format( + "Wrong value in LoanAccountDelinquencyPauseChangedBusinessEvent/delinquent/delinquencyPausePeriods/pausePeriodEnd item Nr: %s . %nActual value is: %s - Expected value is: %s", + itemNr, actual, expected); + } + + public static String wrongValueInLineInInstallmentLevelDelinquencyData(int line, List actual, List expected) { + String lineStr = String.valueOf(line); + String actualStr = actual.toString(); + String expectedStr = expected.toString(); + + return String.format( + "%nWrong value in Installment level delinquency data, line %s. %nActual values in line: \s\s%s %nExpected values in line: %s", + lineStr, actualStr, expectedStr); + } + + public static String wrongValueInLoanLevelDelinquencyData(List actual, List expected) { + String actualStr = actual.toString(); + String expectedStr = expected.toString(); + + return String.format("%nWrong value in LOAN level delinquency data. %nActual values are:\s\s %s %nExpected values are: %s", + actualStr, expectedStr); + } + + public static String nrOfLinesWrongInInstallmentLevelDelinquencyData(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + + return String.format( + "%nNumber of lines does not match in Installment level delinquency data and expected datatable. %nNumber of transaction tab lines: %s %nNumber of expected datatable lines: %s%n", + actualStr, expectedStr); + } + + public static String wrongAmountInLoanDelinquencyRangeChangedEventTotalAmount(BigDecimal actual, BigDecimal expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "%nWrong amount in LoanDelinquencyRangeChangeBusinessEvent - totalAmount. %ninstallmentDelinquencyBuckets/amount/totalAmount: %s %nSum of installmentDelinquencyBuckets/amount/{principalAmount, interestAmount, feeAmount, penaltyAmount}: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLineInDelinquencyPausePeriodData(int line, List> actual, List expected) { + String lineStr = String.valueOf(line); + String expectedStr = expected.toString(); + StringBuilder sb = new StringBuilder(); + for (List innerList : actual) { + sb.append(innerList.toString()); + sb.append(System.lineSeparator()); + } + + return String.format( + "%nWrong value in Delinquency pause periods line %s. %nActual values in line: %s %nExpected values in line: %s", lineStr, + sb.toString(), expectedStr); + } + + public static String nrOfLinesWrongInLoanDelinquencyPauseData(int actual, int expected) { + String actualStr = String.valueOf(actual); + String expectedStr = String.valueOf(expected); + + return String.format( + "%nNumber of lines does not match in Loan delinquency pause data and expected datatable. %nNumber of items in loanDetails/delinquent/delinquencyPausePeriods: %s %nNumber of expected datatable lines: %s%n", + actualStr, expectedStr); + } + + public static String wrongDataInNextPaymentDueDate(String actual, String expected) { + return String.format("Wrong data in Loan details / delinquent.nextPaymentDueDate. Actual value is: %s - But expected value is: %s", + actual, expected); + } + + public static String wrongAmountInTotalRepaymentTransaction(Double actual, Double expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong amount in Loan details / summary/totalRepaymentTransaction. Actual amount is: %s - But expected amount is: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent1(Long actual, Long expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Installment level delinquency -> delinquencyRange/id. %nActual value is: %s %nExpected value is: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent2(String actual, String expected) { + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Installment level delinquency -> delinquencyRange/classification. %nActual value is: %s %nExpected value is: %s", + actual, expected); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent3(BigDecimal actual, BigDecimal expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Installment level delinquency -> amount/totalAmount. %nActual value is: %s %nExpected value is: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent4(Long actual, Long expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Loan level delinquency -> delinquencyRange/id. %nActual value is: %s %nExpected value is: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent5(String actual, String expected) { + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Loan level delinquency -> delinquencyRange/classification. %nActual value is: %s %nExpected value is: %s", + actual, expected); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent6(BigDecimal actual, BigDecimal expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Loan level delinquency -> amount/totalAmount. %nActual value is: %s %nExpected value is: %s", + actualToStr, expectedToStr); + } + + public static String wrongValueInLoanDelinquencyRangeChangeBusinessEvent7(String actual, String expected) { + return String.format( + "Wrong value in LoanDelinquencyRangeChangeBusinessEvent -> Loan level delinquency -> delinquentDate. %nActual value is: %s %nExpected value is: %s", + actual, expected); + } + + public static String wrongfixedLength(Integer actual, Integer expected) { + String actualToStr = actual.toString(); + String expectedToStr = expected.toString(); + return String.format("Wrong value in LoanDeteils/fixedLength. %nActual value is: %s %nExpected Value is: %s", actualToStr, + expectedToStr); + } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorResponse.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorResponse.java new file mode 100644 index 00000000000..db4e7c3765a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorResponse.java @@ -0,0 +1,65 @@ +/** + * 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.test.helper; + +import com.google.gson.Gson; +import java.io.IOException; +import java.util.List; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.fineract.client.util.JSON; +import retrofit2.Response; + +@NoArgsConstructor +@Getter +@Setter +public class ErrorResponse { + + private static final Gson GSON = new JSON().getGson(); + + private String developerMessage; + private Integer httpStatusCode; + private List errors; + + public Error getSingleError() { + if (errors.size() != 1) { + throw new IllegalStateException("Multiple errors found"); + } else { + return errors.iterator().next(); + } + } + + public static ErrorResponse from(Response retrofitResponse) { + try { + String errorBody = retrofitResponse.errorBody().string(); + return GSON.fromJson(errorBody, ErrorResponse.class); + } catch (IOException e) { + throw new RuntimeException("Error while parsing the error body", e); + } + } + + @NoArgsConstructor + @Getter + @Setter + public static class Error { + + private String developerMessage; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/GlobalConfigurationHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/GlobalConfigurationHelper.java new file mode 100644 index 00000000000..6914dc73e55 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/GlobalConfigurationHelper.java @@ -0,0 +1,77 @@ +/** + * 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.test.helper; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.fineract.client.models.GlobalConfigurationPropertyData; +import org.apache.fineract.client.models.PutGlobalConfigurationsRequest; +import org.apache.fineract.client.models.PutGlobalConfigurationsResponse; +import org.apache.fineract.client.services.GlobalConfigurationApi; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Component +@RequiredArgsConstructor +public class GlobalConfigurationHelper { + + private final GlobalConfigurationApi globalConfigurationApi; + + public void disableGlobalConfiguration(String configKey, Long value) throws IOException { + switchAndSetGlobalConfiguration(configKey, false, value); + } + + public void enableGlobalConfiguration(String configKey, Long value) throws IOException { + switchAndSetGlobalConfiguration(configKey, true, value); + } + + private void switchAndSetGlobalConfiguration(String configKey, boolean enabled, Long value) throws IOException { + Response configuration = globalConfigurationApi.retrieveOneByName(configKey).execute(); + ErrorHelper.checkSuccessfulApiCall(configuration); + Long configId = configuration.body().getId(); + + PutGlobalConfigurationsRequest updateRequest = new PutGlobalConfigurationsRequest().enabled(enabled).value(value); + + Response updateResponse = globalConfigurationApi.updateConfiguration1(configId, updateRequest) + .execute(); + assertThat(updateResponse.code()).isEqualTo(HttpStatus.SC_OK); + Response updatedConfiguration = globalConfigurationApi.retrieveOneByName(configKey).execute(); + boolean isEnabled = BooleanUtils.toBoolean(updatedConfiguration.body().getEnabled()); + assertThat(isEnabled).isEqualTo(enabled); + } + + public void setGlobalConfigValueString(String configKey, String value) throws IOException { + Response configuration = globalConfigurationApi.retrieveOneByName(configKey).execute(); + ErrorHelper.checkSuccessfulApiCall(configuration); + Long configId = configuration.body().getId(); + + PutGlobalConfigurationsRequest updateRequest = new PutGlobalConfigurationsRequest().enabled(true).stringValue(value); + + Response updateResponse = globalConfigurationApi.updateConfiguration1(configId, updateRequest) + .execute(); + assertThat(updateResponse.code()).isEqualTo(HttpStatus.SC_OK); + Response updatedConfiguration = globalConfigurationApi.retrieveOneByName(configKey).execute(); + boolean isEnabled = BooleanUtils.toBoolean(updatedConfiguration.body().getEnabled()); + assertThat(isEnabled).isEqualTo(true); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerConfiguration.java new file mode 100644 index 00000000000..71e3d247d73 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerConfiguration.java @@ -0,0 +1,29 @@ +/** + * 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.test.initializer; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan({ "org.apache.fineract.test.initializer.global", "org.apache.fineract.test.initializer.scenario", + "org.apache.fineract.test.initializer.suite", "org.apache.fineract.test.factory", "org.apache.fineract.test.data" }) +public class FineractInitializerConfiguration { + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerFactory.java new file mode 100644 index 00000000000..d07cb8cce49 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/FineractInitializerFactory.java @@ -0,0 +1,47 @@ +/** + * 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.test.initializer; + +import java.util.Set; +import org.apache.fineract.test.initializer.base.FineractInitializer; +import org.apache.fineract.test.support.loader.FineractConfigLoader; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public final class FineractInitializerFactory { + + private FineractInitializerFactory() {} + + private static final class Holder { + + private Holder() {} + + static final FineractInitializer INSTANCE; + + static { + Set> initializerConfigurationClasses = FineractConfigLoader.getInitializerConfigurationClasses(); + ApplicationContext context = new AnnotationConfigApplicationContext(initializerConfigurationClasses.toArray(new Class[0])); + INSTANCE = context.getBean(FineractInitializer.class); + } + } + + public static FineractInitializer get() { + return Holder.INSTANCE; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/InitializerProperties.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/InitializerProperties.java new file mode 100644 index 00000000000..1eca9a1b2d8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/InitializerProperties.java @@ -0,0 +1,29 @@ +/** + * 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.test.initializer; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; + +@Getter +public class InitializerProperties { + + @Value("${fineract-test.initialization.enabled}") + private boolean enabled; +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/BaseFineractInitializerConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/BaseFineractInitializerConfiguration.java new file mode 100644 index 00000000000..f1a624e9705 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/BaseFineractInitializerConfiguration.java @@ -0,0 +1,45 @@ +/** + * 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.test.initializer.base; + +import java.util.List; +import org.apache.fineract.test.config.CacheConfiguration; +import org.apache.fineract.test.helper.BusinessDateHelper; +import org.apache.fineract.test.initializer.global.FineractGlobalInitializerStep; +import org.apache.fineract.test.initializer.scenario.FineractScenarioInitializerStep; +import org.apache.fineract.test.initializer.suite.FineractSuiteInitializerStep; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@ComponentScan({ "org.apache.fineract.test.api", "org.apache.fineract.test.helper" }) +@PropertySource("classpath:fineract-test-application.properties") +@Import({ CacheConfiguration.class }) +public class BaseFineractInitializerConfiguration { + + @Bean + public FineractInitializer fineractInitializer(List globalInitializerSteps, + List suiteInitializerSteps, List scenarioInitializerSteps, + BusinessDateHelper businessDateHelper) { + return new FineractInitializer(globalInitializerSteps, suiteInitializerSteps, scenarioInitializerSteps, businessDateHelper); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java new file mode 100644 index 00000000000..4e5d680d000 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java @@ -0,0 +1,91 @@ +/** + * 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.test.initializer.base; + +import java.util.List; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.test.helper.BusinessDateHelper; +import org.apache.fineract.test.initializer.global.FineractGlobalInitializerStep; +import org.apache.fineract.test.initializer.scenario.FineractScenarioInitializerStep; +import org.apache.fineract.test.initializer.suite.FineractSuiteInitializerStep; +import org.springframework.beans.factory.InitializingBean; + +@Slf4j +@RequiredArgsConstructor +public class FineractInitializer implements InitializingBean { + + public static final String DATE_FORMAT = "dd MMMM yyyy"; + + private final List globalInitializerSteps; + private final List suiteInitializerSteps; + private final List scenarioInitializerSteps; + private final BusinessDateHelper businessDateHelper; + + @Override + public void afterPropertiesSet() throws Exception { + if (log.isDebugEnabled()) { + String globalInitializers = globalInitializerSteps.stream().map(Object::getClass).map(Class::getName) + .collect(Collectors.joining(", ")); + String suiteInitializers = suiteInitializerSteps.stream().map(Object::getClass).map(Class::getName) + .collect(Collectors.joining(", ")); + String scenarioInitializers = scenarioInitializerSteps.stream().map(Object::getClass).map(Class::getName) + .collect(Collectors.joining(", ")); + log.debug(""" + The following initializers have been configured: + Global initializers: [{}] + Suite initializers: [{}] + Scenario initializers: [{}] + """, globalInitializers, suiteInitializers, scenarioInitializers); + } + } + + public void setupGlobalDefaults() throws Exception { + for (FineractGlobalInitializerStep initializerStep : globalInitializerSteps) { + initializerStep.initialize(); + } + + businessDateHelper.setBusinessDateToday(); + } + + public void setupDefaultsForSuite() throws Exception { + for (FineractSuiteInitializerStep initializerStep : suiteInitializerSteps) { + initializerStep.initializeForSuite(); + } + + businessDateHelper.setBusinessDateToday(); + } + + public void setupDefaultsForScenario() throws Exception { + for (FineractScenarioInitializerStep scenarioInitializerStep : scenarioInitializerSteps) { + scenarioInitializerStep.initializeForScenario(); + } + + businessDateHelper.setBusinessDateToday(); + } + + public void resetDefaultsAfterSuite() throws Exception { + for (FineractSuiteInitializerStep initializerStep : suiteInitializerSteps) { + initializerStep.resetAfterSuite(); + } + + businessDateHelper.setBusinessDateToday(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/ChargeGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/ChargeGlobalInitializerStep.java new file mode 100644 index 00000000000..0e5d4d9bef6 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/ChargeGlobalInitializerStep.java @@ -0,0 +1,180 @@ +/** + * 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.test.initializer.global; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostChargesRequest; +import org.apache.fineract.client.models.PostChargesResponse; +import org.apache.fineract.client.services.ChargesApi; +import org.apache.fineract.test.data.ChargeCalculationType; +import org.apache.fineract.test.data.ChargePaymentMode; +import org.apache.fineract.test.data.ChargeProductAppliesTo; +import org.apache.fineract.test.data.ChargeTimeType; +import org.apache.fineract.test.data.CurrencyOptions; +import org.apache.fineract.test.helper.ErrorMessageHelper; +import org.apache.fineract.test.support.TestContext; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@RequiredArgsConstructor +@Component +public class ChargeGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String CURRENCY_CODE = CurrencyOptions.EUR.value; + public static final String MONTH_DAY_FORMAT = "dd MMM"; + public static final String LOCALE_EN = "en"; + public static final Integer CHARGE_PAYMENT_MODE = ChargePaymentMode.REGULAR.value; + public static final Enum CHARGE_APPLIES_TO_LOAN = ChargeProductAppliesTo.LOAN; + public static final Enum CHARGE_APPLIES_TO_CLIENT = ChargeProductAppliesTo.CLIENT; + public static final String CHARGE_LOAN_PERCENTAGE_LATE_FEE = "% Late fee"; + public static final String CHARGE_LOAN_PERCENTAGE_LATE_FEE_AMOUNT_PLUS_INTEREST = "% Late fee amount+interest"; + public static final String CHARGE_LOAN_PERCENTAGE_PROCESSING_FEE = "% Processing fee"; + public static final String CHARGE_LOAN_FIXED_LATE_FEE = "Fixed Late fee"; + public static final String CHARGE_LOAN_FIXED_RETURNED_PAYMENT_FEE = "Fixed Returned payment fee"; + public static final String CHARGE_LOAN_SNOOZE_FEE = "Snooze fee"; + public static final String CHARGE_LOAN_NSF_FEE = "NSF fee"; + public static final String CHARGE_LOAN_DISBURSEMENT_PERCENT_FEE = "Disbursement percentage fee"; + public static final String CHARGE_LOAN_TRANCHE_DISBURSEMENT_PERCENT_FEE = "Tranche Disbursement percentage fee"; + public static final String CHARGE_LOAN_INSTALLMENT_PERCENT_FEE = "Installment percentage fee"; + public static final String CHARGE_CLIENT_FIXED_FEE = "Fixed fee for Client"; + public static final Double CHARGE_AMOUNT_FLAT = 25D; + public static final Double CHARGE_AMOUNT_PERCENTAGE = 5D; + public static final Double CHARGE_AMOUNT_DISBURSEMENT_PERCENTAGE = 1.5D; + public static final Double CHARGE_AMOUNT_INSTALLMENT_PERCENTAGE = 1.5D; + public static final Double CHARGE_AMOUNT_OVERDUE_PERCENTAGE = 1.5D; + public static final Integer CHARGE_TIME_TYPE_OVERDUE_FEES = ChargeTimeType.OVERDUE_FEES.value; + public static final Integer CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE = ChargeTimeType.SPECIFIED_DUE_DATE.value; + public static final Integer CHARGE_TIME_TYPE_DISBURSEMENT = ChargeTimeType.DISBURSEMENT.value; + public static final Integer CHARGE_TIME_TYPE_TRANCHE_DISBURSEMENT = ChargeTimeType.TRANCHE_DISBURSEMENT.value; + public static final Integer CHARGE_TIME_TYPE_INSTALLMENT = ChargeTimeType.INSTALLMENT_FEE.value; + public static final Integer CHARGE_CALCULATION_TYPE_FLAT = ChargeCalculationType.FLAT.value; + public static final Integer CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT = ChargeCalculationType.PERCENTAGE_AMOUNT.value; + public static final Integer CHARGE_CALCULATION_TYPE_PERCENTAGE_DISBURSEMENT_AMOUNT = ChargeCalculationType.PERCENTAGE_DISBURSEMENT_AMOUNT.value; + public static final Integer CHARGE_CALCULATION_TYPE_PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST = ChargeCalculationType.PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST.value; + + private final ChargesApi chargesApi; + + @Override + public void initialize() throws Exception { + // Loan - % late (overdue) fee + PostChargesRequest requestLoanPercentLate = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, CHARGE_LOAN_PERCENTAGE_LATE_FEE, + CHARGE_TIME_TYPE_OVERDUE_FEES, CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, CHARGE_AMOUNT_OVERDUE_PERCENTAGE, true, true); + Response responseLoanPercentLate = chargesApi.createCharge(requestLoanPercentLate).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE, responseLoanPercentLate); + + // Loan - % processing fee + PostChargesRequest requestLoanPercentProcessing = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, + CHARGE_LOAN_PERCENTAGE_PROCESSING_FEE, CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE, + CHARGE_CALCULATION_TYPE_PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST, CHARGE_AMOUNT_PERCENTAGE, true, false); + Response responseLoanPercentProcessing = chargesApi.createCharge(requestLoanPercentProcessing).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE, responseLoanPercentProcessing); + + // Loan - fixed late (overdue) fee + PostChargesRequest requestLoanFixedLate = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, CHARGE_LOAN_FIXED_LATE_FEE, + CHARGE_TIME_TYPE_OVERDUE_FEES, CHARGE_CALCULATION_TYPE_FLAT, CHARGE_AMOUNT_FLAT, true, true); + Response responseLoanFixedLate = chargesApi.createCharge(requestLoanFixedLate).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_FIXED_LATE_CREATE_RESPONSE, responseLoanFixedLate); + + // Loan - fixed returned payment fee + PostChargesRequest requestLoanFixedReturnedPayment = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, + CHARGE_LOAN_FIXED_RETURNED_PAYMENT_FEE, CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE, CHARGE_CALCULATION_TYPE_FLAT, + CHARGE_AMOUNT_FLAT, true, false); + Response responseLoanFixedReturnedPayment = chargesApi.createCharge(requestLoanFixedReturnedPayment).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_FIXED_RETURNED_PAYMENT_CREATE_RESPONSE, responseLoanFixedReturnedPayment); + + // Loan - snooze fee + PostChargesRequest requestLoanSnooze = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, CHARGE_LOAN_SNOOZE_FEE, + CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE, CHARGE_CALCULATION_TYPE_FLAT, CHARGE_AMOUNT_FLAT, true, false); + Response responseLoanSnooze = chargesApi.createCharge(requestLoanSnooze).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_SNOOZE_FEE_CREATE_RESPONSE, responseLoanSnooze); + + // Loan - NSF fee + PostChargesRequest requestLoanNsf = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, CHARGE_LOAN_NSF_FEE, + CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE, CHARGE_CALCULATION_TYPE_FLAT, CHARGE_AMOUNT_FLAT, true, true); + Response responseLoanNsf = chargesApi.createCharge(requestLoanNsf).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_NSF_FEE_CREATE_RESPONSE, responseLoanNsf); + + // Loan - Disbursement % fee + PostChargesRequest requestLoanDisbursePercent = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, CHARGE_LOAN_DISBURSEMENT_PERCENT_FEE, + CHARGE_TIME_TYPE_DISBURSEMENT, CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, CHARGE_AMOUNT_DISBURSEMENT_PERCENTAGE, true, + false); + Response responseLoanDisbursePercent = chargesApi.createCharge(requestLoanDisbursePercent).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_DISBURSEMENET_FEE_CREATE_RESPONSE, responseLoanDisbursePercent); + + // Loan - Tranche Disbursement % fee + PostChargesRequest requestLoanTrancheDisbursePercent = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, + CHARGE_LOAN_TRANCHE_DISBURSEMENT_PERCENT_FEE, CHARGE_TIME_TYPE_TRANCHE_DISBURSEMENT, + CHARGE_CALCULATION_TYPE_PERCENTAGE_DISBURSEMENT_AMOUNT, CHARGE_AMOUNT_DISBURSEMENT_PERCENTAGE, true, false); + Response responseLoanTrancheDisbursePercent = chargesApi.createCharge(requestLoanTrancheDisbursePercent) + .execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_DISBURSEMENET_FEE_CREATE_RESPONSE, responseLoanTrancheDisbursePercent); + + // Loan - Installment % fee + PostChargesRequest requestLoanInstallmentPercent = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, + CHARGE_LOAN_INSTALLMENT_PERCENT_FEE, CHARGE_TIME_TYPE_INSTALLMENT, + CHARGE_CALCULATION_TYPE_PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST, CHARGE_AMOUNT_INSTALLMENT_PERCENTAGE, true, false); + Response responseLoanInstallmentPercent = chargesApi.createCharge(requestLoanInstallmentPercent).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_INSTALLMENT_FEE_CREATE_RESPONSE, responseLoanInstallmentPercent); + + // Loan - % late (overdue) fee amount+interest + PostChargesRequest requestLoanPercentAmountPlusInterestLate = defaultChargesRequest(CHARGE_APPLIES_TO_LOAN, + CHARGE_LOAN_PERCENTAGE_LATE_FEE_AMOUNT_PLUS_INTEREST, CHARGE_TIME_TYPE_OVERDUE_FEES, + CHARGE_CALCULATION_TYPE_PERCENTAGE_LOAN_AMOUNT_PLUS_INTEREST, CHARGE_AMOUNT_OVERDUE_PERCENTAGE, true, true); + Response responseLoanPercentAmountPlusInterestLate = chargesApi + .createCharge(requestLoanPercentAmountPlusInterestLate).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE, + responseLoanPercentAmountPlusInterestLate); + + // Client - fixed fee + PostChargesRequest requestClientFixed = defaultChargesRequest(CHARGE_APPLIES_TO_CLIENT, CHARGE_CLIENT_FIXED_FEE, + CHARGE_TIME_TYPE_SPECIFIED_DUE_DATE, CHARGE_CALCULATION_TYPE_FLAT, CHARGE_AMOUNT_FLAT, true, false); + Response responseClientFixed = chargesApi.createCharge(requestClientFixed).execute(); + TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_CLIENT_FIXED_FEE_CREATE_RESPONSE, responseClientFixed); + } + + public static PostChargesRequest defaultChargesRequest(Enum appliesTo, String name, Integer chargeTimeType, + Integer chargeCalculationType, Double amount, Boolean isActive, Boolean isPenalty) throws Exception { + PostChargesRequest request = new PostChargesRequest(); + Integer chargeAppliesTo; + + if (appliesTo.equals(ChargeProductAppliesTo.CLIENT)) { + chargeAppliesTo = ChargeProductAppliesTo.CLIENT.value; + } else if (appliesTo.equals(ChargeProductAppliesTo.LOAN)) { + chargeAppliesTo = ChargeProductAppliesTo.LOAN.value; + request.chargePaymentMode(CHARGE_PAYMENT_MODE); + } else { + throw new Exception(ErrorMessageHelper.chargeAppliesToIsInvalid(appliesTo)); + } + + request// + .chargeAppliesTo(chargeAppliesTo)// + .name(name)// + .currencyCode(CURRENCY_CODE)// + .chargeTimeType(chargeTimeType)// + .chargeCalculationType(chargeCalculationType)// + .amount(amount)// + .active(isActive)// + .penalty(isPenalty)// + .monthDayFormat(MONTH_DAY_FORMAT)// + .locale(LOCALE_EN);// + + return request; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java new file mode 100644 index 00000000000..4cfe0907a95 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java @@ -0,0 +1,296 @@ +/** + * 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.test.initializer.global; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostCodeValuesDataRequest; +import org.apache.fineract.client.models.PostCodesRequest; +import org.apache.fineract.client.models.PutCodeValuesDataRequest; +import org.apache.fineract.client.services.CodeValuesApi; +import org.apache.fineract.client.services.CodesApi; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String CODE_NAME_FINANCIAL_INSTRUMENT = "financial_instrument"; + public static final String CODE_NAME_TRANSACTION_TYPE = "transaction_type"; + public static final String CODE_NAME_BANKRUPTCY_TAG = "bankruptcy_tag"; + public static final String CODE_NAME_PENDING_FRAUD_TAG = "pending_fraud_tag"; + public static final String CODE_NAME_PENDING_DECEASED_TAG = "pending_deceased_tag"; + public static final String CODE_NAME_HARDSHIP_TAG = "hardship_tag"; + public static final String CODE_NAME_ACTIVE_DUTY_TAG = "active_duty_tag"; + public static final Long CODE_VALUE_ADDRESS_TYPE_ID = 29L; + public static final String CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL = "Residential address"; + public static final String CODE_VALUE_ADDRESS_TYPE_OFFICE = "Office address"; + public static final Long CODE_VALUE_COUNTRY_ID = 28L; + public static final String CODE_VALUE_COUNTRY_GERMANY = "Germany"; + public static final Long CODE_VALUE_STATE_ID = 27L; + public static final String CODE_VALUE_STATE_BERLIN = "Berlin"; + public static final Long CODE_VALUE_FINANCIAL_INSTRUMENT_ID = 39L; + public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT = "debit_card"; + public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT = "credit_card"; + public static final Long CODE_VALUE_TRANSACTION_TYPE_ID = 40L; + public static final String CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT = "scheduled_payment"; + public static final Long CODE_VALUE_BANKRUPTCY_TAG_ID = 41L; + public static final String CODE_VALUE_BANKRUPTCY_TAG_PENDING = "pending_bankruptcy"; + public static final String CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY = "bankruptcy"; + public static final Long CODE_VALUE_PENDING_FRAUD_TAG_ID = 42L; + public static final String CODE_VALUE_PENDING_FRAUD_TAG_PENDING = "pending_fraud"; + public static final String CODE_VALUE_PENDING_FRAUD_TAG_FRAUD = "fraud"; + public static final Long CODE_VALUE_PENDING_DECEASED_TAG_ID = 43L; + public static final String CODE_VALUE_PENDING_DECEASED_TAG_PENDING = "pending_deceased"; + public static final String CODE_VALUE_PENDING_DECEASED_TAG_DECEASED = "deceased"; + public static final Long CODE_VALUE_HARDSHIP_TAG_ID = 44L; + public static final String CODE_VALUE_HARDSHIP_TAG_ACTIVE = "active"; + public static final String CODE_VALUE_HARDSHIP_TAG_INACTIVE = "inactive"; + public static final Long CODE_VALUE_ACTIVE_DUTY_TAG_ID = 45L; + public static final String CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE = "active"; + public static final String CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE = "inactive"; + public static final Long CODE_VALUE_CUSTOMER_IDENTIFIERS_ID = 1L; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_1 = "Passport"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_2 = "Id"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_3 = "Drivers License"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_4 = "Any Other Id Type"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_5 = "SSN"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_6 = "TIN"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_7 = "ITIN"; + public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_8 = "EIN"; + public static final Long CODE_VALUE_GENDER_ID = 4L; + public static final String CODE_VALUE_GENDER_FEMALE = "Female"; + public static final String CODE_VALUE_GENDER_MALE = "Male"; + public static final Long CODE_VALUE_CLIENT_TYPE_ID = 16L; + public static final String CODE_VALUE_CLIENT_TYPE_CORPORATE = "Corporate"; + public static final String CODE_VALUE_CLIENT_TYPE_LEGAL = "Legal"; + public static final String CODE_VALUE_CLIENT_TYPE_NON_LEGAL = "Non-legal"; + public static final Long CODE_VALUE_CLIENT_CLASSIFICATION_ID = 17L; + public static final String CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER = "Lawyer"; + public static final String CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR = "Director"; + public static final String CODE_VALUE_CLIENT_CLASSIFICATION_NONE = "None"; + public static final Long CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID = 31L; + public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_SPOUSE = "Spouse"; + public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER = "Father"; + public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER = "Mother"; + public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD = "Child"; + public static final Long CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID = 32L; + public static final String CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE = "Employee"; + public static final String CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED = "Self-Employed"; + public static final Long CODE_VALUE_FAMILY_MARITAL_STATUS_ID = 30L; + public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED = "Married"; + public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE = "Single"; + public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED = "Widowed"; + public static final Long CODE_VALUE_CONSTITUTION_ID = 24L; + public static final String CODE_VALUE_CONSTITUTION_TEST = "Test"; + + public static final Long CODE_VALUE_RESCHEDULE_REASON_ID = 23L; + public static final String CODE_VALUE_RESCHEDULE_REASON_TEST = "Test"; + + private final CodesApi codesApi; + private final CodeValuesApi codeValuesApi; + + @Override + public void initialize() throws Exception { + createCodeNames(); + createCodeValues(); + } + + private void createCodeValues() { + // address type + List addressNames = new ArrayList<>(); + addressNames.add(CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL); + addressNames.add(CODE_VALUE_ADDRESS_TYPE_OFFICE); + createCodeValues(CODE_VALUE_ADDRESS_TYPE_ID, addressNames); + + // Country + List countryNames = new ArrayList<>(); + countryNames.add(CODE_VALUE_COUNTRY_GERMANY); + createCodeValues(CODE_VALUE_COUNTRY_ID, countryNames); + + // State + List stateNames = new ArrayList<>(); + stateNames.add(CODE_VALUE_STATE_BERLIN); + createCodeValues(CODE_VALUE_STATE_ID, stateNames); + + // financial instrument + List financialInstrumentNames = new ArrayList<>(); + financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT); + financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT); + createCodeValues(CODE_VALUE_FINANCIAL_INSTRUMENT_ID, financialInstrumentNames); + + // transaction type + List transactionTypeNames = new ArrayList<>(); + transactionTypeNames.add(CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT); + createCodeValues(CODE_VALUE_TRANSACTION_TYPE_ID, transactionTypeNames); + + // bankruptcy tag + List bankruptcyTagNames = new ArrayList<>(); + bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_PENDING); + bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY); + createCodeValues(CODE_VALUE_BANKRUPTCY_TAG_ID, bankruptcyTagNames); + + // pending fraud tag + List pendingFraudTagNames = new ArrayList<>(); + pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_PENDING); + pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_FRAUD); + createCodeValues(CODE_VALUE_PENDING_FRAUD_TAG_ID, pendingFraudTagNames); + + // pending deceased tag + List pendingDeceasedTagNames = new ArrayList<>(); + pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_PENDING); + pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_DECEASED); + createCodeValues(CODE_VALUE_PENDING_DECEASED_TAG_ID, pendingDeceasedTagNames); + + // hardship tag + List hardshipTagNames = new ArrayList<>(); + hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_ACTIVE); + hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_INACTIVE); + createCodeValues(CODE_VALUE_HARDSHIP_TAG_ID, hardshipTagNames); + + // active duty tag + List activeDutyTagNames = new ArrayList<>(); + activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE); + activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE); + createCodeValues(CODE_VALUE_ACTIVE_DUTY_TAG_ID, activeDutyTagNames); + + // customer identifiers put/post + List customerIdentifierNamesPut = new ArrayList<>(); + customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_1); + customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_2); + customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_3); + customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_4); + updateCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, customerIdentifierNamesPut); + + List customerIdentifierNamesPost = new ArrayList<>(); + customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_5); + customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_6); + customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_7); + customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_8); + createCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, customerIdentifierNamesPost); + + // gender + List genderNames = new ArrayList<>(); + genderNames.add(CODE_VALUE_GENDER_FEMALE); + genderNames.add(CODE_VALUE_GENDER_MALE); + createCodeValues(CODE_VALUE_GENDER_ID, genderNames); + + // client type + List clientTypeNames = new ArrayList<>(); + clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_CORPORATE); + clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_LEGAL); + clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_NON_LEGAL); + createCodeValues(CODE_VALUE_CLIENT_TYPE_ID, clientTypeNames); + + // client classification + List clientClassificationNames = new ArrayList<>(); + clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER); + clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR); + clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_NONE); + createCodeValues(CODE_VALUE_CLIENT_CLASSIFICATION_ID, clientClassificationNames); + + // add family member - relationship + List familyMemberRelationshipNames = new ArrayList<>(); + familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_SPOUSE); + familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER); + familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER); + familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD); + createCodeValues(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID, familyMemberRelationshipNames); + + // add family member - profession + List familyMemberProfessionNames = new ArrayList<>(); + familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE); + familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED); + createCodeValues(CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID, familyMemberProfessionNames); + + // add family member - marital status + List familyMemberMaritalStatusNames = new ArrayList<>(); + familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED); + familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE); + familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED); + createCodeValues(CODE_VALUE_FAMILY_MARITAL_STATUS_ID, familyMemberMaritalStatusNames); + + // add constitution (for client creation as Entity) + List constitutionNames = new ArrayList<>(); + constitutionNames.add(CODE_VALUE_CONSTITUTION_TEST); + createCodeValues(CODE_VALUE_CONSTITUTION_ID, constitutionNames); + + // add LoanRescheduleReason + List rescheduleReasonNames = new ArrayList<>(); + rescheduleReasonNames.add(CODE_VALUE_RESCHEDULE_REASON_TEST); + createCodeValues(CODE_VALUE_RESCHEDULE_REASON_ID, rescheduleReasonNames); + } + + public void createCodeValues(Long codeId, List codeValueNames) { + codeValueNames.forEach(name -> { + Integer position = codeValueNames.indexOf(name); + PostCodeValuesDataRequest postCodeValuesDataRequest = new PostCodeValuesDataRequest(); + postCodeValuesDataRequest.isActive(true); + postCodeValuesDataRequest.name(name); + postCodeValuesDataRequest.position(position); + + try { + codeValuesApi.createCodeValue(codeId, postCodeValuesDataRequest).execute(); + } catch (IOException e) { + throw new RuntimeException("Error while creating code value", e); + } + }); + } + + public void updateCodeValues(Long codeId, List codeValueNames) { + codeValueNames.forEach(name -> { + int position = codeValueNames.indexOf(name) + 1; + PutCodeValuesDataRequest putCodeValuesDataRequest = new PutCodeValuesDataRequest(); + putCodeValuesDataRequest.isActive(false); + putCodeValuesDataRequest.name(name); + putCodeValuesDataRequest.position(position); + + try { + codeValuesApi.updateCodeValue(codeId, (long) position, putCodeValuesDataRequest).execute(); + } catch (IOException e) { + throw new RuntimeException("Error while updating code value", e); + } + }); + } + + private void createCodeNames() { + List codesNameList = new ArrayList<>(); + codesNameList.add(CODE_NAME_FINANCIAL_INSTRUMENT); + codesNameList.add(CODE_NAME_TRANSACTION_TYPE); + codesNameList.add(CODE_NAME_BANKRUPTCY_TAG); + codesNameList.add(CODE_NAME_PENDING_FRAUD_TAG); + codesNameList.add(CODE_NAME_PENDING_DECEASED_TAG); + codesNameList.add(CODE_NAME_HARDSHIP_TAG); + codesNameList.add(CODE_NAME_ACTIVE_DUTY_TAG); + + codesNameList.forEach(codeName -> { + PostCodesRequest postCodesRequest = new PostCodesRequest(); + try { + codesApi.createCode(postCodesRequest.name(codeName)).execute(); + } catch (IOException e) { + throw new RuntimeException("Error while creating code", e); + } + }); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CurrencyGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CurrencyGlobalInitializerStep.java new file mode 100644 index 00000000000..e98093e7d12 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CurrencyGlobalInitializerStep.java @@ -0,0 +1,50 @@ +/** + * 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.test.initializer.global; + +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PutCurrenciesRequest; +import org.apache.fineract.client.models.PutCurrenciesResponse; +import org.apache.fineract.client.services.CurrencyApi; +import org.apache.fineract.test.support.TestContext; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class CurrencyGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final List CURRENCIES = Arrays.asList("EUR", "USD"); + + private final CurrencyApi currencyApi; + + @Override + public void initialize() throws Exception { + PutCurrenciesRequest putCurrenciesRequest = new PutCurrenciesRequest(); + Response putCurrenciesResponse = currencyApi.updateCurrencies(putCurrenciesRequest.currencies(CURRENCIES)) + .execute(); + TestContext.INSTANCE.set(TestContextKey.PUT_CURRENCIES_RESPONSE, putCurrenciesResponse); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DatatablesGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DatatablesGlobalInitializerStep.java new file mode 100644 index 00000000000..a7237213da2 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DatatablesGlobalInitializerStep.java @@ -0,0 +1,186 @@ +/** + * 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.test.initializer.global; + +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostColumnHeaderData; +import org.apache.fineract.client.models.PostDataTablesRequest; +import org.apache.fineract.client.services.DataTablesApi; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class DatatablesGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String DATA_TABLE_1_NAME = "dt_autopay_details"; + public static final String DATA_TABLE_1_APP_NAME = "m_loan"; + public static final String DATA_TABLE_1_COLUMN_1_NAME = "financial_instruments"; + public static final String DATA_TABLE_1_COLUMN_1_TYPE = "Dropdown"; + public static final String DATA_TABLE_1_COLUMN_1_CODE = "financial_instrument"; + public static final String DATA_TABLE_1_COLUMN_2_NAME = "date_of_payment"; + public static final String DATA_TABLE_1_COLUMN_2_TYPE = "Date"; + public static final String DATA_TABLE_2_NAME = "dt_schedule_payments"; + public static final String DATA_TABLE_2_APP_NAME = "m_loan"; + public static final String DATA_TABLE_2_COLUMN_1_NAME = "external_reference_id"; + public static final String DATA_TABLE_2_COLUMN_1_TYPE = "String"; + public static final Long DATA_TABLE_2_COLUMN_1_LENGTH = 50L; + public static final String DATA_TABLE_2_COLUMN_2_NAME = "scheduled_date"; + public static final String DATA_TABLE_2_COLUMN_2_TYPE = "Date"; + public static final String DATA_TABLE_2_COLUMN_3_NAME = "amount"; + public static final String DATA_TABLE_2_COLUMN_3_TYPE = "Decimal"; + public static final String DATA_TABLE_2_COLUMN_4_NAME = "transaction_type"; + public static final String DATA_TABLE_2_COLUMN_4_TYPE = "Dropdown"; + public static final String DATA_TABLE_2_COLUMN_4_CODE = "transaction_type"; + public static final String DATA_TABLE_3_NAME = "dt_user_tags"; + public static final String DATA_TABLE_3_APP_NAME = "m_client"; + public static final String DATA_TABLE_3_ENTITY_SUBTYPE = "PERSON"; + public static final String DATA_TABLE_3_COLUMN_1_NAME = "bankruptcy_tag"; + public static final String DATA_TABLE_3_COLUMN_1_TYPE = "Dropdown"; + public static final String DATA_TABLE_3_COLUMN_1_CODE = "bankruptcy_tag"; + public static final String DATA_TABLE_3_COLUMN_2_NAME = "pending_fraud_tag"; + public static final String DATA_TABLE_3_COLUMN_2_TYPE = "Dropdown"; + public static final String DATA_TABLE_3_COLUMN_2_CODE = "pending_fraud_tag"; + public static final String DATA_TABLE_3_COLUMN_3_NAME = "pending_deceased_tag"; + public static final String DATA_TABLE_3_COLUMN_3_TYPE = "Dropdown"; + public static final String DATA_TABLE_3_COLUMN_3_CODE = "pending_deceased_tag"; + public static final String DATA_TABLE_3_COLUMN_4_NAME = "hardship_tag"; + public static final String DATA_TABLE_3_COLUMN_4_TYPE = "Dropdown"; + public static final String DATA_TABLE_3_COLUMN_4_CODE = "hardship_tag"; + public static final String DATA_TABLE_3_COLUMN_5_NAME = "active_duty_tag"; + public static final String DATA_TABLE_3_COLUMN_5_TYPE = "Dropdown"; + public static final String DATA_TABLE_3_COLUMN_5_CODE = "active_duty_tag"; + + private final DataTablesApi dataTablesApi; + + @Override + public void initialize() throws Exception { + // autopay + PostColumnHeaderData column1 = new PostColumnHeaderData(); + column1.name(DATA_TABLE_1_COLUMN_1_NAME); + column1.type(DATA_TABLE_1_COLUMN_1_TYPE); + column1.code(DATA_TABLE_1_COLUMN_1_CODE); + column1.mandatory(false); + + PostColumnHeaderData column2 = new PostColumnHeaderData(); + column2.name(DATA_TABLE_1_COLUMN_2_NAME); + column2.type(DATA_TABLE_1_COLUMN_2_TYPE); + column2.mandatory(false); + + List columns = new ArrayList<>(); + columns.add(column1); + columns.add(column2); + + PostDataTablesRequest postDataTablesRequest = new PostDataTablesRequest(); + postDataTablesRequest.datatableName(DATA_TABLE_1_NAME); + postDataTablesRequest.apptableName(DATA_TABLE_1_APP_NAME); + postDataTablesRequest.multiRow(true); + postDataTablesRequest.columns(columns); + + dataTablesApi.createDatatable(postDataTablesRequest).execute(); + + // scheduled payments + PostColumnHeaderData columnScheduled1 = new PostColumnHeaderData(); + columnScheduled1.name(DATA_TABLE_2_COLUMN_1_NAME); + columnScheduled1.type(DATA_TABLE_2_COLUMN_1_TYPE); + columnScheduled1.length(DATA_TABLE_2_COLUMN_1_LENGTH); + columnScheduled1.mandatory(false); + + PostColumnHeaderData columnScheduled2 = new PostColumnHeaderData(); + columnScheduled2.name(DATA_TABLE_2_COLUMN_2_NAME); + columnScheduled2.type(DATA_TABLE_2_COLUMN_2_TYPE); + columnScheduled2.mandatory(false); + + PostColumnHeaderData columnScheduled3 = new PostColumnHeaderData(); + columnScheduled3.name(DATA_TABLE_2_COLUMN_3_NAME); + columnScheduled3.type(DATA_TABLE_2_COLUMN_3_TYPE); + columnScheduled3.mandatory(false); + + PostColumnHeaderData columnScheduled4 = new PostColumnHeaderData(); + columnScheduled4.name(DATA_TABLE_2_COLUMN_4_NAME); + columnScheduled4.type(DATA_TABLE_2_COLUMN_4_TYPE); + columnScheduled4.code(DATA_TABLE_2_COLUMN_4_CODE); + columnScheduled4.mandatory(false); + + List columnsScheduled = new ArrayList<>(); + columnsScheduled.add(columnScheduled1); + columnsScheduled.add(columnScheduled2); + columnsScheduled.add(columnScheduled3); + columnsScheduled.add(columnScheduled4); + + PostDataTablesRequest postDataTablesRequestScheduled = new PostDataTablesRequest(); + postDataTablesRequestScheduled.datatableName(DATA_TABLE_2_NAME); + postDataTablesRequestScheduled.apptableName(DATA_TABLE_2_APP_NAME); + postDataTablesRequestScheduled.multiRow(true); + postDataTablesRequestScheduled.columns(columnsScheduled); + + dataTablesApi.createDatatable(postDataTablesRequestScheduled).execute(); + + // 3 tags + PostColumnHeaderData column3Tags1 = new PostColumnHeaderData(); + column3Tags1.name(DATA_TABLE_3_COLUMN_1_NAME); + column3Tags1.type(DATA_TABLE_3_COLUMN_1_TYPE); + column3Tags1.code(DATA_TABLE_3_COLUMN_1_CODE); + column3Tags1.mandatory(false); + + PostColumnHeaderData column3Tags2 = new PostColumnHeaderData(); + column3Tags2.name(DATA_TABLE_3_COLUMN_2_NAME); + column3Tags2.type(DATA_TABLE_3_COLUMN_2_TYPE); + column3Tags2.code(DATA_TABLE_3_COLUMN_2_CODE); + column3Tags2.mandatory(false); + + PostColumnHeaderData column3Tags3 = new PostColumnHeaderData(); + column3Tags3.name(DATA_TABLE_3_COLUMN_3_NAME); + column3Tags3.type(DATA_TABLE_3_COLUMN_3_TYPE); + column3Tags3.code(DATA_TABLE_3_COLUMN_3_CODE); + column3Tags3.mandatory(false); + + PostColumnHeaderData column3Tags4 = new PostColumnHeaderData(); + column3Tags4.name(DATA_TABLE_3_COLUMN_4_NAME); + column3Tags4.type(DATA_TABLE_3_COLUMN_4_TYPE); + column3Tags4.code(DATA_TABLE_3_COLUMN_4_CODE); + column3Tags4.mandatory(false); + + PostColumnHeaderData column3Tags5 = new PostColumnHeaderData(); + column3Tags5.name(DATA_TABLE_3_COLUMN_5_NAME); + column3Tags5.type(DATA_TABLE_3_COLUMN_5_TYPE); + column3Tags5.code(DATA_TABLE_3_COLUMN_5_CODE); + column3Tags5.mandatory(false); + + List columns3Tags = new ArrayList<>(); + columns3Tags.add(column3Tags1); + columns3Tags.add(column3Tags2); + columns3Tags.add(column3Tags3); + columns3Tags.add(column3Tags4); + columns3Tags.add(column3Tags5); + + PostDataTablesRequest postDataTablesRequest3Tags = new PostDataTablesRequest(); + postDataTablesRequest3Tags.datatableName(DATA_TABLE_3_NAME); + postDataTablesRequest3Tags.apptableName(DATA_TABLE_3_APP_NAME); + postDataTablesRequest3Tags.entitySubType(DATA_TABLE_3_ENTITY_SUBTYPE); + postDataTablesRequest3Tags.multiRow(false); + postDataTablesRequest3Tags.columns(columns3Tags); + + dataTablesApi.createDatatable(postDataTablesRequest3Tags).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java new file mode 100644 index 00000000000..82cf60d6b08 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java @@ -0,0 +1,89 @@ +/** + * 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.test.initializer.global; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostDelinquencyBucketRequest; +import org.apache.fineract.client.models.PostDelinquencyRangeRequest; +import org.apache.fineract.client.services.DelinquencyRangeAndBucketsManagementApi; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class DelinquencyGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String DEFAULT_LOCALE = "en"; + public static final List DEFAULT_DELINQUENCY_RANGES = Arrays.asList(1, 3, 30, 60, 90, 120, 150, 180, 240); + public static final String DEFAULT_DELINQUENCY_BUCKET_NAME = "Default delinquency bucket"; + + private final DelinquencyRangeAndBucketsManagementApi delinquencyApi; + + @Override + public void initialize() throws Exception { + setDefaultDelinquencyRanges(); + setDefaultDelinquencyBucket(); + } + + public void setDefaultDelinquencyRanges() throws IOException { + for (int i = 0; i < DEFAULT_DELINQUENCY_RANGES.size() - 1; i++) { + PostDelinquencyRangeRequest postDelinquencyRangeRequest = new PostDelinquencyRangeRequest(); + postDelinquencyRangeRequest.classification("Delinquency range " + DEFAULT_DELINQUENCY_RANGES.get(i).toString()); + postDelinquencyRangeRequest.locale(DEFAULT_LOCALE); + if (DEFAULT_DELINQUENCY_RANGES.get(i) == 1) { + postDelinquencyRangeRequest.minimumAgeDays(1); + postDelinquencyRangeRequest.maximumAgeDays(3); + } else { + postDelinquencyRangeRequest.minimumAgeDays(DEFAULT_DELINQUENCY_RANGES.get(i) + 1); + postDelinquencyRangeRequest.maximumAgeDays(DEFAULT_DELINQUENCY_RANGES.get(i + 1)); + } + + delinquencyApi.createDelinquencyRange(postDelinquencyRangeRequest).execute(); + } + + PostDelinquencyRangeRequest lastRange = new PostDelinquencyRangeRequest(); + lastRange.classification("Delinquency range " + DEFAULT_DELINQUENCY_RANGES.get(DEFAULT_DELINQUENCY_RANGES.size() - 1).toString()); + lastRange.locale(DEFAULT_LOCALE); + lastRange.minimumAgeDays(DEFAULT_DELINQUENCY_RANGES.get(DEFAULT_DELINQUENCY_RANGES.size() - 1) + 1); + lastRange.maximumAgeDays(null); + + delinquencyApi.createDelinquencyRange(lastRange).execute(); + } + + public void setDefaultDelinquencyBucket() throws IOException { + List rangesNr = new ArrayList<>(); + + for (int i = 1; i < DEFAULT_DELINQUENCY_RANGES.size() + 1; i++) { + rangesNr.add((long) DEFAULT_DELINQUENCY_RANGES.indexOf(DEFAULT_DELINQUENCY_RANGES.get(i - 1))); + } + rangesNr.add((long) DEFAULT_DELINQUENCY_RANGES.size()); + + PostDelinquencyBucketRequest postDelinquencyBucketRequest = new PostDelinquencyBucketRequest(); + postDelinquencyBucketRequest.name(DEFAULT_DELINQUENCY_BUCKET_NAME); + postDelinquencyBucketRequest.ranges(rangesNr); + + delinquencyApi.createDelinquencyBucket(postDelinquencyBucketRequest).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java new file mode 100644 index 00000000000..66885e39de2 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java @@ -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.test.initializer.global; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostFinancialActivityAccountsRequest; +import org.apache.fineract.client.services.MappingFinancialActivitiesToAccountsApi; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +public class FinancialActivityMappingGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final Long FINANCIAL_ACTIVITY_ID_ASSET_TRANSFER = 100L; + public static final Long GL_ACCOUNT_ID_ASSET_TRANSFER = 21L; + + private final MappingFinancialActivitiesToAccountsApi mappingFinancialActivitiesToAccountsApi; + + @Override + public void initialize() throws Exception { + + PostFinancialActivityAccountsRequest request = new PostFinancialActivityAccountsRequest() + .financialActivityId(FINANCIAL_ACTIVITY_ID_ASSET_TRANSFER).glAccountId(GL_ACCOUNT_ID_ASSET_TRANSFER); + mappingFinancialActivitiesToAccountsApi.createGLAccount(request).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FineractGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FineractGlobalInitializerStep.java new file mode 100644 index 00000000000..ef3d26d4d67 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FineractGlobalInitializerStep.java @@ -0,0 +1,24 @@ +/** + * 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.test.initializer.global; + +public interface FineractGlobalInitializerStep { + + void initialize() throws Exception; +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FundGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FundGlobalInitializerStep.java new file mode 100644 index 00000000000..b46821e642f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FundGlobalInitializerStep.java @@ -0,0 +1,57 @@ +/** + * 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.test.initializer.global; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostFundsRequest; +import org.apache.fineract.client.services.FundsApi; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Order(Ordered.HIGHEST_PRECEDENCE) +public class FundGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String FUNDS_LENDER_A = "Lender A"; + public static final String FUNDS_LENDER_B = "Lender B"; + + private final FundsApi fundsApi; + + @Override + public void initialize() throws Exception { + List fundNames = new ArrayList<>(); + fundNames.add(FUNDS_LENDER_A); + fundNames.add(FUNDS_LENDER_B); + fundNames.forEach(name -> { + PostFundsRequest postFundsRequest = new PostFundsRequest(); + postFundsRequest.name(name); + try { + fundsApi.createFund(postFundsRequest).execute(); + } catch (IOException e) { + throw new RuntimeException("Error while creating fund", e); + } + }); + + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GLGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GLGlobalInitializerStep.java new file mode 100644 index 00000000000..8ed010793c2 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GLGlobalInitializerStep.java @@ -0,0 +1,153 @@ +/** + * 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.test.initializer.global; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostGLAccountsRequest; +import org.apache.fineract.client.services.GeneralLedgerAccountApi; +import org.apache.fineract.test.data.GLAType; +import org.apache.fineract.test.data.GLAUsage; +import org.apache.fineract.test.factory.GLAccountRequestFactory; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class GLGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final Integer GLA_USAGE_DETAIL = GLAUsage.DETAIL.value; + public static final Integer GLA_TYPE_ASSET = GLAType.ASSET.value; + public static final Integer GLA_TYPE_LIABILITY = GLAType.LIABILITY.value; + public static final Integer GLA_TYPE_INCOME = GLAType.INCOME.value; + public static final Integer GLA_TYPE_EXPENSE = GLAType.EXPENSE.value; + public static final String GLA_NAME_1 = "Loans Receivable"; + public static final String GLA_NAME_2 = "Interest/Fee Receivable"; + public static final String GLA_NAME_3 = "Other Receivables"; + public static final String GLA_NAME_4 = "UNC Receivable"; + public static final String GLA_NAME_5 = "AA Suspense Balance"; + public static final String GLA_NAME_6 = "Suspense/Clearing account"; + public static final String GLA_NAME_7 = "Deferred Interest Revenue"; + public static final String GLA_NAME_8 = "Retained Earnings Prior Year"; + public static final String GLA_NAME_9 = "Interest Income"; + public static final String GLA_NAME_10 = "Fee Income"; + public static final String GLA_NAME_11 = "Fee Charge Off"; + public static final String GLA_NAME_12 = "Credit Loss/Bad Debt"; + public static final String GLA_NAME_13 = "Credit Loss/Bad Debt-Fraud"; + public static final String GLA_NAME_14 = "Transfer in suspense account"; + public static final String GLA_NAME_15 = "Recoveries"; + public static final String GLA_NAME_16 = "Written off"; + public static final String GLA_NAME_17 = "Overpayment account"; + public static final String GLA_NAME_18 = "Fund Receivables"; + public static final String GLA_NAME_19 = "Goodwill Expense Account"; + public static final String GLA_NAME_20 = "Interest Income Charge Off"; + public static final String GLA_NAME_21 = "Asset transfer"; + public static final String GLA_GL_CODE_1 = "112601"; + public static final String GLA_GL_CODE_2 = "112603"; + public static final String GLA_GL_CODE_3 = "145800"; + public static final String GLA_GL_CODE_4 = "245000"; + public static final String GLA_GL_CODE_5 = "999999"; + public static final String GLA_GL_CODE_6 = "145023"; + public static final String GLA_GL_CODE_7 = "240005"; + public static final String GLA_GL_CODE_8 = "320000"; + public static final String GLA_GL_CODE_9 = "404000"; + public static final String GLA_GL_CODE_10 = "404007"; + public static final String GLA_GL_CODE_11 = "404008"; + public static final String GLA_GL_CODE_12 = "744007"; + public static final String GLA_GL_CODE_13 = "744037"; + public static final String GLA_GL_CODE_14 = "A5"; + public static final String GLA_GL_CODE_15 = "744008"; + public static final String GLA_GL_CODE_16 = "e4"; + public static final String GLA_GL_CODE_17 = "l1"; + public static final String GLA_GL_CODE_18 = "987654"; + public static final String GLA_GL_CODE_19 = "744003"; + public static final String GLA_GL_CODE_20 = "404001"; + public static final String GLA_GL_CODE_21 = "146000"; + + private final GeneralLedgerAccountApi glaApi; + + @Override + public void initialize() throws Exception { + + PostGLAccountsRequest postGLAccountsRequest1 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_1, GLA_GL_CODE_1, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest1).execute(); + PostGLAccountsRequest postGLAccountsRequest2 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_2, GLA_GL_CODE_2, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest2).execute(); + PostGLAccountsRequest postGLAccountsRequest3 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_3, GLA_GL_CODE_3, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest3).execute(); + PostGLAccountsRequest postGLAccountsRequest4 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_4, GLA_GL_CODE_4, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest4).execute(); + PostGLAccountsRequest postGLAccountsRequest5 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_5, GLA_GL_CODE_5, + GLA_TYPE_LIABILITY, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest5).execute(); + PostGLAccountsRequest postGLAccountsRequest6 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_6, GLA_GL_CODE_6, + GLA_TYPE_LIABILITY, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest6).execute(); + PostGLAccountsRequest postGLAccountsRequest7 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_7, GLA_GL_CODE_7, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest7).execute(); + PostGLAccountsRequest postGLAccountsRequest8 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_8, GLA_GL_CODE_8, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest8).execute(); + PostGLAccountsRequest postGLAccountsRequest9 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_9, GLA_GL_CODE_9, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest9).execute(); + PostGLAccountsRequest postGLAccountsRequest10 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_10, GLA_GL_CODE_10, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest10).execute(); + PostGLAccountsRequest postGLAccountsRequest11 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_11, GLA_GL_CODE_11, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest11).execute(); + PostGLAccountsRequest postGLAccountsRequest12 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_12, GLA_GL_CODE_12, + GLA_TYPE_EXPENSE, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest12).execute(); + PostGLAccountsRequest postGLAccountsRequest13 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_13, GLA_GL_CODE_13, + GLA_TYPE_EXPENSE, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest13).execute(); + PostGLAccountsRequest postGLAccountsRequest14 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_14, GLA_GL_CODE_14, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest14).execute(); + PostGLAccountsRequest postGLAccountsRequest15 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_15, GLA_GL_CODE_15, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest15).execute(); + PostGLAccountsRequest postGLAccountsRequest16 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_16, GLA_GL_CODE_16, + GLA_TYPE_EXPENSE, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest16).execute(); + PostGLAccountsRequest postGLAccountsRequest17 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_17, GLA_GL_CODE_17, + GLA_TYPE_LIABILITY, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest17).execute(); + PostGLAccountsRequest postGLAccountsRequest18 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_18, GLA_GL_CODE_18, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest18).execute(); + PostGLAccountsRequest postGLAccountsRequest19 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_19, GLA_GL_CODE_19, + GLA_TYPE_EXPENSE, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest19).execute(); + PostGLAccountsRequest postGLAccountsRequest20 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_20, GLA_GL_CODE_20, + GLA_TYPE_INCOME, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest20).execute(); + PostGLAccountsRequest postGLAccountsRequest21 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_21, GLA_GL_CODE_21, + GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true); + glaApi.createGLAccount1(postGLAccountsRequest21).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GlobalConfigurationGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GlobalConfigurationGlobalInitializerStep.java new file mode 100644 index 00000000000..9d3e0cf4718 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/GlobalConfigurationGlobalInitializerStep.java @@ -0,0 +1,52 @@ +/** + * 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.test.initializer.global; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.test.helper.GlobalConfigurationHelper; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class GlobalConfigurationGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String CONFIG_KEY_ENABLE_ADDRESS = "Enable-Address"; + public static final String CONFIG_KEY_ENABLE_INTEREST_CALCULATION = "interest-charged-from-date-same-as-disbursal-date"; + public static final String CONFIG_KEY_ENABLE_BUSINESS_DATE = "enable_business_date"; + public static final String CONFIG_KEY_ENABLE_RECALCULATE_COB_DATE = "enable_automatic_cob_date_adjustment"; + public static final String CONFIG_KEY_DAYS_BEFORE_REPAYMENT_IS_DUE = "days-before-repayment-is-due"; + public static final String CONFIG_KEY_DAYS_AFTER_REPAYMENT_IS_OVERDUE = "days-after-repayment-is-overdue"; + public static final String CONFIG_KEY_ENABLE_AUTO_GENERATED_EXTERNAL_ID = "enable-auto-generated-external-id"; + + private final GlobalConfigurationHelper globalConfigurationHelper; + + @Override + public void initialize() throws Exception { + globalConfigurationHelper.disableGlobalConfiguration(CONFIG_KEY_ENABLE_ADDRESS, 0L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_INTEREST_CALCULATION, 0L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_BUSINESS_DATE, 0L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_RECALCULATE_COB_DATE, 0L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_DAYS_BEFORE_REPAYMENT_IS_DUE, 1L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_DAYS_AFTER_REPAYMENT_IS_OVERDUE, 2L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_AUTO_GENERATED_EXTERNAL_ID, 0L); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java new file mode 100644 index 00000000000..78e94360119 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java @@ -0,0 +1,539 @@ +/** + * 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.test.initializer.global; + +import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.AdvancedPaymentData; +import org.apache.fineract.client.models.ChargeData; +import org.apache.fineract.client.models.CreditAllocationData; +import org.apache.fineract.client.models.CreditAllocationOrder; +import org.apache.fineract.client.models.LoanProductPaymentAllocationRule; +import org.apache.fineract.client.models.PaymentAllocationOrder; +import org.apache.fineract.client.models.PostLoanProductsRequest; +import org.apache.fineract.client.models.PostLoanProductsResponse; +import org.apache.fineract.client.services.LoanProductsApi; +import org.apache.fineract.test.data.AdvancePaymentsAdjustmentType; +import org.apache.fineract.test.data.ChargeProductType; +import org.apache.fineract.test.data.InterestCalculationPeriodTime; +import org.apache.fineract.test.data.RecalculationRestFrequencyType; +import org.apache.fineract.test.data.TransactionProcessingStrategyCode; +import org.apache.fineract.test.data.loanproduct.DefaultLoanProduct; +import org.apache.fineract.test.factory.LoanProductsRequestFactory; +import org.apache.fineract.test.support.TestContext; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@RequiredArgsConstructor +@Component +public class LoanProductGlobalInitializerStep implements FineractGlobalInitializerStep { + + private final LoanProductsApi loanProductsApi; + private final LoanProductsRequestFactory loanProductsRequestFactory; + + @Override + public void initialize() throws Exception { + // PIN30 + String name = DefaultLoanProduct.PIN30.getName(); + PostLoanProductsRequest loanProductsRequest = loanProductsRequestFactory.defaultLoanProductsRequestPin30().name(name); + Response response = loanProductsApi.createLoanProduct(loanProductsRequest).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30, response); + + // PIN30 product with due date and overdue date for repayment in config + // (PIN30_DUE_DATE) + PostLoanProductsRequest loanProductsRequestDueDate = loanProductsRequestFactory.defaultLoanProductsRequestPin30()// + .name(DefaultLoanProduct.PIN30_DUE_DATE.getName())// + .dueDaysForRepaymentEvent(3)// + .overDueDaysForRepaymentEvent(3);// + Response responseDueDate = loanProductsApi.createLoanProduct(loanProductsRequestDueDate).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_DUE_DATE, responseDueDate); + + // PIN30 with 12% FLAT interest + // (PIN30_INTEREST_FLAT) + String name2 = DefaultLoanProduct.PIN30_INTEREST_FLAT.getName(); + PostLoanProductsRequest loanProductsRequestInterestFlat = loanProductsRequestFactory.defaultLoanProductsRequestPin30InterestFlat() + .name(name2); + Response responseInterestFlat = loanProductsApi.createLoanProduct(loanProductsRequestInterestFlat) + .execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT, responseInterestFlat); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Same as payment period + // (PIN30_INTEREST_DECLINING_BALANCE_PERIOD_SAME_AS_PAYMENT) + String name3 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_PERIOD_SAME_AS_PAYMENT.getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningPeriodSameAsPayment = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDeclining().name(name3); + Response responseInterestDecliningPeriodSameAsPayment = loanProductsApi + .createLoanProduct(loanProductsRequestInterestDecliningPeriodSameAsPayment).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_SAME_AS_PAYMENT, + responseInterestDecliningPeriodSameAsPayment); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily + // (PIN30_INTEREST_DECLINING_BALANCE_PERIOD_DAILY) + String name4 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_PERIOD_DAILY.getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningPeriodDaily = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDeclining().name(name4) + .interestCalculationPeriodType(InterestCalculationPeriodTime.DAILY.value).allowPartialPeriodInterestCalcualtion(false); + Response responseInterestDecliningPeriodDaily = loanProductsApi + .createLoanProduct(loanProductsRequestInterestDecliningPeriodDaily).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_DAILY, + responseInterestDecliningPeriodDaily); + + // PIN30-1MONTH with 12% DECLINING BALANCE interest, interest period: Daily, Interest recalculation-Monthly, + // Compounding:Interest + // (PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY) + String name5 = DefaultLoanProduct.PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY.getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingMonthly = loanProductsRequestFactory + .defaultLoanProductsRequestPin301MonthInterestDecliningBalanceDailyRecalculationCompoundingMonthly().name(name5); + Response responseInterestDecliningBalanceDailyRecalculationCompoundingMonthly = loanProductsApi + .createLoanProduct(loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingMonthly).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY, + responseInterestDecliningBalanceDailyRecalculationCompoundingMonthly); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest + // recalculation-Daily, Compounding:none + // (PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE) + String name6 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE.getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNone = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone().name(name6); + Response responseInterestDecliningBalanceDailyRecalculationCompoundingNone = loanProductsApi + .createLoanProduct(loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNone).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE, + responseInterestDecliningBalanceDailyRecalculationCompoundingNone); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest + // recalculation-Daily, Compounding:none, rescheduleStrategyMethod:Reduce number of installments + // (PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INST) + String name7 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INST + .getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone()// + .name(name7)// + .rescheduleStrategyMethod(AdvancePaymentsAdjustmentType.REDUCE_NUMBER_OF_INSTALLMENTS.value);// + Response responseInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments = loanProductsApi + .createLoanProduct( + loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments) + .execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INSTALLMENTS, + responseInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest + // recalculation-Daily, Compounding:none, rescheduleStrategyMethod:Reschedule next repayments + // (PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_RESCH_NEXT_REP) + String name8 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_RESCH_NEXT_REP + .getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleRescheduleNextRepayments = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone()// + .name(name8)// + .rescheduleStrategyMethod(AdvancePaymentsAdjustmentType.RESCHEDULE_NEXT_REPAYMENTS.value);// + Response responseInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleRescheduleNextRepayments = loanProductsApi + .createLoanProduct( + loanProductsRequestInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleRescheduleNextRepayments) + .execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_NEXT_REPAYMENTS, + responseInterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleRescheduleNextRepayments); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest + // recalculation-Daily, Compounding:none, Interest Recalculation Frequency: Same as Repayment Period + // (PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE) + String name9 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE.getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone()// + .name(name9)// + .recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value);// + Response responseInterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone = loanProductsApi + .createLoanProduct(loanProductsRequestInterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE, + responseInterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone); + + // PIN30 with 12% DECLINING BALANCE interest, interest period: Daily, Interest + // recalculation-Daily, Compounding:none, Interest Recalculation Frequency: Same as Repayment Period, + // Multi-disbursement + // (PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTIDISB) + String name10 = DefaultLoanProduct.PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTIDISB + .getName(); + PostLoanProductsRequest loanProductsRequestInterestDecliningBalanceSaRRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestDecliningBalanceDailyRecalculationCompoundingNone()// + .name(name10)// + .interestCalculationPeriodType(InterestCalculationPeriodTime.SAME_AS_REPAYMENT_PERIOD.value)// + .recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value)// + .multiDisburseLoan(true)// + .disallowExpectedDisbursements(true)// + .allowPartialPeriodInterestCalcualtion(true)// + .maxTrancheCount(10)// + .outstandingLoanBalance(10000.0);// + Response responseInterestDecliningBalanceSaRRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement = loanProductsApi + .createLoanProduct( + loanProductsRequestInterestDecliningBalanceSaRRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement) + .execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTI_DISBURSEMENT, + responseInterestDecliningBalanceSaRRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement); + + // PIN30 with new due-penalty-fee-interest-principal-in-advance-principal-penalty-fee-interest-strategy payment + // strategy + // (PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE) + String name11 = DefaultLoanProduct.PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE.getName(); + PostLoanProductsRequest loanProductsRequestDueInAdvance = loanProductsRequestFactory.defaultLoanProductsRequestPin30()// + .name(name11)// + .transactionProcessingStrategyCode( + TransactionProcessingStrategyCode.DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST.value);// + Response responseDueInAdvance = loanProductsApi.createLoanProduct(loanProductsRequestDueInAdvance) + .execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE, + responseDueInAdvance); + + // PIN30 with new due-penalty-fee-interest-principal-in-advance-principal-penalty-fee-interest-strategy payment + // strategy and with 12% FLAT interest + // (PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT) + String name12 = DefaultLoanProduct.PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT.getName(); + PostLoanProductsRequest loanProductsRequestDueInAdvanceInterestFlat = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestFlat()// + .name(name12)// + .transactionProcessingStrategyCode( + TransactionProcessingStrategyCode.DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST.value);// + Response responseDueInAdvanceInterestFlat = loanProductsApi + .createLoanProduct(loanProductsRequestDueInAdvanceInterestFlat).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_INTEREST_FLAT, + responseDueInAdvanceInterestFlat); + + // PIN30 with new due-penalty-interest-principal-fee-in-advance-penalty-interest-principal-fee-strategy payment + // strategy + // (PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE) + PostLoanProductsRequest loanProductsRequestDueInAdvance2 = loanProductsRequestFactory.defaultLoanProductsRequestPin30()// + .name(DefaultLoanProduct.PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE.getName())// + .transactionProcessingStrategyCode( + TransactionProcessingStrategyCode.DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE.value);// + Response responseDueInAdvance2 = loanProductsApi.createLoanProduct(loanProductsRequestDueInAdvance2) + .execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE, + responseDueInAdvance2); + + // PIN30 with new due-penalty-interest-principal-fee-in-advance-penalty-interest-principal-fee-strategy payment + // strategy and with 12% FLAT interest + // (PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT) + PostLoanProductsRequest loanProductsRequestDueInAdvanceInterestFlat2 = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestFlat()// + .name(DefaultLoanProduct.PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT.getName())// + .transactionProcessingStrategyCode( + TransactionProcessingStrategyCode.DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE.value);// + Response responseDueInAdvanceInterestFlat2 = loanProductsApi + .createLoanProduct(loanProductsRequestDueInAdvanceInterestFlat2).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT, + responseDueInAdvanceInterestFlat2); + + // PIN30 with 12% FLAT interest with % overdue fee for amount + // (PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT) + String name13 = DefaultLoanProduct.PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT.getName(); + List charges = new ArrayList<>(); + charges.add(new ChargeData().id(ChargeProductType.LOAN_PERCENTAGE_LATE_FEE.value)); + PostLoanProductsRequest loanProductsRequestInterestFlatOverdueFeeAmount = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestFlat()// + .name(name13)// + .charges(charges);// + Response responseInterestFlatOverdueFeeAmount = loanProductsApi + .createLoanProduct(loanProductsRequestInterestFlatOverdueFeeAmount).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT, + responseInterestFlatOverdueFeeAmount); + + // PIN30 with 12% FLAT interest with % overdue fee for amount+interest + // (PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST) + String name14 = DefaultLoanProduct.PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST.getName(); + List chargesInterest = new ArrayList<>(); + chargesInterest.add(new ChargeData().id(ChargeProductType.LOAN_PERCENTAGE_LATE_FEE_AMOUNT_PLUS_INTEREST.value)); + PostLoanProductsRequest loanProductsRequestInterestFlatOverdueFeeAmountInterest = loanProductsRequestFactory + .defaultLoanProductsRequestPin30InterestFlat()// + .name(name14)// + .charges(chargesInterest);// + Response responseInterestFlatOverdueFeeAmountInterest = loanProductsApi + .createLoanProduct(loanProductsRequestInterestFlatOverdueFeeAmountInterest).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST, + responseInterestFlatOverdueFeeAmountInterest); + + // PIN4 with Down-payment + // (PIN4_DOWNPAYMENT) + String name15 = DefaultLoanProduct.PIN4_DOWNPAYMENT.getName(); + PostLoanProductsRequest loanProductsRequestDownPayment = loanProductsRequestFactory.defaultLoanProductsRequestPin4()// + .name(name15)// + .enableAutoRepaymentForDownPayment(false);// + Response responseDownPayment = loanProductsApi.createLoanProduct(loanProductsRequestDownPayment) + .execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT, responseDownPayment); + + // PIN4 with Down-payment+autopayment + // (PIN4_DOWNPAYMENT_AUTO) + String name16 = DefaultLoanProduct.PIN4_DOWNPAYMENT_AUTO.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAuto = loanProductsRequestFactory.defaultLoanProductsRequestPin4() + .name(name16); + Response responseDownPaymentAuto = loanProductsApi.createLoanProduct(loanProductsRequestDownPaymentAuto) + .execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO, responseDownPaymentAuto); + + // PIN4 with Down-payment+autopayment + advanced payment allocation + // (PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION) + String name17 = DefaultLoanProduct.PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAutoAdvPaymentAllocation = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name17)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAutoAdvPaymentAllocation = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAutoAdvPaymentAllocation).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION, + responseLoanProductsRequestDownPaymentAutoAdvPaymentAllocation); + + // PIN4 with Down-payment + advanced payment allocation - no auto downpayment + // (PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION) + String name24 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPaymentAllocation = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name24)// + .enableAutoRepaymentForDownPayment(false)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPaymentAllocation = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPaymentAllocation).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION, + responseLoanProductsRequestDownPaymentAdvPaymentAllocation); + + // PIN4 with Down-payment and interest + // (PIN4_DOWNPAYMENT_INTEREST) + String name18 = DefaultLoanProduct.PIN4_DOWNPAYMENT_INTEREST.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentInterest = loanProductsRequestFactory + .defaultLoanProductsRequestPin4InterestFlat()// + .name(name18)// + .enableAutoRepaymentForDownPayment(false);// + Response responseDownPaymentInterest = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentInterest).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST, + responseDownPaymentInterest); + + // PIN4 with Down-payment and interest + // (PIN4_DOWNPAYMENT_INTEREST_AUTO) + String name19 = DefaultLoanProduct.PIN4_DOWNPAYMENT_INTEREST_AUTO.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentInterestAuto = loanProductsRequestFactory + .defaultLoanProductsRequestPin4InterestFlat().name(name19); + Response responseDownPaymentInterestAuto = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentInterestAuto).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST_AUTO, + responseDownPaymentInterestAuto); + + // PIN4 with Down-payment + advanced payment allocation + progressive loan schedule + horizontal + // (PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL) + String name20 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanSchedule = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name20)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .loanScheduleProcessingType("HORIZONTAL")// + .enableAutoRepaymentForDownPayment(false)// + .installmentAmountInMultiplesOf(null)// + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanSchedule = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanSchedule).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE, + responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanSchedule); + + // PIN4 with Down-payment + advanced payment allocation + progressive loan schedule + vertical + // (PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL) + String name21 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleVertical = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name21)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .loanScheduleProcessingType("VERTICAL")// + .enableAutoRepaymentForDownPayment(false)// + .installmentAmountInMultiplesOf(null)// + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleVertical = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleVertical).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL, + responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleVertical); + + // PIN4 with Down-payment + advanced payment allocation + progressive loan schedule + horizontal + installment + // level delinquency + // (PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY) + String name22 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY + .getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleInstLvlDelinquency = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name22)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .loanScheduleProcessingType("HORIZONTAL")// + .enableInstallmentLevelDelinquency(true)// + .enableAutoRepaymentForDownPayment(false)// + .installmentAmountInMultiplesOf(null)// + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleInstLvlDelinquency = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleInstLvlDelinquency).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_INSTALLMENT_LEVEL_DELINQUENCY, + responseLoanProductsRequestDownPaymentAdvPaymentAllocationProgressiveLoanScheduleInstLvlDelinquency); + + // PIN4 with Down-payment + advanced payment allocation + progressive loan schedule + horizontal + installment + // level delinquency + creditAllocation + // (PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY) + String name23 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION + .getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPmtAllocProgSchedInstLvlDelinquencyCreditAllocation = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name23)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .loanScheduleProcessingType("HORIZONTAL")// + .enableInstallmentLevelDelinquency(true)// + .enableAutoRepaymentForDownPayment(false)// + .installmentAmountInMultiplesOf(null)// + .creditAllocation(List.of(// + createCreditAllocation("CHARGEBACK", List.of("PENALTY", "FEE", "INTEREST", "PRINCIPAL"))// + ))// + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPmtAllocProgSchedInstLvlDelinquencyCreditAllocation = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPmtAllocProgSchedInstLvlDelinquencyCreditAllocation).execute(); + TestContext.INSTANCE.set( + TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION, + responseLoanProductsRequestDownPaymentAdvPmtAllocProgSchedInstLvlDelinquencyCreditAllocation); + + // PIN4 with Down-payment + advanced payment allocation + progressive loan schedule + horizontal + installment + // level delinquency + creditAllocation + fixed length (90) + // (PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH) + String name25 = DefaultLoanProduct.PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH.getName(); + PostLoanProductsRequest loanProductsRequestDownPaymentAdvPmtAllocFixedLength = loanProductsRequestFactory + .defaultLoanProductsRequestPin4()// + .name(name25)// + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())// + .loanScheduleType("PROGRESSIVE") // + .loanScheduleProcessingType("HORIZONTAL")// + .enableInstallmentLevelDelinquency(true)// + .enableAutoRepaymentForDownPayment(false)// + .installmentAmountInMultiplesOf(null)// + .fixedLength(90).creditAllocation(List.of(// + createCreditAllocation("CHARGEBACK", List.of("PENALTY", "FEE", "INTEREST", "PRINCIPAL"))// + ))// + .paymentAllocation(List.of(// + createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), // + createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), // + createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), // + createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));// + Response responseLoanProductsRequestDownPaymentAdvPmtAllocFixedLength = loanProductsApi + .createLoanProduct(loanProductsRequestDownPaymentAdvPmtAllocFixedLength).execute(); + TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH, + responseLoanProductsRequestDownPaymentAdvPmtAllocFixedLength); + } + + public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule, + LoanProductPaymentAllocationRule.AllocationTypesEnum... rules) { + AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData(); + advancedPaymentData.setTransactionType(transactionType); + advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule); + + List paymentAllocationOrders; + if (rules.length == 0) { + paymentAllocationOrders = getPaymentAllocationOrder(// + LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PENALTY, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_FEE, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_INTEREST, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PENALTY, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_FEE, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_INTEREST, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL, // + LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_INTEREST);// + } else { + paymentAllocationOrders = getPaymentAllocationOrder(rules); + } + + advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders); + + return advancedPaymentData; + } + + private static CreditAllocationData createCreditAllocation(String transactionType, List creditAllocationRules) { + CreditAllocationData creditAllocationData = new CreditAllocationData(); + creditAllocationData.setTransactionType(transactionType); + + List creditAllocationOrders = new ArrayList<>(); + for (int i = 0; i < creditAllocationRules.size(); i++) { + CreditAllocationOrder e = new CreditAllocationOrder(); + e.setOrder(i + 1); + e.setCreditAllocationRule(creditAllocationRules.get(i)); + creditAllocationOrders.add(e); + } + + creditAllocationData.setCreditAllocationOrder(creditAllocationOrders); + return creditAllocationData; + } + + private static List getPaymentAllocationOrder( + LoanProductPaymentAllocationRule.AllocationTypesEnum... paymentAllocations) { + AtomicInteger integer = new AtomicInteger(1); + return Arrays.stream(paymentAllocations).map(pat -> { + PaymentAllocationOrder paymentAllocationOrder = new PaymentAllocationOrder(); + paymentAllocationOrder.setPaymentAllocationRule(pat.name()); + paymentAllocationOrder.setOrder(integer.getAndIncrement()); + return paymentAllocationOrder; + }).toList(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/PaymentTypeGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/PaymentTypeGlobalInitializerStep.java new file mode 100644 index 00000000000..f7cd1415490 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/PaymentTypeGlobalInitializerStep.java @@ -0,0 +1,72 @@ +/** + * 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.test.initializer.global; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.PostPaymentTypesRequest; +import org.apache.fineract.client.services.PaymentTypeApi; +import org.apache.fineract.test.factory.PaymentTypesRequestFactory; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class PaymentTypeGlobalInitializerStep implements FineractGlobalInitializerStep { + + public static final String PAYMENT_TYPE_AUTOPAY = "AUTOPAY"; + public static final String PAYMENT_TYPE_DOWN_PAYMENT = "DOWN_PAYMENT"; + public static final String PAYMENT_TYPE_REAL_TIME = "REAL_TIME"; + public static final String PAYMENT_TYPE_SCHEDULED = "SCHEDULED"; + public static final String PAYMENT_TYPE_CHECK_PAYMENT = "CHECK_PAYMENT"; + public static final String PAYMENT_TYPE_OCA_PAYMENT = "OCA_PAYMENT"; + public static final String PAYMENT_TYPE_REPAYMENT_ADJUSTMENT_CHARGEBACK = "REPAYMENT_ADJUSTMENT_CHARGEBACK"; + public static final String PAYMENT_TYPE_REPAYMENT_ADJUSTMENT_REFUND = "REPAYMENT_ADJUSTMENT_REFUND"; + + private final PaymentTypeApi paymentTypeApi; + + @Override + public void initialize() throws Exception { + List paymentTypes = new ArrayList<>(); + paymentTypes.add(PAYMENT_TYPE_AUTOPAY); + paymentTypes.add(PAYMENT_TYPE_DOWN_PAYMENT); + paymentTypes.add(PAYMENT_TYPE_REAL_TIME); + paymentTypes.add(PAYMENT_TYPE_SCHEDULED); + paymentTypes.add(PAYMENT_TYPE_CHECK_PAYMENT); + paymentTypes.add(PAYMENT_TYPE_OCA_PAYMENT); + paymentTypes.add(PAYMENT_TYPE_REPAYMENT_ADJUSTMENT_CHARGEBACK); + paymentTypes.add(PAYMENT_TYPE_REPAYMENT_ADJUSTMENT_REFUND); + + paymentTypes.forEach(paymentType -> { + Integer position = paymentTypes.indexOf(paymentType) + 2; + PostPaymentTypesRequest postPaymentTypesRequest = PaymentTypesRequestFactory.defaultPaymentTypeRequest(paymentType, paymentType, + false, position); + + try { + paymentTypeApi.createPaymentType(postPaymentTypesRequest).execute(); + } catch (IOException e) { + throw new RuntimeException("Error while creating payment type", e); + } + }); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/SchedulerGlobalInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/SchedulerGlobalInitializerStep.java new file mode 100644 index 00000000000..3bd290047f6 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/SchedulerGlobalInitializerStep.java @@ -0,0 +1,40 @@ +/** + * 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.test.initializer.global; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.services.SchedulerApi; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class SchedulerGlobalInitializerStep implements FineractGlobalInitializerStep { + + private static final String SCHEDULER_STATUS_STOP = "stop"; + + private final SchedulerApi schedulerApi; + + @Override + public void initialize() throws Exception { + schedulerApi.changeSchedulerStatus(SCHEDULER_STATUS_STOP); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/FineractScenarioInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/FineractScenarioInitializerStep.java new file mode 100644 index 00000000000..0e433c30e21 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/FineractScenarioInitializerStep.java @@ -0,0 +1,24 @@ +/** + * 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.test.initializer.scenario; + +public interface FineractScenarioInitializerStep { + + void initializeForScenario() throws Exception; +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/GlobalConfigurationScenarioInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/GlobalConfigurationScenarioInitializerStep.java new file mode 100644 index 00000000000..cc149aebaa9 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/scenario/GlobalConfigurationScenarioInitializerStep.java @@ -0,0 +1,48 @@ +/** + * 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.test.initializer.scenario; + +import static org.apache.fineract.test.initializer.global.GlobalConfigurationGlobalInitializerStep.CONFIG_KEY_ENABLE_ADDRESS; +import static org.apache.fineract.test.initializer.global.GlobalConfigurationGlobalInitializerStep.CONFIG_KEY_ENABLE_BUSINESS_DATE; +import static org.apache.fineract.test.initializer.global.GlobalConfigurationGlobalInitializerStep.CONFIG_KEY_ENABLE_RECALCULATE_COB_DATE; + +import lombok.RequiredArgsConstructor; +import org.apache.fineract.test.helper.GlobalConfigurationHelper; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class GlobalConfigurationScenarioInitializerStep implements FineractScenarioInitializerStep { + + private final GlobalConfigurationHelper globalConfigurationHelper; + + @Override + public void initializeForScenario() throws Exception { + /** + * Enable-address set to false + */ + globalConfigurationHelper.disableGlobalConfiguration(CONFIG_KEY_ENABLE_ADDRESS, 0L); + + /** + * Enable business date and COB date + */ + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_BUSINESS_DATE, 0L); + globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_RECALCULATE_COB_DATE, 0L); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java new file mode 100644 index 00000000000..1aebd6bb0a4 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java @@ -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.test.initializer.suite; + +import static java.lang.System.lineSeparator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.ExternalEventConfigurationItemData; +import org.apache.fineract.client.models.GetExternalEventConfigurationsResponse; +import org.apache.fineract.client.models.PutExternalEventConfigurationsRequest; +import org.apache.fineract.client.services.ExternalEventConfigurationApi; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@RequiredArgsConstructor +@Component +public class ExternalEventSuiteInitializerStep implements FineractSuiteInitializerStep { + + private final ExternalEventConfigurationApi eventConfigurationApi; + + @Override + public void initializeForSuite() throws Exception { + Map eventConfigMap = new HashMap<>(); + + Response response = eventConfigurationApi.retrieveExternalEventConfiguration().execute(); + if (!response.isSuccessful()) { + String responseBody = response.errorBody().string(); + throw new RuntimeException("Cannot configure external events due to " + lineSeparator() + responseBody); + } + + List externalEventConfiguration = response.body().getExternalEventConfiguration(); + externalEventConfiguration.forEach(e -> { + eventConfigMap.put(e.getType(), true); + }); + + PutExternalEventConfigurationsRequest request = new PutExternalEventConfigurationsRequest() + .externalEventConfigurations(eventConfigMap); + + eventConfigurationApi.updateExternalEventConfigurationsDetails(request).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/FineractSuiteInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/FineractSuiteInitializerStep.java new file mode 100644 index 00000000000..9b982cb4c94 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/FineractSuiteInitializerStep.java @@ -0,0 +1,28 @@ +/** + * 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.test.initializer.suite; + +public interface FineractSuiteInitializerStep { + + void initializeForSuite() throws Exception; + + default void resetAfterSuite() throws Exception { + // noop + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java new file mode 100644 index 00000000000..db01909a75c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java @@ -0,0 +1,55 @@ +/** + * 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.test.initializer.suite; + +import java.io.IOException; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.GetJobsResponse; +import org.apache.fineract.client.models.PutJobsJobIDRequest; +import org.apache.fineract.client.services.SchedulerJobApi; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class JobSuiteInitializerStep implements FineractSuiteInitializerStep { + + public static final String SEND_ASYNCHRONOUS_EVENTS_JOB_NAME = "Send Asynchronous Events"; + public static final String EVERY_1_SECONDS = "0/1 * * * * ?"; + public static final String EVERY_60_SECONDS = "0 0/1 * * * ?"; + + private final SchedulerJobApi jobApi; + + @Override + public void initializeForSuite() throws Exception { + updateExternalEventJobFrequency(EVERY_1_SECONDS); + } + + @Override + public void resetAfterSuite() throws Exception { + updateExternalEventJobFrequency(EVERY_60_SECONDS); + } + + private void updateExternalEventJobFrequency(String cronExpression) throws IOException { + GetJobsResponse externalEventJobResponse = jobApi.retrieveAll8().execute().body().stream() + .filter(r -> r.getDisplayName().equals(SEND_ASYNCHRONOUS_EVENTS_JOB_NAME)).findAny() + .orElseThrow(() -> new IllegalStateException(SEND_ASYNCHRONOUS_EVENTS_JOB_NAME + " is not found")); + Long jobId = externalEventJobResponse.getJobId(); + jobApi.updateJobDetail(jobId, new PutJobsJobIDRequest().cronExpression(cronExpression)).execute(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EmptyEventMessage.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EmptyEventMessage.java new file mode 100644 index 00000000000..402261dc5b1 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EmptyEventMessage.java @@ -0,0 +1,26 @@ +/** + * 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.test.messaging; + +public class EmptyEventMessage extends EventMessage { + + public EmptyEventMessage() { + super(null, null, null); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventAssertion.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventAssertion.java new file mode 100644 index 00000000000..226d825ad43 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventAssertion.java @@ -0,0 +1,182 @@ +/** + * 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.test.messaging; + +import static java.lang.String.format; +import static org.awaitility.Awaitility.await; + +import java.math.BigDecimal; +import java.time.Duration; +import java.time.LocalDate; +import java.util.function.Function; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.test.messaging.config.EventProperties; +import org.apache.fineract.test.messaging.event.Event; +import org.apache.fineract.test.messaging.event.EventFactory; +import org.apache.fineract.test.messaging.store.EventStore; +import org.apache.fineract.test.messaging.store.LoggedEvent; +import org.assertj.core.api.Assertions; +import org.awaitility.core.ConditionTimeoutException; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +public class EventAssertion { + + private final EventStore eventStore; + private final EventFactory eventFactory; + private final EventProperties eventProperties; + + public > void assertEventRaised(Class eventClazz, Long id) { + internalAssertEventRaised(eventClazz, id, true); + } + + public > void assertEventNotRaised(Class eventClazz, Long id) { + internalAssertEventNotRaised(eventClazz, id); + } + + private > void internalAssertEventRaised(Class eventClazz, Long id, boolean removeEventIfFound) { + if (eventProperties.isEventVerificationDisabled()) { + return; + } + T event = eventFactory.create(eventClazz); + try { + await().atMost(Duration.ofSeconds(eventProperties.getEventWaitTimeoutInSec())).until(() -> { + if (removeEventIfFound) { + return eventStore.removeEventById(event, id).isPresent(); + } else { + return eventStore.findEventById(event, id).isPresent(); + } + }); + } catch (ConditionTimeoutException e) { + Assertions + .fail(event.getEventName() + " hasn't been received within " + eventProperties.getEventWaitTimeoutInSec() + " seconds"); + } + } + + private > void internalAssertEventNotRaised(Class eventClazz, Long id) { + if (eventProperties.isEventVerificationDisabled()) { + return; + } + T event = eventFactory.create(eventClazz); + try { + await().atMost(Duration.ofSeconds(eventProperties.getEventWaitTimeoutInSec())).until(() -> { + return eventStore.existsEventById(event, id); + }); + + String receivedEventsLogParam = eventStore.getReceivedEvents().stream().map(LoggedEvent::new).map(LoggedEvent::toString) + .reduce("", (s, e) -> format("%s%s%n", s, e)); + Assertions.fail(""" + %s has been received, but it was unexpected. + Events received but not verified: + %s + """.formatted(event.getEventName(), receivedEventsLogParam)); + } catch (ConditionTimeoutException e) { + // This is the expected outcome here! + } + } + + public > EventAssertionBuilder assertEvent(Class eventClazz, Long id) { + EventMessage eventMessage; + if (eventProperties.isEventVerificationEnabled()) { + internalAssertEventRaised(eventClazz, id, false); + T event = eventFactory.create(eventClazz); + eventMessage = eventStore.removeEventById(event, id).get(); + } else { + eventMessage = (EventMessage) new EmptyEventMessage(); + } + return new EventAssertionBuilder<>(eventMessage); + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + public class EventAssertionBuilder { + + private final EventMessage eventMessage; + + public EventAssertionBuilder isRaisedOnBusinessDate(LocalDate businessDate) { + if (eventProperties.isEventVerificationEnabled()) { + Assertions.assertThat(eventMessage.getBusinessDate()).isEqualTo(businessDate); + } + return this; + } + + public EventDataAssertionBuilder extractingData(Function valueExtractor) { + V dataValue; + if (eventProperties.isEventVerificationEnabled()) { + dataValue = valueExtractor.apply(eventMessage.getData()); + } else { + dataValue = null; + } + return new EventDataAssertionBuilder<>(eventMessage, dataValue); + } + + public EventBigDecimalAssertionBuilder extractingBigDecimal(Function valueExtractor) { + BigDecimal dataValue; + if (eventProperties.isEventVerificationEnabled()) { + dataValue = valueExtractor.apply(eventMessage.getData()); + } else { + dataValue = null; + } + return new EventBigDecimalAssertionBuilder<>(eventMessage, dataValue); + } + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + public class EventDataAssertionBuilder { + + private final EventMessage eventMessage; + private final V extractedValue; + + public EventAssertionBuilder isEqualTo(V value) { + if (eventProperties.isEventVerificationEnabled()) { + Assertions.assertThat(extractedValue).isEqualTo(value); + } + return new EventAssertionBuilder<>(eventMessage); + } + + public EventAssertionBuilder isNotEqualTo(V value) { + if (eventProperties.isEventVerificationEnabled()) { + Assertions.assertThat(extractedValue).isNotEqualTo(value); + } + return new EventAssertionBuilder<>(eventMessage); + } + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + public class EventBigDecimalAssertionBuilder { + + private final EventMessage eventMessage; + private final BigDecimal extractedValue; + + public EventAssertionBuilder isEqualTo(BigDecimal value) { + if (eventProperties.isEventVerificationEnabled()) { + Assertions.assertThat(extractedValue).isEqualByComparingTo(value); + } + return new EventAssertionBuilder<>(eventMessage); + } + + public EventAssertionBuilder isNotEqualTo(BigDecimal value) { + if (eventProperties.isEventVerificationEnabled()) { + Assertions.assertThat(extractedValue).isNotEqualByComparingTo(value); + } + return new EventAssertionBuilder<>(eventMessage); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventMessage.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventMessage.java new file mode 100644 index 00000000000..ca039edaaa1 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/EventMessage.java @@ -0,0 +1,32 @@ +/** + * 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.test.messaging; + +import java.time.LocalDate; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class EventMessage { + + private final String type; + private final LocalDate businessDate; + private final T data; +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventProperties.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventProperties.java new file mode 100644 index 00000000000..8fa4d1c07e0 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventProperties.java @@ -0,0 +1,38 @@ +/** + * 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.test.messaging.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Getter +public class EventProperties { + + @Value("${fineract-test.event.wait-timeout-in-sec}") + private int eventWaitTimeoutInSec; + + @Value("${fineract-test.event.verification-enabled}") + private boolean eventVerificationEnabled; + + public boolean isEventVerificationDisabled() { + return !isEventVerificationEnabled(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventVerificationEnabledCondition.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventVerificationEnabledCondition.java new file mode 100644 index 00000000000..8b14ed2e8d7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/EventVerificationEnabledCondition.java @@ -0,0 +1,34 @@ +/** + * 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.test.messaging.config; + +import org.apache.fineract.test.support.PropertiesCondition; + +public class EventVerificationEnabledCondition extends PropertiesCondition { + + @Override + protected Class getPropertiesClass() { + return EventProperties.class; + } + + @Override + protected boolean matches(EventProperties properties) { + return properties.isEventVerificationEnabled(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingConfiguration.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingConfiguration.java new file mode 100644 index 00000000000..f6dacc95f09 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingConfiguration.java @@ -0,0 +1,62 @@ +/** + * 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.test.messaging.config; + +import jakarta.jms.ConnectionFactory; +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.command.ActiveMQTopic; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.annotation.EnableJms; +import org.springframework.jms.config.DefaultJmsListenerContainerFactory; + +@Configuration +@Conditional(EventVerificationEnabledCondition.class) +@EnableJms +public class MessagingConfiguration { + + @Autowired + private MessagingProperties properties; + + @Bean + public ConnectionFactory activeMQConnectionFactory() { + ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(); + connectionFactory.setBrokerURL(properties.getBrokerUrl()); + if (isBrokerPasswordProtected()) { + connectionFactory.setUserName(properties.getBrokerUsername()); + connectionFactory.setPassword(properties.getBrokerPassword()); + } + return connectionFactory; + } + + @Bean + public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { + DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); + factory.setConnectionFactory(activeMQConnectionFactory()); + factory.setDestinationResolver((session, destinationName, pubSubDomain) -> new ActiveMQTopic(destinationName)); + return factory; + } + + private boolean isBrokerPasswordProtected() { + return StringUtils.isNotBlank(properties.getBrokerUsername()) || StringUtils.isNotBlank(properties.getBrokerPassword()); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingProperties.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingProperties.java new file mode 100644 index 00000000000..2c121be7eda --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/config/MessagingProperties.java @@ -0,0 +1,53 @@ +/** + * 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.test.messaging.config; + +import static org.apache.commons.lang3.StringUtils.isBlank; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Getter +@Component +@RequiredArgsConstructor +public class MessagingProperties implements InitializingBean { + + @Value("${fineract-test.messaging.jms.broker-url}") + private String brokerUrl; + @Value("${fineract-test.messaging.jms.broker-username}") + private String brokerUsername; + @Value("${fineract-test.messaging.jms.broker-password}") + private String brokerPassword; + @Value("${fineract-test.messaging.jms.topic-name}") + private String topicName; + + private final EventProperties eventProperties; + + @Override + public void afterPropertiesSet() throws Exception { + if (eventProperties.isEventVerificationEnabled()) { + if (isBlank(brokerUrl) || isBlank(topicName)) { + throw new IllegalStateException("Broker and topic must be configured in case event verification is enabled"); + } + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/Event.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/Event.java new file mode 100644 index 00000000000..a7216543e1e --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/Event.java @@ -0,0 +1,30 @@ +/** + * 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.test.messaging.event; + +import java.util.function.Function; + +public interface Event { + + String getEventName(); + + Class getDataClass(); + + Function getIdExtractor(); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java new file mode 100644 index 00000000000..83eedb213dd --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java @@ -0,0 +1,409 @@ +/** + * 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.test.messaging.event; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.math.BigDecimal; +import java.time.format.DateTimeFormatter; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.avro.client.v1.ClientDataV1; +import org.apache.fineract.avro.loan.v1.DelinquencyPausePeriodV1; +import org.apache.fineract.avro.loan.v1.LoanAccountDataV1; +import org.apache.fineract.avro.loan.v1.LoanAmountDataV1; +import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1; +import org.apache.fineract.avro.loan.v1.LoanOwnershipTransferDataV1; +import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1; +import org.apache.fineract.client.models.ExternalTransferData; +import org.apache.fineract.client.models.GetClientsClientIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdDelinquencyPausePeriod; +import org.apache.fineract.client.models.GetLoansLoanIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdTransactions; +import org.apache.fineract.client.models.PageExternalTransferData; +import org.apache.fineract.client.models.PostClientsResponse; +import org.apache.fineract.client.models.PostLoansLoanIdResponse; +import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; +import org.apache.fineract.client.models.PostLoansResponse; +import org.apache.fineract.client.services.ClientApi; +import org.apache.fineract.client.services.ExternalAssetOwnersApi; +import org.apache.fineract.client.services.LoansApi; +import org.apache.fineract.test.data.AssetExternalizationTransferStatus; +import org.apache.fineract.test.data.AssetExternalizationTransferStatusReason; +import org.apache.fineract.test.data.TransactionType; +import org.apache.fineract.test.helper.ErrorMessageHelper; +import org.apache.fineract.test.messaging.EventAssertion; +import org.apache.fineract.test.messaging.event.assetexternalization.LoanAccountSnapshotEvent; +import org.apache.fineract.test.messaging.event.assetexternalization.LoanOwnershipTransferEvent; +import org.apache.fineract.test.messaging.event.client.ClientActivatedEvent; +import org.apache.fineract.test.messaging.event.client.ClientCreatedEvent; +import org.apache.fineract.test.messaging.event.loan.LoanApprovedEvent; +import org.apache.fineract.test.messaging.event.loan.LoanCreatedEvent; +import org.apache.fineract.test.messaging.event.loan.LoanDisbursalEvent; +import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyPauseChangedEvent; +import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyRangeChangeEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.AbstractLoanTransactionEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanDisbursalTransactionEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanRefundPostBusinessEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionGoodwillCreditPostEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionMakeRepaymentPostEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionMerchantIssuedRefundPostEvent; +import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionPayoutRefundPostEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import retrofit2.Response; + +@Slf4j +@Component +@RequiredArgsConstructor +public class EventCheckHelper { + + private static final DateTimeFormatter FORMATTER_EVENTS = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + @Autowired + private ClientApi clientApi; + + @Autowired + private LoansApi loansApi; + + @Autowired + private EventAssertion eventAssertion; + + @Autowired + private ExternalAssetOwnersApi externalAssetOwnersApi; + + public void clientEventCheck(Response clientCreationResponse) throws IOException { + Response clientDetails = clientApi.retrieveOne11(clientCreationResponse.body().getClientId(), false) + .execute(); + + GetClientsClientIdResponse body = clientDetails.body(); + Long clientId = Long.valueOf(body.getId()); + Integer status = body.getStatus().getId().intValue(); + String firstname = body.getFirstname(); + String lastname = body.getLastname(); + Boolean active = body.getActive(); + + eventAssertion.assertEvent(ClientCreatedEvent.class, clientCreationResponse.body().getClientId())// + .extractingData(ClientDataV1::getId).isEqualTo(clientId)// + .extractingData(clientDataV1 -> clientDataV1.getStatus().getId()).isEqualTo(status)// + .extractingData(ClientDataV1::getFirstname).isEqualTo(firstname)// + .extractingData(ClientDataV1::getLastname).isEqualTo(lastname)// + .extractingData(ClientDataV1::getActive).isEqualTo(active);// + + eventAssertion.assertEvent(ClientActivatedEvent.class, clientCreationResponse.body().getClientId())// + .extractingData(ClientDataV1::getActive).isEqualTo(true)// + .extractingData(clientDataV1 -> clientDataV1.getStatus().getId()).isEqualTo(status);// + + } + + public void createLoanEventCheck(Response createLoanResponse) throws IOException { + Response loanDetails = loansApi.retrieveLoan(createLoanResponse.body().getLoanId(), false, "", "", "") + .execute(); + GetLoansLoanIdResponse body = loanDetails.body(); + + eventAssertion.assertEvent(LoanCreatedEvent.class, createLoanResponse.body().getLoanId()).extractingData(LoanAccountDataV1::getId) + .isEqualTo(body.getId()).extractingData(loanAccountDataV1 -> loanAccountDataV1.getStatus().getId()) + .isEqualTo(body.getStatus().getId()).extractingData(LoanAccountDataV1::getClientId) + .isEqualTo(Long.valueOf(body.getClientId())) + .extractingData(loanAccountDataV11 -> loanAccountDataV11.getPrincipal().longValue()) + .isEqualTo(body.getPrincipal().longValue()) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getCurrency().getCode()) + .isEqualTo(body.getCurrency().getCode()); + } + + public void approveLoanEventCheck(Response loanApproveResponse) throws IOException { + Response loanDetails = loansApi.retrieveLoan(loanApproveResponse.body().getLoanId(), false, "", "", "") + .execute(); + GetLoansLoanIdResponse body = loanDetails.body(); + + eventAssertion.assertEvent(LoanApprovedEvent.class, loanApproveResponse.body().getLoanId()).extractingData(LoanAccountDataV1::getId) + .isEqualTo(body.getId()).extractingData(loanAccountDataV1 -> loanAccountDataV1.getStatus().getId()) + .isEqualTo(body.getStatus().getId()).extractingData(loanAccountDataV1 -> loanAccountDataV1.getStatus().getCode()) + .isEqualTo(body.getStatus().getCode()).extractingData(LoanAccountDataV1::getClientId) + .isEqualTo(Long.valueOf(body.getClientId())) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getApprovedPrincipal().longValue()) + .isEqualTo(body.getApprovedPrincipal().longValue()) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getTimeline().getApprovedOnDate()) + .isEqualTo(FORMATTER_EVENTS.format(body.getTimeline().getApprovedOnDate())) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getCurrency().getCode()) + .isEqualTo(body.getCurrency().getCode()); + } + + public void disburseLoanEventCheck(Response loanDisburseResponse) throws IOException { + Response loanDetails = loansApi.retrieveLoan(loanDisburseResponse.body().getLoanId(), false, "", "", "") + .execute(); + GetLoansLoanIdResponse body = loanDetails.body(); + + eventAssertion.assertEvent(LoanDisbursalEvent.class, loanDisburseResponse.body().getLoanId())// + .extractingData(LoanAccountDataV1::getId).isEqualTo(body.getId())// + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getStatus().getId()).isEqualTo(body.getStatus().getId())// + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getStatus().getCode()).isEqualTo(body.getStatus().getCode())// + .extractingData(LoanAccountDataV1::getClientId).isEqualTo(Long.valueOf(body.getClientId()))// + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getPrincipalDisbursed().longValue()) + .isEqualTo(body.getSummary().getPrincipalDisbursed().longValue())// + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getTimeline().getActualDisbursementDate()) + .isEqualTo(FORMATTER_EVENTS.format(body.getTimeline().getActualDisbursementDate())) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getCurrency().getCode()) + .isEqualTo(body.getCurrency().getCode());// + } + + public void loanDisbursalTransactionEventCheck(Response loanDisburseResponse) throws IOException { + Long disbursementTransactionId = loanDisburseResponse.body().getSubResourceId(); + + Response loanDetails = loansApi + .retrieveLoan(loanDisburseResponse.body().getLoanId(), false, "transactions", "", "").execute(); + GetLoansLoanIdResponse body = loanDetails.body(); + List transactions = body.getTransactions(); + GetLoansLoanIdTransactions disbursementTransaction = transactions// + .stream()// + .filter(t -> t.getId().equals(disbursementTransactionId))// + .findFirst()// + .orElseThrow(() -> new IllegalStateException("Disbursement transaction not found"));// + + eventAssertion.assertEvent(LoanDisbursalTransactionEvent.class, disbursementTransaction.getId())// + .extractingData(LoanTransactionDataV1::getLoanId).isEqualTo(body.getId())// + .extractingData(LoanTransactionDataV1::getDate).isEqualTo(FORMATTER_EVENTS.format(disbursementTransaction.getDate()))// + .extractingData(loanTransactionDataV1 -> loanTransactionDataV1.getAmount().longValue()) + .isEqualTo(disbursementTransaction.getAmount().longValue());// + } + + public EventAssertion.EventAssertionBuilder transactionEventCheck( + Response transactionResponse, TransactionType transactionType, String externalOwnerId) + throws IOException { + Long loanId = transactionResponse.body().getLoanId(); + Long transactionId = transactionResponse.body().getResourceId(); + Response loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute(); + List transactions = loanDetailsResponse.body().getTransactions(); + GetLoansLoanIdTransactions transactionFound = transactions// + .stream()// + .filter(t -> t.getId().equals(transactionId))// + .findAny()// + .orElseThrow(() -> new IllegalStateException("Transaction cannot be found"));// + + Class eventClass = switch (transactionType) { + case REPAYMENT -> LoanTransactionMakeRepaymentPostEvent.class; + case GOODWILL_CREDIT -> LoanTransactionGoodwillCreditPostEvent.class; + case PAYOUT_REFUND -> LoanTransactionPayoutRefundPostEvent.class; + case MERCHANT_ISSUED_REFUND -> LoanTransactionMerchantIssuedRefundPostEvent.class; + case REFUND_BY_CASH -> LoanRefundPostBusinessEvent.class; + default -> throw new IllegalStateException(String.format("transaction type %s cannot be found", transactionType.getValue())); + }; + + EventAssertion.EventAssertionBuilder eventBuilder = eventAssertion.assertEvent(eventClass, transactionId); + eventBuilder.extractingData(LoanTransactionDataV1::getLoanId).isEqualTo(loanDetailsResponse.body().getId())// + .extractingData(LoanTransactionDataV1::getDate).isEqualTo(FORMATTER_EVENTS.format(transactionFound.getDate()))// + .extractingData(loanTransactionDataV1 -> loanTransactionDataV1.getAmount().longValue()) + .isEqualTo(transactionFound.getAmount().longValue())// + .extractingData(LoanTransactionDataV1::getExternalOwnerId).isEqualTo(externalOwnerId);// + return eventBuilder; + } + + public void loanOwnershipTransferBusinessEventCheck(Long loanId, Long transferId) throws IOException { + Response response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute(); + List content = response.body().getContent(); + + ExternalTransferData filtered = content.stream().filter(t -> transferId.equals(t.getTransferId())).reduce((first, second) -> second) + .orElseThrow(() -> new IllegalStateException("No element found")); + + BigDecimal totalOutstandingBalanceAmountExpected = zeroConversion(filtered.getDetails().getTotalOutstanding()); + BigDecimal outstandingPrincipalPortionExpected = zeroConversion(filtered.getDetails().getTotalPrincipalOutstanding()); + BigDecimal outstandingFeePortionExpected = zeroConversion(filtered.getDetails().getTotalFeeChargesOutstanding()); + BigDecimal outstandingPenaltyPortionExpected = zeroConversion(filtered.getDetails().getTotalPenaltyChargesOutstanding()); + BigDecimal outstandingInterestPortionExpected = zeroConversion(filtered.getDetails().getTotalInterestOutstanding()); + BigDecimal overPaymentPortionExpected = zeroConversion(filtered.getDetails().getTotalOverpaid()); + + eventAssertion.assertEvent(LoanOwnershipTransferEvent.class, loanId).extractingData(LoanOwnershipTransferDataV1::getLoanId) + .isEqualTo(loanId).extractingData(LoanOwnershipTransferDataV1::getAssetOwnerExternalId) + .isEqualTo(filtered.getOwner().getExternalId()).extractingData(LoanOwnershipTransferDataV1::getTransferExternalId) + .isEqualTo(filtered.getTransferExternalId()).extractingData(LoanOwnershipTransferDataV1::getSettlementDate) + .isEqualTo(FORMATTER_EVENTS.format(filtered.getSettlementDate())) + .extractingData(LoanOwnershipTransferDataV1::getTotalOutstandingBalanceAmount) + .isEqualTo(totalOutstandingBalanceAmountExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingPrincipalPortion).isEqualTo(outstandingPrincipalPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingFeePortion).isEqualTo(outstandingFeePortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingPenaltyPortion).isEqualTo(outstandingPenaltyPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingInterestPortion).isEqualTo(outstandingInterestPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOverPaymentPortion).isEqualTo(overPaymentPortionExpected); + } + + public void loanOwnershipTransferBusinessEventWithStatusCheck(Long loanId, Long transferId, String transferStatus, + String transferStatusReason) throws IOException { + Response response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute(); + List content = response.body().getContent(); + + ExternalTransferData filtered = content.stream().filter(t -> transferId.equals(t.getTransferId())).reduce((first, second) -> second) + .orElseThrow(() -> new IllegalStateException("No element found")); + + BigDecimal totalOutstandingBalanceAmountExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalOutstanding()); + BigDecimal outstandingPrincipalPortionExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalPrincipalOutstanding()); + BigDecimal outstandingFeePortionExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalFeeChargesOutstanding()); + BigDecimal outstandingPenaltyPortionExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalPenaltyChargesOutstanding()); + BigDecimal outstandingInterestPortionExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalInterestOutstanding()); + BigDecimal overPaymentPortionExpected = filtered.getDetails() == null ? null + : zeroConversion(filtered.getDetails().getTotalOverpaid()); + + AssetExternalizationTransferStatus transferStatusType = AssetExternalizationTransferStatus.valueOf(transferStatus); + String transferStatusExpected = transferStatusType.getValue(); + + AssetExternalizationTransferStatusReason transferStatusReasonType = AssetExternalizationTransferStatusReason + .valueOf(transferStatusReason); + String transferStatusReasonExpected = transferStatusReasonType.getValue(); + + eventAssertion.assertEvent(LoanOwnershipTransferEvent.class, loanId).extractingData(LoanOwnershipTransferDataV1::getLoanId) + .isEqualTo(loanId).extractingData(LoanOwnershipTransferDataV1::getAssetOwnerExternalId) + .isEqualTo(filtered.getOwner().getExternalId()).extractingData(LoanOwnershipTransferDataV1::getTransferExternalId) + .isEqualTo(filtered.getTransferExternalId()).extractingData(LoanOwnershipTransferDataV1::getSettlementDate) + .isEqualTo(FORMATTER_EVENTS.format(filtered.getSettlementDate())) + .extractingData(LoanOwnershipTransferDataV1::getTotalOutstandingBalanceAmount) + .isEqualTo(totalOutstandingBalanceAmountExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingPrincipalPortion).isEqualTo(outstandingPrincipalPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingFeePortion).isEqualTo(outstandingFeePortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingPenaltyPortion).isEqualTo(outstandingPenaltyPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOutstandingInterestPortion).isEqualTo(outstandingInterestPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getOverPaymentPortion).isEqualTo(overPaymentPortionExpected) + .extractingData(LoanOwnershipTransferDataV1::getTransferStatus).isEqualTo(transferStatusExpected) + .extractingData(LoanOwnershipTransferDataV1::getTransferStatusReason).isEqualTo(transferStatusReasonExpected); + } + + public void loanAccountSnapshotBusinessEventCheck(Long loanId, Long transferId) throws IOException { + Response response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute(); + List content = response.body().getContent(); + + ExternalTransferData filtered = content.stream().filter(t -> transferId.equals(t.getTransferId())).reduce((first, second) -> second) + .orElseThrow(() -> new IllegalStateException("No element found")); + + String ownerExternalIdExpected = filtered.getStatus().getValue().equals("BUYBACK") ? null : filtered.getOwner().getExternalId(); + String settlementDateExpected = filtered.getStatus().getValue().equals("BUYBACK") ? null + : FORMATTER_EVENTS.format(filtered.getSettlementDate()); + BigDecimal totalOutstandingBalanceAmountExpected = zeroConversion(filtered.getDetails().getTotalOutstanding()); + BigDecimal outstandingPrincipalPortionExpected = zeroConversion(filtered.getDetails().getTotalPrincipalOutstanding()); + BigDecimal outstandingFeePortionExpected = zeroConversion(filtered.getDetails().getTotalFeeChargesOutstanding()); + BigDecimal outstandingPenaltyPortionExpected = zeroConversion(filtered.getDetails().getTotalPenaltyChargesOutstanding()); + BigDecimal outstandingInterestPortionExpected = zeroConversion(filtered.getDetails().getTotalInterestOutstanding()); + BigDecimal overPaymentPortionExpected = zeroConversion(filtered.getDetails().getTotalOverpaid()); + + eventAssertion.assertEvent(LoanAccountSnapshotEvent.class, loanId).extractingData(LoanAccountDataV1::getId).isEqualTo(loanId) + .extractingData(LoanAccountDataV1::getExternalOwnerId).isEqualTo(ownerExternalIdExpected) + .extractingData(LoanAccountDataV1::getSettlementDate).isEqualTo(settlementDateExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getTotalOutstanding()) + .isEqualTo(totalOutstandingBalanceAmountExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getPrincipalOutstanding()) + .isEqualTo(outstandingPrincipalPortionExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getFeeChargesOutstanding()) + .isEqualTo(outstandingFeePortionExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getPenaltyChargesOutstanding()) + .isEqualTo(outstandingPenaltyPortionExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getInterestOutstanding()) + .isEqualTo(outstandingInterestPortionExpected) + .extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getTotalOverdue()) + .isEqualTo(overPaymentPortionExpected); + } + + public void loanAccountDelinquencyPauseChangedBusinessEventCheck(Long loanId) throws IOException { + Response loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute(); + List delinquencyPausePeriodsActual = loanDetails.body().getDelinquent() + .getDelinquencyPausePeriods(); + + eventAssertion.assertEvent(LoanDelinquencyPauseChangedEvent.class, loanId)// + .extractingData(LoanAccountDataV1::getId).isEqualTo(loanId)// + .extractingData(loanAccountDataV1 -> { + List delinquencyPausePeriodsExpected = loanAccountDataV1.getDelinquent() + .getDelinquencyPausePeriods(); + + for (int i = 0; i < delinquencyPausePeriodsActual.size(); i++) { + Boolean isActiveActual = delinquencyPausePeriodsActual.get(i).getActive(); + String pausePeriodStartActual = FORMATTER_EVENTS.format(delinquencyPausePeriodsActual.get(i).getPausePeriodStart()); + String pausePeriodEndActual = FORMATTER_EVENTS.format(delinquencyPausePeriodsActual.get(i).getPausePeriodEnd()); + + Boolean isActiveExpected = delinquencyPausePeriodsExpected.get(i).getActive(); + String pausePeriodStartExpected = delinquencyPausePeriodsExpected.get(i).getPausePeriodStart(); + String pausePeriodEndExpected = delinquencyPausePeriodsExpected.get(i).getPausePeriodEnd(); + + assertThat(isActiveActual)// + .as(ErrorMessageHelper.wrongValueInPauseDelinquencyEventActive(i, isActiveActual, isActiveExpected))// + .isEqualTo(isActiveExpected);// + assertThat(pausePeriodStartActual)// + .as(ErrorMessageHelper.wrongValueInPauseDelinquencyEventStartDate(i, pausePeriodStartActual, + pausePeriodStartExpected))// + .isEqualTo(pausePeriodStartExpected);// + assertThat(pausePeriodEndActual)// + .as(ErrorMessageHelper.wrongValueInPauseDelinquencyEventEndDate(i, pausePeriodEndActual, + pausePeriodEndExpected))// + .isEqualTo(pausePeriodEndExpected);// + + log.info("LoanAccountDelinquencyPauseChangedBusinessEvent -> isActiveActual:\s{}", isActiveActual); + log.info("LoanAccountDelinquencyPauseChangedBusinessEvent -> pausePeriodStartActual:\s{}", pausePeriodStartActual); + log.info("LoanAccountDelinquencyPauseChangedBusinessEvent -> pausePeriodEndActual:\s{}", pausePeriodEndActual); + } + return null; + }); + } + + public void installmentLevelDelinquencyRangeChangeEventCheck(Long loanId) throws IOException { + eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId).extractingData(loanAccountDelinquencyRangeDataV1 -> { + // check if sum of total amounts equal the sum of amount types in installmentDelinquencyBuckets + BigDecimal totalAmountSum = loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().stream()// + .map(LoanInstallmentDelinquencyBucketDataV1::getAmount)// + .map(LoanAmountDataV1::getTotalAmount)// + .reduce(BigDecimal.ZERO, BigDecimal::add);// + BigDecimal principalAmountSum = loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().stream()// + .map(LoanInstallmentDelinquencyBucketDataV1::getAmount)// + .map(LoanAmountDataV1::getPrincipalAmount)// + .reduce(BigDecimal.ZERO, BigDecimal::add);// + BigDecimal interestAmountSum = loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().stream()// + .map(LoanInstallmentDelinquencyBucketDataV1::getAmount)// + .map(LoanAmountDataV1::getInterestAmount)// + .reduce(BigDecimal.ZERO, BigDecimal::add);// + BigDecimal feeAmountSum = loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().stream()// + .map(LoanInstallmentDelinquencyBucketDataV1::getAmount)// + .map(LoanAmountDataV1::getFeeAmount)// + .reduce(BigDecimal.ZERO, BigDecimal::add);// + BigDecimal penaltyAmountSum = loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().stream()// + .map(LoanInstallmentDelinquencyBucketDataV1::getAmount)// + .map(LoanAmountDataV1::getPenaltyAmount)// + .reduce(BigDecimal.ZERO, BigDecimal::add);// + + BigDecimal totalAmountSumActual = principalAmountSum.add(interestAmountSum).add(feeAmountSum).add(penaltyAmountSum); + + assertThat(totalAmountSum) + .as(ErrorMessageHelper.wrongAmountInLoanDelinquencyRangeChangedEventTotalAmount(totalAmountSum, totalAmountSumActual)) + .isEqualTo(totalAmountSumActual); + + log.info("Nr of installment level delinquency buckets: {}", + loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().size()); + log.info("Buckets:"); + loanAccountDelinquencyRangeDataV1.getInstallmentDelinquencyBuckets().forEach(e -> { + log.info("{}\s-\sTotal amount:\s{}", e.getDelinquencyRange().getClassification(), e.getAmount().getTotalAmount()); + }); + + return null; + }); + } + + private BigDecimal zeroConversion(BigDecimal input) { + return input.compareTo(BigDecimal.ZERO) == 0 ? new BigDecimal(input.toEngineeringString()) : input.setScale(8); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventFactory.java new file mode 100644 index 00000000000..7f0d9763cd8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventFactory.java @@ -0,0 +1,38 @@ +/** + * 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.test.messaging.event; + +import java.lang.reflect.Constructor; +import org.springframework.stereotype.Component; +import org.springframework.util.ReflectionUtils; + +@Component +public class EventFactory { + + public > T create(Class eventClass) { + try { + Constructor constructor = ReflectionUtils.accessibleConstructor(eventClass); + return constructor.newInstance(); + } catch (NoSuchMethodException e) { + throw new RuntimeException("No no-arg constructor is available for class " + eventClass.getSimpleName(), e); + } catch (Exception e) { + throw new RuntimeException("Error while instantiating event " + eventClass.getSimpleName(), e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/AbstractLoanOwnershipTransferEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/AbstractLoanOwnershipTransferEvent.java new file mode 100644 index 00000000000..f165222c03b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/AbstractLoanOwnershipTransferEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.assetexternalization; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanOwnershipTransferDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanOwnershipTransferEvent implements Event { + + @Override + public Class getDataClass() { + return LoanOwnershipTransferDataV1.class; + } + + @Override + public Function getIdExtractor() { + return loanOwnershipTransferDataV1 -> (Long) loanOwnershipTransferDataV1.getLoanId(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountCustomSnapshotEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountCustomSnapshotEvent.java new file mode 100644 index 00000000000..d4fe08f4a45 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountCustomSnapshotEvent.java @@ -0,0 +1,29 @@ +/** + * 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.test.messaging.event.assetexternalization; + +import org.apache.fineract.test.messaging.event.loan.AbstractLoanEvent; + +public class LoanAccountCustomSnapshotEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanAccountCustomSnapshotBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountSnapshotEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountSnapshotEvent.java new file mode 100644 index 00000000000..379e147c8fd --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanAccountSnapshotEvent.java @@ -0,0 +1,29 @@ +/** + * 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.test.messaging.event.assetexternalization; + +import org.apache.fineract.test.messaging.event.loan.AbstractLoanEvent; + +public class LoanAccountSnapshotEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanAccountSnapshotBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanOwnershipTransferEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanOwnershipTransferEvent.java new file mode 100644 index 00000000000..475fd0d7dbc --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/assetexternalization/LoanOwnershipTransferEvent.java @@ -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.test.messaging.event.assetexternalization; + +public class LoanOwnershipTransferEvent extends AbstractLoanOwnershipTransferEvent { + + @Override + public String getEventName() { + return "LoanOwnershipTransferBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/AbstractClientEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/AbstractClientEvent.java new file mode 100644 index 00000000000..e7e7b1b597c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/AbstractClientEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.client; + +import java.util.function.Function; +import org.apache.fineract.avro.client.v1.ClientDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractClientEvent implements Event { + + @Override + public Class getDataClass() { + return ClientDataV1.class; + } + + @Override + public Function getIdExtractor() { + return ClientDataV1::getId; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientActivatedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientActivatedEvent.java new file mode 100644 index 00000000000..ca6918343dd --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientActivatedEvent.java @@ -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.test.messaging.event.client; + +public class ClientActivatedEvent extends AbstractClientEvent { + + @Override + public String getEventName() { + return "ClientActivateBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientCreatedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientCreatedEvent.java new file mode 100644 index 00000000000..563722d12a2 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/client/ClientCreatedEvent.java @@ -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.test.messaging.event.client; + +public class ClientCreatedEvent extends AbstractClientEvent { + + @Override + public String getEventName() { + return "ClientCreateBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/AbstractLoanEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/AbstractLoanEvent.java new file mode 100644 index 00000000000..e691d5345ca --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/AbstractLoanEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.loan; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanAccountDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanEvent implements Event { + + @Override + public Class getDataClass() { + return LoanAccountDataV1.class; + } + + @Override + public Function getIdExtractor() { + return LoanAccountDataV1::getId; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanApprovedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanApprovedEvent.java new file mode 100644 index 00000000000..a1252f3382a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanApprovedEvent.java @@ -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.test.messaging.event.loan; + +public class LoanApprovedEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanApprovedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanBalanceChangedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanBalanceChangedEvent.java new file mode 100644 index 00000000000..6465cb7b798 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanBalanceChangedEvent.java @@ -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.test.messaging.event.loan; + +public class LoanBalanceChangedEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanBalanceChangedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanCreatedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanCreatedEvent.java new file mode 100644 index 00000000000..025bf2861a8 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanCreatedEvent.java @@ -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.test.messaging.event.loan; + +public class LoanCreatedEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanCreatedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanDisbursalEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanDisbursalEvent.java new file mode 100644 index 00000000000..e63ad1a5b0c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanDisbursalEvent.java @@ -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.test.messaging.event.loan; + +public class LoanDisbursalEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanDisbursalBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAgeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAgeEvent.java new file mode 100644 index 00000000000..452a1cece0a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAgeEvent.java @@ -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.test.messaging.event.loan; + +public class LoanReAgeEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanReAgeBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAmortizeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAmortizeEvent.java new file mode 100644 index 00000000000..ea8d217b6c4 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanReAmortizeEvent.java @@ -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.test.messaging.event.loan; + +public class LoanReAmortizeEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanReAmortizeBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanRescheduledDueAdjustScheduleEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanRescheduledDueAdjustScheduleEvent.java new file mode 100644 index 00000000000..e4876647f74 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanRescheduledDueAdjustScheduleEvent.java @@ -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.test.messaging.event.loan; + +public class LoanRescheduledDueAdjustScheduleEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanRescheduledDueAdjustScheduleBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanStatusChangedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanStatusChangedEvent.java new file mode 100644 index 00000000000..9685e1195ec --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/LoanStatusChangedEvent.java @@ -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.test.messaging.event.loan; + +public class LoanStatusChangedEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanStatusChangedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/AbstractLoanChargeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/AbstractLoanChargeEvent.java new file mode 100644 index 00000000000..3b334acda6a --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/AbstractLoanChargeEvent.java @@ -0,0 +1,37 @@ +/** + * 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.test.messaging.event.loan.charge; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanChargeDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanChargeEvent implements Event { + + @Override + public Class getDataClass() { + return LoanChargeDataV1.class; + } + + @Override + public Function getIdExtractor() { + return LoanChargeDataV1::getId; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/LoanAddChargeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/LoanAddChargeEvent.java new file mode 100644 index 00000000000..96e81e3cb14 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/charge/LoanAddChargeEvent.java @@ -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.test.messaging.event.loan.charge; + +public class LoanAddChargeEvent extends AbstractLoanChargeEvent { + + @Override + public String getEventName() { + return "LoanAddChargeBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/AbstractLoanDelinquencyRangeChangeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/AbstractLoanDelinquencyRangeChangeEvent.java new file mode 100644 index 00000000000..cff5b97b485 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/AbstractLoanDelinquencyRangeChangeEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.loan.delinquency; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanAccountDelinquencyRangeDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanDelinquencyRangeChangeEvent implements Event { + + @Override + public Class getDataClass() { + return LoanAccountDelinquencyRangeDataV1.class; + } + + @Override + public Function getIdExtractor() { + return loanAccountDelinquencyRangeDataV1 -> (Long) loanAccountDelinquencyRangeDataV1.getLoanId(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyPauseChangedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyPauseChangedEvent.java new file mode 100644 index 00000000000..ed25cba148f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyPauseChangedEvent.java @@ -0,0 +1,29 @@ +/** + * 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.test.messaging.event.loan.delinquency; + +import org.apache.fineract.test.messaging.event.loan.AbstractLoanEvent; + +public class LoanDelinquencyPauseChangedEvent extends AbstractLoanEvent { + + @Override + public String getEventName() { + return "LoanAccountDelinquencyPauseChangedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyRangeChangeEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyRangeChangeEvent.java new file mode 100644 index 00000000000..1ea205accbf --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/delinquency/LoanDelinquencyRangeChangeEvent.java @@ -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.test.messaging.event.loan.delinquency; + +public class LoanDelinquencyRangeChangeEvent extends AbstractLoanDelinquencyRangeChangeEvent { + + @Override + public String getEventName() { + return "LoanDelinquencyRangeChangeBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/AbstractLoanRepaymentDueEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/AbstractLoanRepaymentDueEvent.java new file mode 100644 index 00000000000..81df01d4d3f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/AbstractLoanRepaymentDueEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.loan.repayment; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanRepaymentDueDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanRepaymentDueEvent implements Event { + + @Override + public Class getDataClass() { + return LoanRepaymentDueDataV1.class; + } + + @Override + public Function getIdExtractor() { + return loanRepaymentDueDataV1 -> (Long) loanRepaymentDueDataV1.getLoanId(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentDueEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentDueEvent.java new file mode 100644 index 00000000000..085ae8dbc8c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentDueEvent.java @@ -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.test.messaging.event.loan.repayment; + +public class LoanRepaymentDueEvent extends AbstractLoanRepaymentDueEvent { + + @Override + public String getEventName() { + return "LoanRepaymentDueBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentOverdueEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentOverdueEvent.java new file mode 100644 index 00000000000..5c5199b08ca --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/repayment/LoanRepaymentOverdueEvent.java @@ -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.test.messaging.event.loan.repayment; + +public class LoanRepaymentOverdueEvent extends AbstractLoanRepaymentDueEvent { + + @Override + public String getEventName() { + return "LoanRepaymentOverdueBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/AbstractLoanTransactionEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/AbstractLoanTransactionEvent.java new file mode 100644 index 00000000000..3fe0ee9f232 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/AbstractLoanTransactionEvent.java @@ -0,0 +1,36 @@ +/** + * 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.test.messaging.event.loan.transaction; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public abstract class AbstractLoanTransactionEvent implements Event { + + @Override + public Class getDataClass() { + return LoanTransactionDataV1.class; + } + + @Override + public Function getIdExtractor() { + return LoanTransactionDataV1::getId; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAccrualTransactionCreatedBusinessEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAccrualTransactionCreatedBusinessEvent.java new file mode 100644 index 00000000000..96370c16b30 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAccrualTransactionCreatedBusinessEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanAccrualTransactionCreatedBusinessEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanAccrualTransactionCreatedBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAdjustTransactionBusinessEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAdjustTransactionBusinessEvent.java new file mode 100644 index 00000000000..70841581cff --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanAdjustTransactionBusinessEvent.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.messaging.event.loan.transaction; + +import java.util.function.Function; +import org.apache.fineract.avro.loan.v1.LoanTransactionAdjustmentDataV1; +import org.apache.fineract.test.messaging.event.Event; + +public class LoanAdjustTransactionBusinessEvent implements Event { + + @Override + public Class getDataClass() { + return LoanTransactionAdjustmentDataV1.class; + } + + @Override + public Function getIdExtractor() { + return loanTransactionAdjustmentDataV1 -> (Long) loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId(); + } + + @Override + public String getEventName() { + return "LoanAdjustTransactionBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffEvent.java new file mode 100644 index 00000000000..0c840ffaf8b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanChargeOffEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanChargeOffPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffUndoEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffUndoEvent.java new file mode 100644 index 00000000000..e2534a8917c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargeOffUndoEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanChargeOffUndoEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanUndoChargeOffBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargebackTransactionEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargebackTransactionEvent.java new file mode 100644 index 00000000000..4e19f1ea754 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanChargebackTransactionEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanChargebackTransactionEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanChargebackTransactionBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanDisbursalTransactionEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanDisbursalTransactionEvent.java new file mode 100644 index 00000000000..bdc392b920b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanDisbursalTransactionEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanDisbursalTransactionEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanDisbursalTransactionBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanRefundPostBusinessEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanRefundPostBusinessEvent.java new file mode 100644 index 00000000000..76bb6d65a8f --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanRefundPostBusinessEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanRefundPostBusinessEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanRefundPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionGoodwillCreditPostEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionGoodwillCreditPostEvent.java new file mode 100644 index 00000000000..e8dd8aeb2c5 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionGoodwillCreditPostEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanTransactionGoodwillCreditPostEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanTransactionGoodwillCreditPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMakeRepaymentPostEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMakeRepaymentPostEvent.java new file mode 100644 index 00000000000..f53cd435ade --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMakeRepaymentPostEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanTransactionMakeRepaymentPostEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanTransactionMakeRepaymentPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMerchantIssuedRefundPostEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMerchantIssuedRefundPostEvent.java new file mode 100644 index 00000000000..632b206edcf --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionMerchantIssuedRefundPostEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanTransactionMerchantIssuedRefundPostEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanTransactionMerchantIssuedRefundPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionPayoutRefundPostEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionPayoutRefundPostEvent.java new file mode 100644 index 00000000000..1c9b1cd89eb --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/loan/transaction/LoanTransactionPayoutRefundPostEvent.java @@ -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.test.messaging.event.loan.transaction; + +public class LoanTransactionPayoutRefundPostEvent extends AbstractLoanTransactionEvent { + + @Override + public String getEventName() { + return "LoanTransactionPayoutRefundPostBusinessEvent"; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/EventStore.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/EventStore.java new file mode 100644 index 00000000000..91b4051bca2 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/EventStore.java @@ -0,0 +1,124 @@ +/** + * 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.test.messaging.store; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.avro.BulkMessageItemV1; +import org.apache.fineract.avro.BulkMessagePayloadV1; +import org.apache.fineract.avro.MessageV1; +import org.apache.fineract.test.messaging.EventMessage; +import org.apache.fineract.test.messaging.event.Event; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Slf4j +public class EventStore { + + public static final String BULK_BUSINESS_EVENT_TYPE = "BulkBusinessEvent"; + private final List> receivedEvents = new CopyOnWriteArrayList<>(); + + public > boolean existsEventById(T type, Long id) { + return findEventById(type, id).isPresent(); + } + + public > Optional> removeEventById(T type, Long id) { + Optional> event = findEventById(type, id); + event.ifPresent(receivedEvents::remove); + return event; + } + + public > Optional> findEventById(T type, Long id) { + List> events = findByType(type); + return events.stream().filter(em -> type.getIdExtractor().apply(em.getData()).equals(id)).findFirst(); + } + + public > List> findByType(T type) { + return receivedEvents.stream().filter(em -> em.getType().equals(type.getEventName())).map(em -> (EventMessage) em) + .collect(Collectors.toList()); + } + + public List> getReceivedEvents() { + return receivedEvents; + } + + void receive(byte[] message) throws Exception { + MessageV1 msgObject = MessageV1.fromByteBuffer(ByteBuffer.wrap(message)); + String type = msgObject.getType(); + LocalDate businessDate = LocalDate.parse(msgObject.getBusinessDate(), DateTimeFormatter.ISO_LOCAL_DATE); + Object dataObject = getDataObject(msgObject); + if (BULK_BUSINESS_EVENT_TYPE.equals(type)) { + BulkMessagePayloadV1 bulkPayload = (BulkMessagePayloadV1) dataObject; + List> bulkEvents = bulkPayload.getDatas().stream() + .map((BulkMessageItemV1 item) -> getEventMessageFromBulkItem(item, businessDate)).toList(); + if (log.isDebugEnabled()) { + bulkEvents.forEach(msg -> { + log.debug("Received event {}", new LoggedEvent(msg)); + }); + } + receivedEvents.addAll(bulkEvents); + } else { + EventMessage msg = new EventMessage<>(type, businessDate, dataObject); + if (log.isDebugEnabled()) { + log.debug("Received event {}", new LoggedEvent(msg)); + } + receivedEvents.add(msg); + } + log.trace("Data object within event {}", dataObject); + } + + private EventMessage getEventMessageFromBulkItem(BulkMessageItemV1 item, LocalDate businessDate) { + try { + String dataschema = item.getDataschema(); + ByteBuffer data = item.getData(); + Object deserialized = deserialize(dataschema, data); + return new EventMessage<>(item.getType(), businessDate, deserialized); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Object getDataObject(MessageV1 msgObject) + throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + String dataschema = msgObject.getDataschema(); + ByteBuffer data = msgObject.getData(); + return deserialize(dataschema, data); + } + + private Object deserialize(String dataschema, ByteBuffer data) + throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Class eventClass = Class.forName(dataschema); + Method fromByteBuffer = eventClass.getMethod("fromByteBuffer", ByteBuffer.class); + return fromByteBuffer.invoke(null, data); + } + + public void reset() { + receivedEvents.clear(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/LoggedEvent.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/LoggedEvent.java new file mode 100644 index 00000000000..869ccf44b10 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/LoggedEvent.java @@ -0,0 +1,39 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.test.messaging.store; + +import java.time.format.DateTimeFormatter; +import org.apache.fineract.test.messaging.EventMessage; + +public class LoggedEvent { + + private final String type; + private final String businessDate; + + public LoggedEvent(EventMessage message) { + this.type = message.getType(); + this.businessDate = DateTimeFormatter.ISO_LOCAL_DATE.format(message.getBusinessDate()); + } + + // Don't use Lombok @ToString since the class name isn't included in the msg + @Override + public String toString() { + return "{" + "type='" + type + '\'' + ", businessDate='" + businessDate + '\'' + '}'; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/MessageConsumer.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/MessageConsumer.java new file mode 100644 index 00000000000..9f6206a9bfb --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/store/MessageConsumer.java @@ -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.test.messaging.store; + +import lombok.RequiredArgsConstructor; +import org.apache.activemq.command.ActiveMQBytesMessage; +import org.springframework.jms.annotation.JmsListener; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class MessageConsumer { + + private final EventStore eventStore; + + @JmsListener(destination = "${fineract-test.messaging.jms.topic-name}") + public void receiveMessage(ActiveMQBytesMessage message) { + try { + byte[] buffer = new byte[(int) message.getBodyLength()]; + message.readBytes(buffer); + eventStore.receive(buffer); + } catch (Exception e) { + throw new RuntimeException("Error while consuming message", e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java new file mode 100644 index 00000000000..92d5dd3d940 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java @@ -0,0 +1,1023 @@ +/** + * 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.test.stepdef.common; + +import static org.apache.fineract.test.stepdef.datatable.DatatablesStepDef.DATATABLE_NAME; +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import io.cucumber.datatable.DataTable; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Clock; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; +import org.apache.fineract.avro.loan.v1.LoanSchedulePeriodDataV1; +import org.apache.fineract.client.models.BatchRequest; +import org.apache.fineract.client.models.BatchResponse; +import org.apache.fineract.client.models.GetClientsClientIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdStatus; +import org.apache.fineract.client.models.GetLoansLoanIdTransactions; +import org.apache.fineract.client.models.GetUsersUserIdResponse; +import org.apache.fineract.client.models.Header; +import org.apache.fineract.client.models.PostClientsRequest; +import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest; +import org.apache.fineract.client.models.PostLoansLoanIdChargesRequest; +import org.apache.fineract.client.models.PostLoansLoanIdRequest; +import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; +import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; +import org.apache.fineract.client.models.PostLoansRequest; +import org.apache.fineract.client.models.PostLoansResponse; +import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest; +import org.apache.fineract.client.models.PostUsersResponse; +import org.apache.fineract.client.services.BatchApiApi; +import org.apache.fineract.client.services.ClientApi; +import org.apache.fineract.client.services.LoansApi; +import org.apache.fineract.client.services.UsersApi; +import org.apache.fineract.client.util.JSON; +import org.apache.fineract.test.api.ApiProperties; +import org.apache.fineract.test.data.ChargeProductType; +import org.apache.fineract.test.data.LoanRescheduleErrorMessage; +import org.apache.fineract.test.data.LoanStatus; +import org.apache.fineract.test.data.TransactionType; +import org.apache.fineract.test.factory.ClientRequestFactory; +import org.apache.fineract.test.factory.LoanRequestFactory; +import org.apache.fineract.test.helper.ErrorHelper; +import org.apache.fineract.test.helper.ErrorMessageHelper; +import org.apache.fineract.test.helper.ErrorResponse; +import org.apache.fineract.test.messaging.EventAssertion; +import org.apache.fineract.test.messaging.event.loan.LoanRescheduledDueAdjustScheduleEvent; +import org.apache.fineract.test.stepdef.AbstractStepDef; +import org.apache.fineract.test.support.TestContextKey; +import org.springframework.beans.factory.annotation.Autowired; +import retrofit2.Response; + +@Slf4j +public class BatchApiStepDef extends AbstractStepDef { + + private static final Gson GSON = new JSON().getGson(); + private static final String DATE_FORMAT = "dd MMMM yyyy"; + private static final String DEFAULT_LOCALE = "en"; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_1 = 1L; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_2 = 2L; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_3 = 3L; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_4 = 4L; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_5 = 5L; + private static final Long BATCH_API_SAMPLE_REQUEST_ID_6 = 6L; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_CLIENTS = "clients"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOANS = "loans"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOAN_RESCHEDULE = "rescheduleloans"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOAN_RESCHEDULE_APPROVE = "rescheduleloans/$.resourceId?command=approve"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOANS_CHARGES = "loans/$.loanId/charges"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOANS_APPROVE = "loans/$.loanId?command=approve"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOANS_DISBURSE = "loans/$.loanId?command=disburse"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_LOANS_REPAYMENT = "loans/$.loanId/transactions?command=repayment"; + private static final String BATCH_API_RELATIVE_URL_LOANS_APPLY_EXTERNAL_ID = "loans/external-id/$.resourceExternalId?command=approve"; + private static final String BATCH_API_RELATIVE_URL_GET_LOAN_DETAILS_EXTERNAL_ID = "loans/external-id/$.resourceExternalId"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES_QUERY = "/query?columnFilter=loan_id&valueFilter=0&resultColumns=loan_id"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES_UPDATE = "/$.[0].loan_id"; + private static final String BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES = "datatables/"; + private static final String BATCH_API_METHOD_POST = "POST"; + private static final String BATCH_API_METHOD_GET = "GET"; + private static final String BATCH_API_METHOD_PUT = "PUT"; + private static final Header HEADER = new Header().name("Content-type").value("text/html"); + private static final Header HEADER_JSON = new Header().name("Content-type").value("application/json"); + private static final String BODY_GET_REQUEST = "{}"; + private static final Long CHARGE_ID_NFS_FEE = ChargeProductType.LOAN_NSF_FEE.value; + private static final String ERROR_DEVELOPER_MESSAGE = "The requested resource is not available."; + private static final Integer ERROR_HTTP_404 = 404; + private static final String ERROR_DEVELOPER_MESSAGE_CLIENT = "Client with identifier null does not exist"; + private static final String ERROR_DEVELOPER_MESSAGE_LOAN_EXTERNAL = "Loan with external identifier {externalId} does not exist"; + + @Autowired + private BatchApiApi batchApiApi; + + @Autowired + private LoansApi loansApi; + + @Autowired + private ClientApi clientApi; + + @Autowired + private ClientRequestFactory clientRequestFactory; + + @Autowired + private EventAssertion eventAssertion; + + @Autowired + private LoanRequestFactory loanRequestFactory; + + @Autowired + private UsersApi usersApi; + + @Autowired + private ApiProperties apiProperties; + + @When("Batch API sample call ran") + public void runSampleBatchApiCall() throws IOException { + List requestList = new ArrayList<>(); + Set
headers = new HashSet<>(); + headers.add(HEADER); + + // request 1 - create client + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest(); + String bodyClientsRequest = GSON.toJson(clientsRequest); + + BatchRequest batchRequest1 = new BatchRequest(); + batchRequest1.requestId(BATCH_API_SAMPLE_REQUEST_ID_1); + batchRequest1.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_CLIENTS); + batchRequest1.method(BATCH_API_METHOD_POST); + batchRequest1.headers(headers); + batchRequest1.body(bodyClientsRequest); + + // request 2 - create Loan + PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(1L); + String bodyLoansRequest = GSON.toJson(loansRequest); + String bodyLoansRequestMod = bodyLoansRequest.replace("\"clientId\":1", "\"clientId\":\"$.clientId\""); + + BatchRequest batchRequest2 = new BatchRequest(); + batchRequest2.requestId(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest2.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS); + batchRequest2.method(BATCH_API_METHOD_POST); + batchRequest2.headers(headers); + batchRequest2.reference(BATCH_API_SAMPLE_REQUEST_ID_1); + batchRequest2.body(bodyLoansRequestMod); + + // request 3 - charge Loan + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); + String dateOfCharge = formatter.format(LocalDate.now(Clock.systemUTC()).minusMonths(1L).plusDays(1L)); + + PostLoansLoanIdChargesRequest loanIdChargesRequest = new PostLoansLoanIdChargesRequest(); + loanIdChargesRequest.chargeId(CHARGE_ID_NFS_FEE); + loanIdChargesRequest.amount(25D); + loanIdChargesRequest.dueDate(dateOfCharge); + loanIdChargesRequest.dateFormat(DATE_FORMAT); + loanIdChargesRequest.locale(DEFAULT_LOCALE); + String bodyLoanIdChargesRequest = GSON.toJson(loanIdChargesRequest); + + BatchRequest batchRequest3 = new BatchRequest(); + batchRequest3.requestId(BATCH_API_SAMPLE_REQUEST_ID_3); + batchRequest3.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_CHARGES); + batchRequest3.method(BATCH_API_METHOD_POST); + batchRequest3.headers(headers); + batchRequest3.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest3.body(bodyLoanIdChargesRequest); + + // request 4 - get charge data + BatchRequest batchRequest4 = new BatchRequest(); + batchRequest4.requestId(BATCH_API_SAMPLE_REQUEST_ID_4); + batchRequest4.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_CHARGES); + batchRequest4.method(BATCH_API_METHOD_GET); + batchRequest4.headers(headers); + batchRequest4.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest4.body(BODY_GET_REQUEST); + + // build Batch Api request + requestList.add(batchRequest1); + requestList.add(batchRequest2); + requestList.add(batchRequest3); + requestList.add(batchRequest4); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, false).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + } + + @When("Batch API call runs with idempotency key") + public void runBatchAPIWithIdempotencyKey() throws IOException { + List requestList = new ArrayList<>(); + Set
headers = new HashSet<>(); + headers.add(HEADER); + + // request 1 - create client + PostClientsRequest clientsRequest = clientRequestFactory.defaultClientCreationRequest(); + String bodyClientsRequest = GSON.toJson(clientsRequest); + + BatchRequest batchRequest1 = new BatchRequest(); + batchRequest1.requestId(BATCH_API_SAMPLE_REQUEST_ID_1); + batchRequest1.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_CLIENTS); + batchRequest1.method(BATCH_API_METHOD_POST); + batchRequest1.headers(headers); + batchRequest1.body(bodyClientsRequest); + + // request 2 - create Loan + PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(1L); + String bodyLoansRequest = GSON.toJson(loansRequest); + String bodyLoansRequestMod = bodyLoansRequest.replace("\"clientId\":1", "\"clientId\":\"$.clientId\""); + + BatchRequest batchRequest2 = new BatchRequest(); + batchRequest2.requestId(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest2.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS); + batchRequest2.method(BATCH_API_METHOD_POST); + batchRequest2.headers(headers); + batchRequest2.reference(BATCH_API_SAMPLE_REQUEST_ID_1); + batchRequest2.body(bodyLoansRequestMod); + + // request 3 - approve Loan + PostLoansLoanIdRequest loanApproveRequest = LoanRequestFactory.defaultLoanApproveRequest(); + String bodyLoanApproveRequest = GSON.toJson(loanApproveRequest); + + BatchRequest batchRequest3 = new BatchRequest(); + batchRequest3.requestId(BATCH_API_SAMPLE_REQUEST_ID_3); + batchRequest3.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_APPROVE); + batchRequest3.method(BATCH_API_METHOD_POST); + batchRequest3.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest3.headers(headers); + batchRequest3.body(bodyLoanApproveRequest); + + // request 4 - disburse Loan + PostLoansLoanIdRequest loanDisburseRequest = LoanRequestFactory.defaultLoanDisburseRequest(); + String bodyLoanDisburseRequest = GSON.toJson(loanDisburseRequest); + + BatchRequest batchRequest4 = new BatchRequest(); + batchRequest4.requestId(BATCH_API_SAMPLE_REQUEST_ID_4); + batchRequest4.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_DISBURSE); + batchRequest4.method(BATCH_API_METHOD_POST); + batchRequest4.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest4.headers(headers); + batchRequest4.body(bodyLoanDisburseRequest); + + // request 5 - repayment with idempotency key + PostLoansLoanIdTransactionsRequest loanRepaymentRequest1 = LoanRequestFactory.defaultRepaymentRequest(); + String bodyLoanRepaymentRequest1 = GSON.toJson(loanRepaymentRequest1); + + String idempotencyKey = UUID.randomUUID().toString(); + headers.add(new Header().name("Idempotency-Key").value(idempotencyKey)); + + BatchRequest batchRequest5 = new BatchRequest(); + batchRequest5.requestId(BATCH_API_SAMPLE_REQUEST_ID_5); + batchRequest5.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_REPAYMENT); + batchRequest5.method(BATCH_API_METHOD_POST); + batchRequest5.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest5.headers(headers); + batchRequest5.body(bodyLoanRepaymentRequest1); + + // request 6 - repayment with same idempotency key + PostLoansLoanIdTransactionsRequest loanRepaymentRequest2 = LoanRequestFactory.defaultRepaymentRequest(); + String bodyLoanRepaymentRequest2 = GSON.toJson(loanRepaymentRequest2); + + BatchRequest batchRequest6 = new BatchRequest(); + batchRequest6.requestId(BATCH_API_SAMPLE_REQUEST_ID_6); + batchRequest6.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS_REPAYMENT); + batchRequest6.method(BATCH_API_METHOD_POST); + batchRequest6.reference(BATCH_API_SAMPLE_REQUEST_ID_2); + batchRequest6.headers(headers); + batchRequest6.body(bodyLoanRepaymentRequest2); + + // build Batch Api request + requestList.add(batchRequest1); + requestList.add(batchRequest2); + requestList.add(batchRequest3); + requestList.add(batchRequest4); + requestList.add(batchRequest5); + requestList.add(batchRequest6); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, false).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + } + + @When("Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: {string}") + public void runBatchApiClientLoanApproveLoanDetails(String enclosingTransaction) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + String clientExternalId = UUID.randomUUID().toString(); + String loanExternalId = UUID.randomUUID().toString(); + + List requestList = new ArrayList<>(); + + requestList.add(createClient(1L, idempotencyKey, clientExternalId)); + requestList.add(createLoan(2L, 1L, idempotencyKey, loanExternalId)); + requestList.add(approveLoanByExternalId(3L, 2L, idempotencyKey)); + requestList.add(getLoanDetailsByExternalId(4L, 2L, idempotencyKey)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID, clientExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID, loanExternalId); + } + + @When("Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: {string}, with failed approve step") + public void runBatchApiClientLoanApproveLoanDetailsApproveFails(String enclosingTransaction) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + String clientExternalId = UUID.randomUUID().toString(); + String loanExternalId = UUID.randomUUID().toString(); + + List requestList = new ArrayList<>(); + + requestList.add(createClient(1L, idempotencyKey, clientExternalId)); + requestList.add(createLoan(2L, 1L, idempotencyKey, loanExternalId)); + requestList.add(approveLoanByExternalIdFail(3L, 2L, idempotencyKey, "approve-fail")); + requestList.add(getLoanDetailsByExternalId(4L, 2L, idempotencyKey)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID, clientExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID, loanExternalId); + } + + @When("Batch API call with steps done twice: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: {string}") + public void runBatchApiTwiceClientLoanApproveLoanDetails(String enclosingTransaction) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + String clientExternalId = UUID.randomUUID().toString(); + String loanExternalId = UUID.randomUUID().toString(); + String idempotencyKey2 = UUID.randomUUID().toString(); + String clientExternalId2 = UUID.randomUUID().toString(); + String loanExternalId2 = UUID.randomUUID().toString(); + + List requestList = new ArrayList<>(); + + requestList.add(createClient(1L, idempotencyKey, clientExternalId)); + requestList.add(createLoan(2L, 1L, idempotencyKey, loanExternalId)); + requestList.add(approveLoanByExternalId(3L, 2L, idempotencyKey)); + requestList.add(getLoanDetailsByExternalId(4L, 2L, idempotencyKey)); + requestList.add(createClient(5L, idempotencyKey2, clientExternalId2)); + requestList.add(createLoan(6L, 5L, idempotencyKey2, loanExternalId2)); + requestList.add(approveLoanByExternalId(7L, 6L, idempotencyKey2)); + requestList.add(getLoanDetailsByExternalId(8L, 6L, idempotencyKey2)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID, clientExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID, loanExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY_2, idempotencyKey2); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID_2, clientExternalId2); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID_2, loanExternalId2); + } + + @When("Batch API call with steps done twice: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: {string}, with failed approve step in second tree") + public void runBatchApiTwiceClientLoanApproveLoanDetailsSecondApproveFails(String enclosingTransaction) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + String clientExternalId = UUID.randomUUID().toString(); + String loanExternalId = UUID.randomUUID().toString(); + String idempotencyKey2 = UUID.randomUUID().toString(); + String clientExternalId2 = UUID.randomUUID().toString(); + String loanExternalId2 = UUID.randomUUID().toString(); + + List requestList = new ArrayList<>(); + + requestList.add(createClient(1L, idempotencyKey, clientExternalId)); + requestList.add(createLoan(2L, 1L, idempotencyKey, loanExternalId)); + requestList.add(approveLoanByExternalId(3L, 2L, idempotencyKey)); + requestList.add(getLoanDetailsByExternalId(4L, 2L, idempotencyKey)); + requestList.add(createClient(5L, idempotencyKey2, clientExternalId2)); + requestList.add(createLoan(6L, 5L, idempotencyKey2, loanExternalId2)); + requestList.add(approveLoanByExternalIdFail(7L, 6L, idempotencyKey2, "approve-fail")); + requestList.add(getLoanDetailsByExternalId(8L, 6L, idempotencyKey2)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID, clientExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID, loanExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY_2, idempotencyKey2); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID_2, clientExternalId2); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID_2, loanExternalId2); + } + + @When("Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: {string}, and approveLoan is doubled") + public void runBatchApiClientLoanApproveLoanDetailsApproveDoubled(String enclosingTransaction) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + String clientExternalId = UUID.randomUUID().toString(); + String loanExternalId = UUID.randomUUID().toString(); + + List requestList = new ArrayList<>(); + + requestList.add(createClient(1L, idempotencyKey, clientExternalId)); + requestList.add(createLoan(2L, 1L, idempotencyKey, loanExternalId)); + requestList.add(approveLoanByExternalId(3L, 2L, idempotencyKey)); + requestList.add(approveLoanByExternalId(4L, 2L, idempotencyKey)); + requestList.add(getLoanDetailsByExternalId(5L, 2L, idempotencyKey)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + testContext().set(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID, clientExternalId); + testContext().set(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID, loanExternalId); + } + + @When("Batch API call with steps: rescheduleLoan from {string} to {string} submitted on date: {string}, approveReschedule on date: {string} runs with enclosingTransaction: {string}") + public void runBatchApiCreateAndApproveLoanReschedule(String fromDateStr, String toDateStr, String submittedOnDate, + String approvedOnDate, String enclosingTransaction) throws IOException { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); + String idempotencyKey = UUID.randomUUID().toString(); + Response loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Long loanId = loanResponse.body().getLoanId(); + + List requestList = new ArrayList<>(); + + requestList.add(createLoanReschedule(1L, loanId, fromDateStr, toDateStr, submittedOnDate, idempotencyKey, null)); + requestList.add(approveLoanReschedule(2L, idempotencyKey, approvedOnDate, 1L)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + eventAssertion.assertEvent(LoanRescheduledDueAdjustScheduleEvent.class, loanId).extractingData(loanAccountDataV1 -> { + Optional period = loanAccountDataV1.getRepaymentSchedule().getPeriods().stream() + .filter(p -> formatter.format(LocalDate.parse(p.getDueDate())).equals(toDateStr)).findFirst(); + String dueDate = ""; + if (period.isPresent()) { + dueDate = formatter.format(LocalDate.parse(period.get().getDueDate())); + } + assertThat(dueDate).as(ErrorMessageHelper.wrongDataInLastPaymentAmount(dueDate, toDateStr)).isEqualTo(toDateStr); + return null; + }); + } + + @When("Batch API call with created user and with steps: rescheduleLoan from {string} to {string} submitted on date: {string}, approveReschedule on date: {string} runs with enclosingTransaction: {string}") + public void runBatchApiCreateAndApproveLoanRescheduleWithGivenUser(String fromDateStr, String toDateStr, String submittedOnDate, + String approvedOnDate, String enclosingTransaction) throws IOException { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT); + String idempotencyKey = UUID.randomUUID().toString(); + Response loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Long loanId = loanResponse.body().getLoanId(); + + Map headerMap = new HashMap<>(); + + Response createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE); + Long createdUserId = createUserResponse.body().getResourceId(); + Response user = usersApi.retrieveOne31(createdUserId).execute(); + ErrorHelper.checkSuccessfulApiCall(user); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + Base64 base64 = new Base64(); + headerMap.put("Authorization", + "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); + + List requestList = new ArrayList<>(); + + requestList.add(createLoanReschedule(1L, loanId, fromDateStr, toDateStr, submittedOnDate, idempotencyKey, null)); + requestList.add(approveLoanReschedule(2L, idempotencyKey, approvedOnDate, 1L)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction, headerMap) + .execute(); + + if (batchResponseList.errorBody() != null) { + log.info("ERROR: {}", batchResponseList.errorBody().string()); + + } + if (batchResponseList.body() != null) { + log.info("Body: {}", batchResponseList.body()); + } + + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + eventAssertion.assertEvent(LoanRescheduledDueAdjustScheduleEvent.class, loanId).extractingData(loanAccountDataV1 -> { + Optional period = loanAccountDataV1.getRepaymentSchedule().getPeriods().stream() + .filter(p -> formatter.format(LocalDate.parse(p.getDueDate())).equals(toDateStr)).findFirst(); + String dueDate = ""; + if (period.isPresent()) { + dueDate = formatter.format(LocalDate.parse(period.get().getDueDate())); + } + assertThat(dueDate).as(ErrorMessageHelper.wrongDataInLastPaymentAmount(dueDate, toDateStr)).isEqualTo(toDateStr); + return null; + }); + } + + @When("Batch API call with created user and the following data results a {int} error and a {string} error message:") + public void runBatchApiCreateAndApproveLoanRescheduleWithGivenUserLockedByCobError(int errorCodeExpected, String errorMessageType, + DataTable table) throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + Response loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE); + Long loanId = loanResponse.body().getLoanId(); + + LoanRescheduleErrorMessage loanRescheduleErrorMessage = LoanRescheduleErrorMessage.valueOf(errorMessageType); + String errorMessageExpected = loanRescheduleErrorMessage.getValue(loanId); + + List> data = table.asLists(); + List transferData = data.get(1); + String fromDateStr = transferData.get(0); + String submittedOnDate = transferData.get(1); + String toDateStr = transferData.get(2); + String approvedOnDate = transferData.get(3); + String enclosingTransaction = transferData.get(4); + + Map headerMap = new HashMap<>(); + + Response createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE); + Long createdUserId = createUserResponse.body().getResourceId(); + Response user = usersApi.retrieveOne31(createdUserId).execute(); + ErrorHelper.checkSuccessfulApiCall(user); + String authorizationString = user.body().getUsername() + ":" + apiProperties.getPassword(); + Base64 base64 = new Base64(); + headerMap.put("Authorization", + "Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)); + + List requestList = new ArrayList<>(); + requestList.add(createLoanReschedule(1L, loanId, fromDateStr, toDateStr, submittedOnDate, idempotencyKey, null)); + requestList.add(approveLoanReschedule(2L, idempotencyKey, approvedOnDate, 1L)); + + Boolean isEnclosingTransaction = Boolean.valueOf(enclosingTransaction); + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, isEnclosingTransaction, headerMap) + .execute(); + String errorToString = batchResponseList.errorBody().string(); + ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class); + String errorMessageActual = errorResponse.getDeveloperMessage(); + Integer errorCodeActual = errorResponse.getHttpStatusCode(); + + assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected); + assertThat(errorMessageActual).as(ErrorMessageHelper.wrongErrorMessage(errorMessageActual, errorMessageExpected)) + .isEqualTo(errorMessageExpected); + + log.info("ERROR CODE: {}", errorCodeActual); + log.info("ERROR MESSAGE: {}", errorMessageActual); + } + + @When("Batch API call with steps: queryDatatable, updateDatatable runs, with empty queryDatatable response") + public void runBatchApiQueryDatatableUpdateDatatable() throws IOException { + String idempotencyKey = UUID.randomUUID().toString(); + List requestList = new ArrayList<>(); + + requestList.add(queryDatatable(1L)); + requestList.add(updateDatatable(2L, 1L)); + + Response> batchResponseList = batchApiApi.handleBatchRequests(requestList, false).execute(); + testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList); + testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey); + } + + private BatchRequest createLoanReschedule(Long requestId, Long loanId, String fromDateStr, String toDateStr, String submittedOnDate, + String idempotencyKey, Long referenceId) { + PostCreateRescheduleLoansRequest rescheduleLoansRequest = LoanRequestFactory.defaultLoanRescheduleCreateRequest(loanId, fromDateStr, + toDateStr); + rescheduleLoansRequest.setSubmittedOnDate(submittedOnDate); + String bodyLoanRescheduleRequest = GSON.toJson(rescheduleLoansRequest); + + Set
headers = new HashSet<>(); + headers.add(HEADER); + if (idempotencyKey != null) { + headers.add(new Header().name("Idempotency-Key").value(idempotencyKey)); + } + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOAN_RESCHEDULE); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.headers(headers); + batchRequest.reference(referenceId); + batchRequest.body(bodyLoanRescheduleRequest); + + return batchRequest; + } + + private BatchRequest approveLoanReschedule(Long requestId, String idempotencyKey, String approvedOnDate, Long referenceId) { + PostUpdateRescheduleLoansRequest rescheduleLoansRequest = LoanRequestFactory.defaultLoanRescheduleUpdateRequest(); + rescheduleLoansRequest.setApprovedOnDate(approvedOnDate); + String bodyLoanRescheduleRequest = GSON.toJson(rescheduleLoansRequest); + + Set
headers = new HashSet<>(); + headers.add(HEADER); + if (idempotencyKey != null) { + headers.add(new Header().name("Idempotency-Key").value(idempotencyKey)); + } + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOAN_RESCHEDULE_APPROVE); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.headers(headers); + batchRequest.reference(referenceId); + batchRequest.body(bodyLoanRescheduleRequest); + + return batchRequest; + } + + @Then("Admin checks that all steps result 200OK") + public void adminChecksThatAllStepsResultOK() { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + ErrorHelper.checkSuccessfulBatchApiCall(batchResponseList); + } + + @Then("Verify that step Nr. {int} results {int}") + public void checkGivenStepResult(int nr, int resultStatusCode) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse stepResponse = batchResponseList.body().stream().filter(r -> r.getRequestId() == nr).findAny() + .orElseThrow(() -> new IllegalStateException(String.format("Request id %s not found", nr))); + + assertThat(stepResponse.getStatusCode()).as(ErrorMessageHelper.wrongStatusCode(stepResponse.getStatusCode(), resultStatusCode)) + .isEqualTo(resultStatusCode); + } + + @Then("Verify that step {int} throws an error with error code {int}") + public void errorCodeInStep(int step, int errorCode) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse response = batchResponseList.body().stream().filter(r -> r.getRequestId() == step).findAny() + .orElseThrow(() -> new IllegalStateException(String.format("Step %s is not found", step))); + ErrorResponse errorResponse = GSON.fromJson(response.getBody(), ErrorResponse.class); + + String developerMessageActual = errorResponse.getDeveloperMessage(); + Integer httpStatusCodeActual = errorResponse.getHttpStatusCode(); + + String developerMessageExpected = ERROR_DEVELOPER_MESSAGE; + Integer httpStatusCodeExpected = ERROR_HTTP_404; + + assertThat(response.getStatusCode()).as(ErrorMessageHelper.wrongStatusCode(response.getStatusCode(), errorCode)) + .isEqualTo(errorCode); + assertThat(developerMessageActual).as(ErrorMessageHelper.wrongErrorMessage(developerMessageActual, developerMessageExpected)) + .isEqualTo(developerMessageExpected); + assertThat(httpStatusCodeActual).as(ErrorMessageHelper.wrongStatusCode(httpStatusCodeActual, httpStatusCodeExpected)) + .isEqualTo(httpStatusCodeExpected); + } + + @Then("Admin checks that all steps result 200OK for Batch API idempotency request") + public void adminChecksThatAllStepsResultOKIdempotency() { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + ErrorHelper.checkSuccessfulBatchApiCall(batchResponseList); + } + + @Then("Batch API response has boolean value in header {string}: {string} in segment with requestId {int}") + public void batchAPITransactionHeaderCheckBoolean(String headerKeyExpected, String headerValueExpected, int requestId) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse batchResponse = batchResponseList.body().get(requestId - 1); + + Set
headers = batchResponse.getHeaders(); + List
headersList = new ArrayList<>(Objects.requireNonNull(headers)); + String headerValueActual = getHeaderValueByHeaderKey(headersList, headerKeyExpected); + + assertThat(headerValueActual) + .as(ErrorMessageHelper.wrongValueInResponseHeader(headerKeyExpected, headerValueActual, headerValueExpected)) + .isEqualTo(headerValueExpected); + } + + @Then("Batch API response has no {string} field in segment with requestId {int}") + public void batchAPITransactionHeaderCheckNoField(String headerKeyExpected, int requestId) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse batchResponse = batchResponseList.body().get(requestId - 1); + + Set
headers = batchResponse.getHeaders(); + List
headersList = new ArrayList<>(Objects.requireNonNull(headers)); + boolean hasHeaderKey = false; + for (Header header : headersList) { + if (headerKeyExpected.equals(header.getName())) { + hasHeaderKey = true; + } + } + + assertThat(hasHeaderKey).isFalse(); + } + + @Then("Batch API response has {double} EUR value for transaction amount in segment with requestId {int}") + public void batchAPITransactionAmountCheck(double transactionAmountExpected, int requestId) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse batchResponse = batchResponseList.body().get(requestId - 1); + + PostLoansLoanIdTransactionsResponse loanTransactionResponse = GSON.fromJson(batchResponse.getBody(), + PostLoansLoanIdTransactionsResponse.class); + Double transactionAmountActual = Double + .valueOf(Objects.requireNonNull(Objects.requireNonNull(loanTransactionResponse.getChanges()).getTransactionAmount())); + + assertThat(transactionAmountActual) + .as(ErrorMessageHelper.wrongAmountInTransactionsAmount(transactionAmountActual, transactionAmountExpected)) + .isEqualTo(transactionAmountExpected); + } + + @Then("Batch API response has the same clientId and loanId in segment with requestId {int} as in segment with requestId {int}") + public void batchAPIClientIdLoanIdCheck(int requestIdSecondTransaction, int requestIdFirstTransaction) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse batchResponseFirstTransaction = batchResponseList.body().get(requestIdFirstTransaction - 1); + BatchResponse batchResponseSecondTransaction = batchResponseList.body().get(requestIdSecondTransaction - 1); + + PostLoansLoanIdTransactionsResponse loanTransactionResponseFirst = GSON.fromJson(batchResponseFirstTransaction.getBody(), + PostLoansLoanIdTransactionsResponse.class); + PostLoansLoanIdTransactionsResponse loanTransactionResponseSecond = GSON.fromJson(batchResponseSecondTransaction.getBody(), + PostLoansLoanIdTransactionsResponse.class); + + Long clientIdFirstTransaction = loanTransactionResponseFirst.getClientId(); + Long clientIdSecondTransaction = loanTransactionResponseSecond.getClientId(); + + Long loanIdFirstTransaction = loanTransactionResponseFirst.getLoanId(); + Long loanIdSecondTransaction = loanTransactionResponseSecond.getLoanId(); + + assertThat(clientIdSecondTransaction) + .as(ErrorMessageHelper.wrongClientIdInTransactionResponse(clientIdSecondTransaction, clientIdFirstTransaction)) + .isEqualTo(clientIdFirstTransaction); + assertThat(loanIdSecondTransaction) + .as(ErrorMessageHelper.wrongLoanIdInTransactionResponse(loanIdSecondTransaction, loanIdFirstTransaction)) + .isEqualTo(loanIdFirstTransaction); + } + + @Then("Batch API response has the same idempotency key in segment with requestId {int} as in segment with requestId {int}") + public void batchAPIIdempotencyKeyCheck(int requestIdSecondTransaction, int requestIdFirstTransaction) { + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse batchResponseFirstTransaction = batchResponseList.body().get(requestIdFirstTransaction - 1); + BatchResponse batchResponseSecondTransaction = batchResponseList.body().get(requestIdSecondTransaction - 1); + + Set
headersFirstTransaction = batchResponseFirstTransaction.getHeaders(); + List
headersListFirstTransaction = new ArrayList<>(Objects.requireNonNull(headersFirstTransaction)); + Set
headersSecondTransaction = batchResponseSecondTransaction.getHeaders(); + List
headersListSecondTransaction = new ArrayList<>(Objects.requireNonNull(headersSecondTransaction)); + + String idempotencyKey = "Idempotency-Key"; + String idempotencyValueFirstTransaction = getHeaderValueByHeaderKey(headersListFirstTransaction, idempotencyKey); + String idempotencyValueSecondTransaction = getHeaderValueByHeaderKey(headersListSecondTransaction, idempotencyKey); + + assertThat(idempotencyValueSecondTransaction) + .as(ErrorMessageHelper.idempotencyKeyNoMatch(idempotencyValueSecondTransaction, idempotencyValueFirstTransaction)) + .isEqualTo(idempotencyValueFirstTransaction); + } + + @Then("Loan has {int} {string} transactions on Transactions tab after Batch API run") + public void checkNrOfTransactionsBatchApi(int nrOfTransactionsExpected, String transactionTypeInput) throws IOException { + TransactionType transactionType = TransactionType.valueOf(transactionTypeInput); + String transactionTypeValue = transactionType.getValue(); + + Response> batchResponseList = testContext().get(TestContextKey.BATCH_API_CALL_RESPONSE); + BatchResponse lastBatchResponse = batchResponseList.body().get(batchResponseList.body().size() - 1); + PostLoansLoanIdTransactionsResponse loanTransactionResponse = GSON.fromJson(lastBatchResponse.getBody(), + PostLoansLoanIdTransactionsResponse.class); + Long loanId = loanTransactionResponse.getLoanId(); + + Response loanDetails = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute(); + + List transactions = loanDetails.body().getTransactions(); + List transactionsMatched = new ArrayList<>(); + + transactions.forEach(t -> { + String transactionTypeValueActual = t.getType().getCode(); + String transactionTypeValueExpected = "loanTransactionType." + transactionTypeValue; + + if (transactionTypeValueActual.equals(transactionTypeValueExpected)) { + transactionsMatched.add(transactionTypeValueActual); + } + }); + + int nrOfTransactionsActual = transactionsMatched.size(); + assertThat(nrOfTransactionsActual) + .as(ErrorMessageHelper.wrongNrOfTransactions(transactionTypeInput, nrOfTransactionsActual, nrOfTransactionsExpected)) + .isEqualTo(nrOfTransactionsExpected); + } + + @Then("Nr. {int} Client was created") + public void givenClientCreated(int nr) throws IOException { + String clientExternalId = ""; + if (nr == 1) { + clientExternalId = testContext().get(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID); + } else if (nr == 2) { + clientExternalId = testContext().get(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID_2); + } else { + throw new IllegalStateException(String.format("Nr. %s client external ID not found", nr)); + } + + Response response = clientApi.retrieveOne12(clientExternalId, false).execute(); + ErrorHelper.checkSuccessfulApiCall(response); + assertThat(response.body().getId()).as(ErrorMessageHelper.idNull()).isNotNull(); + } + + @Then("Nr. {int} Loan was created") + public void givenLoanCreated(int nr) throws IOException { + String loanExternalId = ""; + if (nr == 1) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID); + } else if (nr == 2) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID_2); + } else { + throw new IllegalStateException(String.format("Nr. %s loan external ID not found", nr)); + } + + Response response = loansApi.retrieveLoan1(loanExternalId, false, "", "", "").execute(); + ErrorHelper.checkSuccessfulApiCall(response); + assertThat(response.body().getId()).as(ErrorMessageHelper.idNull()).isNotNull(); + } + + @Then("Nr. {int} Loan was approved") + public void givenLoanApproved(int nr) throws IOException { + String loanExternalId = ""; + if (nr == 1) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID); + } else if (nr == 2) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID_2); + } else { + throw new IllegalStateException(String.format("Nr. %s loan external ID not found", nr)); + } + + Response response = loansApi.retrieveLoan1(loanExternalId, false, "", "", "").execute(); + ErrorHelper.checkSuccessfulApiCall(response); + + GetLoansLoanIdStatus status = response.body().getStatus(); + Integer statusIdActual = status.getId(); + Integer statusIdExpected = LoanStatus.APPROVED.value; + + assertThat(statusIdActual).as(ErrorMessageHelper.wrongLoanStatus(statusIdActual, statusIdExpected)).isEqualTo(statusIdExpected); + } + + @Then("Nr. {int} Client creation was rolled back") + public void clientNotCreated(int nr) throws IOException { + String clientExternalId = ""; + if (nr == 1) { + clientExternalId = testContext().get(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID); + } else if (nr == 2) { + clientExternalId = testContext().get(TestContextKey.BATCH_API_CALL_CLIENT_EXTERNAL_ID_2); + } else { + throw new IllegalStateException(String.format("Nr. %s client external id mot found", nr)); + } + + Response response = clientApi.retrieveOne12(clientExternalId, false).execute(); + ErrorResponse errorResponse = GSON.fromJson(response.errorBody().string(), ErrorResponse.class); + String developerMessageActual = errorResponse.getDeveloperMessage(); + Integer httpStatusCodeActual = errorResponse.getHttpStatusCode(); + String errorsDeveloperMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage(); + + String developerMessageExpected = ERROR_DEVELOPER_MESSAGE; + Integer httpStatusCodeExpected = ERROR_HTTP_404; + String errorsDeveloperMessageExpected = ERROR_DEVELOPER_MESSAGE_CLIENT; + + assertThat(developerMessageActual).as(ErrorMessageHelper.wrongErrorMessage(developerMessageActual, developerMessageExpected)) + .isEqualTo(developerMessageExpected); + assertThat(httpStatusCodeActual).as(ErrorMessageHelper.wrongStatusCode(httpStatusCodeActual, httpStatusCodeExpected)) + .isEqualTo(httpStatusCodeExpected); + assertThat(errorsDeveloperMessageActual) + .as(ErrorMessageHelper.wrongErrorMessage(errorsDeveloperMessageActual, errorsDeveloperMessageExpected)) + .isEqualTo(errorsDeveloperMessageExpected); + } + + @Then("Nr. {int} Loan creation was rolled back") + public void loanNotCreated(int nr) throws IOException { + String loanExternalId = ""; + if (nr == 1) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID); + } else if (nr == 2) { + loanExternalId = testContext().get(TestContextKey.BATCH_API_CALL_LOAN_EXTERNAL_ID_2); + } else { + throw new IllegalStateException(String.format("Nr. %s loan external id mot found", nr)); + } + + Response response = loansApi.retrieveLoan1(loanExternalId, false, "", "", "").execute(); + + ErrorResponse errorResponse = GSON.fromJson(response.errorBody().string(), ErrorResponse.class); + String developerMessageActual = errorResponse.getDeveloperMessage(); + Integer httpStatusCodeActual = errorResponse.getHttpStatusCode(); + String errorsDeveloperMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage(); + + String developerMessageExpected = ERROR_DEVELOPER_MESSAGE; + Integer httpStatusCodeExpected = ERROR_HTTP_404; + String errorsDeveloperMessageExpected = ERROR_DEVELOPER_MESSAGE_LOAN_EXTERNAL.replace("{externalId}", loanExternalId); + + assertThat(developerMessageActual).as(ErrorMessageHelper.wrongErrorMessage(developerMessageActual, developerMessageExpected)) + .isEqualTo(developerMessageExpected); + assertThat(httpStatusCodeActual).as(ErrorMessageHelper.wrongStatusCode(httpStatusCodeActual, httpStatusCodeExpected)) + .isEqualTo(httpStatusCodeExpected); + assertThat(errorsDeveloperMessageActual) + .as(ErrorMessageHelper.wrongErrorMessage(errorsDeveloperMessageActual, errorsDeveloperMessageExpected)) + .isEqualTo(errorsDeveloperMessageExpected); + } + + private String getHeaderValueByHeaderKey(List
headersList, String headerKey) { + for (Header header : headersList) { + if (Objects.requireNonNull(header.getName()).equals(headerKey)) { + return header.getValue(); + } + } + throw new Error(ErrorMessageHelper.noHeaderKeyFound(headersList, headerKey)); + } + + private BatchRequest createClient(Long requestId, String idempotencyKey, String clientExternalId) { + PostClientsRequest clientsRequest = clientExternalId == null ? clientRequestFactory.defaultClientCreationRequest() + : clientRequestFactory.defaultClientCreationRequest().externalId(clientExternalId); + String bodyClientsRequest = GSON.toJson(clientsRequest); + + Set
headers = new HashSet<>(); + headers.add(HEADER); + if (idempotencyKey != null) { + headers.add(new Header().name("Idempotency-Key").value(idempotencyKey)); + } + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_CLIENTS); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.headers(headers); + batchRequest.body(bodyClientsRequest); + + return batchRequest; + } + + private BatchRequest createLoan(Long requestId, Long referenceId, String idempotencyKey, String loanExternalId) { + PostLoansRequest loansRequest = loanExternalId == null ? loanRequestFactory.defaultLoansRequest(1L) + : loanRequestFactory.defaultLoansRequest(1L).externalId(loanExternalId); + String bodyLoansRequest = GSON.toJson(loansRequest); + String bodyLoansRequestMod = bodyLoansRequest.replace("\"clientId\":1", "\"clientId\":\"$.clientId\""); + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_LOANS); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.headers(setHeaders(idempotencyKey)); + batchRequest.reference(referenceId); + batchRequest.body(bodyLoansRequestMod); + + return batchRequest; + } + + private BatchRequest queryDatatable(Long requestId) { + String datatableName = testContext().get(DATATABLE_NAME); + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES + datatableName + BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES_QUERY); + batchRequest.method(BATCH_API_METHOD_GET); + batchRequest.headers(Set.of(HEADER_JSON)); + batchRequest.body("{}"); + + return batchRequest; + } + + private BatchRequest updateDatatable(Long requestId, Long referenceId) { + String datatableName = testContext().get(DATATABLE_NAME); + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest + .relativeUrl(BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES + datatableName + BATCH_API_SAMPLE_RELATIVE_URL_DATATABLES_UPDATE); + batchRequest.method(BATCH_API_METHOD_PUT); + batchRequest.headers(Set.of(HEADER_JSON)); + batchRequest.reference(referenceId); + batchRequest.body("{\"loan_id\": \"345\"}"); + + return batchRequest; + } + + private BatchRequest approveLoanByExternalId(Long requestId, Long referenceId, String idempotencyKey) { + PostLoansLoanIdRequest loanApproveRequest = LoanRequestFactory.defaultLoanApproveRequest(); + String bodyLoanApproveRequest = GSON.toJson(loanApproveRequest); + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_RELATIVE_URL_LOANS_APPLY_EXTERNAL_ID); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.reference(referenceId); + batchRequest.headers(setHeaders(idempotencyKey)); + batchRequest.body(bodyLoanApproveRequest); + + return batchRequest; + } + + private BatchRequest approveLoanByExternalIdFail(Long requestId, Long referenceId, String idempotencyKey, String loanExternalId) { + PostLoansLoanIdRequest loanApproveRequest = LoanRequestFactory.defaultLoanApproveRequest(); + String bodyLoanApproveRequest = GSON.toJson(loanApproveRequest); + + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_RELATIVE_URL_LOANS_APPLY_EXTERNAL_ID.replace("$.resourceExternalId", loanExternalId)); + batchRequest.method(BATCH_API_METHOD_POST); + batchRequest.reference(referenceId); + batchRequest.headers(setHeaders(idempotencyKey)); + batchRequest.body(bodyLoanApproveRequest); + + return batchRequest; + } + + private BatchRequest getLoanDetailsByExternalId(Long requestId, Long referenceId, String idempotencyKey) { + BatchRequest batchRequest = new BatchRequest(); + batchRequest.requestId(requestId); + batchRequest.relativeUrl(BATCH_API_RELATIVE_URL_GET_LOAN_DETAILS_EXTERNAL_ID); + batchRequest.method(BATCH_API_METHOD_GET); + batchRequest.headers(setHeaders(idempotencyKey)); + batchRequest.reference(referenceId); + batchRequest.body(BODY_GET_REQUEST); + + return batchRequest; + } + + private Set
setHeaders(String idempotencyKey) { + Set
headers = new HashSet<>(); + headers.add(HEADER); + if (idempotencyKey != null) { + headers.add(new Header().name("Idempotency-Key").value(idempotencyKey)); + } + + return headers; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java new file mode 100644 index 00000000000..4631bf2b423 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java @@ -0,0 +1,47 @@ +/** + * 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.test.stepdef.common; + +import io.cucumber.java.en.Given; +import io.cucumber.java.en.When; +import java.io.IOException; +import org.apache.fineract.test.helper.GlobalConfigurationHelper; +import org.springframework.beans.factory.annotation.Autowired; + +public class GlobalConfigurationStepDef { + + @Autowired + private GlobalConfigurationHelper globalConfigurationHelper; + + @Given("Global configuration {string} is disabled") + public void disableGlobalConfiguration(String configKey) throws IOException { + globalConfigurationHelper.disableGlobalConfiguration(configKey, 0L); + } + + @Given("Global configuration {string} is enabled") + public void enableGlobalConfiguration(String configKey) throws IOException { + globalConfigurationHelper.enableGlobalConfiguration(configKey, 0L); + } + + @When("Global config {string} value set to {string}") + public void setGlobalConfigValueString(String configKey, String configValue) throws IOException { + globalConfigurationHelper.setGlobalConfigValueString(configKey, configValue); + + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/datatable/DatatablesStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/datatable/DatatablesStepDef.java new file mode 100644 index 00000000000..68409ffa214 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/datatable/DatatablesStepDef.java @@ -0,0 +1,197 @@ +/** + * 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.test.stepdef.datatable; + +import static java.util.function.Function.identity; +import static org.apache.fineract.test.helper.ErrorHelper.checkSuccessfulApiCall; +import static org.assertj.core.api.Assertions.assertThat; + +import io.cucumber.datatable.DataTable; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.fineract.client.models.GetDataTablesResponse; +import org.apache.fineract.client.models.PostColumnHeaderData; +import org.apache.fineract.client.models.PostDataTablesRequest; +import org.apache.fineract.client.models.PostDataTablesResponse; +import org.apache.fineract.client.models.ResultsetColumnHeaderData; +import org.apache.fineract.client.services.DataTablesApi; +import org.apache.fineract.test.data.datatable.DatatableColumnType; +import org.apache.fineract.test.data.datatable.DatatableEntityType; +import org.apache.fineract.test.data.datatable.DatatableNameGenerator; +import org.apache.fineract.test.stepdef.AbstractStepDef; +import org.springframework.beans.factory.annotation.Autowired; +import retrofit2.Response; + +public class DatatablesStepDef extends AbstractStepDef { + + public static final String CREATE_DATATABLE_RESULT_KEY = "CreateDatatableResult"; + public static final String DATATABLE_NAME = "DatatableId"; + public static final String DATATABLE_QUERY_RESPONSE = "DatatableQueryResponse"; + + @Autowired + private DataTablesApi dataTablesApi; + + @Autowired + private DatatableNameGenerator datatableNameGenerator; + + @When("A datatable for {string} is created") + public void whenDatatableCreated(String entityTypeStr) throws IOException { + DatatableEntityType entityType = DatatableEntityType.fromString(entityTypeStr); + List columns = createRandomDatatableColumnsRequest(); + PostDataTablesRequest request = createDatatableRequest(entityType, columns); + + Response response = dataTablesApi.createDatatable(request).execute(); + checkSuccessfulApiCall(response); + + PostDataTablesResponse responseBody = response.body(); + testContext().set(CREATE_DATATABLE_RESULT_KEY, responseBody); + testContext().set(DATATABLE_NAME, responseBody.getResourceIdentifier()); + } + + @When("A datatable for {string} is created with the following extra columns:") + public void whenDatatableCreatedWithFollowingExtraColumns(String entityTypeStr, DataTable dataTable) throws IOException { + DatatableEntityType entityType = DatatableEntityType.fromString(entityTypeStr); + List> rows = dataTable.asLists(); + List> rowsWithoutHeader = rows.subList(1, rows.size()); + List columns = createDatatableColumnsRequest(rowsWithoutHeader); + PostDataTablesRequest request = createDatatableRequest(entityType, columns); + + Response response = dataTablesApi.createDatatable(request).execute(); + checkSuccessfulApiCall(response); + + PostDataTablesResponse responseBody = response.body(); + testContext().set(CREATE_DATATABLE_RESULT_KEY, responseBody); + testContext().set(DATATABLE_NAME, responseBody.getResourceIdentifier()); + } + + private List createDatatableColumnsRequest(List> rowsWithoutHeader) { + return rowsWithoutHeader.stream().map(row -> { + String columnName = row.get(0); + DatatableColumnType columnType = DatatableColumnType.fromTypeString(row.get(1)); + long columnLength = Long.parseLong(row.get(2)); + boolean unique = BooleanUtils.toBoolean(row.get(3)); + boolean indexed = BooleanUtils.toBoolean(row.get(4)); + + PostColumnHeaderData postColumnHeaderData = new PostColumnHeaderData(); + postColumnHeaderData.setName(columnName); + postColumnHeaderData.setType(columnType.getTypeString()); + postColumnHeaderData.setLength(columnLength); + postColumnHeaderData.setUnique(unique); + postColumnHeaderData.setIndexed(indexed); + return postColumnHeaderData; + }).collect(Collectors.toList()); + } + + @When("A multirow datatable for {string} is created") + public void whenMultirowDatatableCreated(String entityTypeStr) throws IOException { + DatatableEntityType entityType = DatatableEntityType.fromString(entityTypeStr); + List columns = createRandomDatatableColumnsRequest(); + PostDataTablesRequest request = createDatatableRequest(entityType, columns, true); + + Response response = dataTablesApi.createDatatable(request).execute(); + checkSuccessfulApiCall(response); + + PostDataTablesResponse responseBody = response.body(); + testContext().set(CREATE_DATATABLE_RESULT_KEY, responseBody); + testContext().set(DATATABLE_NAME, responseBody.getResourceIdentifier()); + } + + private List createRandomDatatableColumnsRequest() { + PostColumnHeaderData columnDef = new PostColumnHeaderData(); + columnDef.setName("col"); + columnDef.setType(DatatableColumnType.NUMBER.getTypeString()); + columnDef.setMandatory(false); + columnDef.setLength(10L); + columnDef.setCode(""); + columnDef.setUnique(false); + columnDef.setIndexed(false); + return List.of(columnDef); + } + + private PostDataTablesRequest createDatatableRequest(DatatableEntityType entityType, List columns) { + return createDatatableRequest(entityType, columns, false); + } + + private PostDataTablesRequest createDatatableRequest(DatatableEntityType entityType, List columns, + boolean multiRow) { + PostDataTablesRequest request = new PostDataTablesRequest(); + String datatableName = datatableNameGenerator.generate(entityType); + request.setDatatableName(datatableName); + request.setApptableName(entityType.getReferencedTableName()); + request.setMultiRow(multiRow); + request.setColumns(columns); + return request; + } + + @Then("The following column definitions match:") + public void thenColumnsMatch(DataTable dataTable) throws IOException { + String datatableName = testContext().get(DATATABLE_NAME); + Response httpResponse = dataTablesApi.getDatatable(datatableName).execute(); + checkSuccessfulApiCall(httpResponse); + + GetDataTablesResponse response = httpResponse.body(); + Map columnMap = response.getColumnHeaderData().stream() + .collect(Collectors.toMap(ResultsetColumnHeaderData::getColumnName, identity())); + + List> rows = dataTable.asLists(); + List> rowsWithoutHeader = rows.subList(1, rows.size()); + + for (List row : rowsWithoutHeader) { + String columnName = row.get(0); + boolean primaryKey = BooleanUtils.toBoolean(row.get(1)); + boolean unique = BooleanUtils.toBoolean(row.get(2)); + boolean indexed = BooleanUtils.toBoolean(row.get(3)); + + ResultsetColumnHeaderData columnMetadata = columnMap.get(columnName); + assertThat(columnMetadata).withFailMessage("Column [%s] not found on datatable", columnName).isNotNull(); + + assertThat(columnMetadata.getIsColumnPrimaryKey()) + .withFailMessage("Primary key definition for column [%s] does not match", columnName).isEqualTo(primaryKey); + assertThat(columnMetadata.getIsColumnUnique()) + .withFailMessage("Unique constraint definition for column [%s] does not match", columnName).isEqualTo(unique); + assertThat(columnMetadata.getIsColumnIndexed()).withFailMessage("Index definition for column [%s] does not match", columnName) + .isEqualTo(indexed); + } + } + + @When("The client calls the query endpoint for the created datatable with {string} column filter, and {string} value filter") + public void thenColum23nsMatch(String columnFilter, String valueFilter) throws IOException { + Response response = dataTablesApi.queryValues(testContext().get(DATATABLE_NAME), columnFilter, valueFilter, columnFilter) + .execute(); + testContext().set(DATATABLE_QUERY_RESPONSE, response); + } + + @Then("The status of the HTTP response should be {int}") + public void thenStatusCodeMatch(int statusCode) { + Response response = testContext().get(DATATABLE_QUERY_RESPONSE); + assertThat(response.code()).isEqualTo(statusCode); + } + + @Then("The response body should contain the following message: {string}") + public void thenColumnsMatch(String json) throws IOException { + Response response = testContext().get(DATATABLE_QUERY_RESPONSE); + String jsonResponse = response.errorBody().string(); + assertThat(jsonResponse).contains(json); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/InitializingHook.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/InitializingHook.java new file mode 100644 index 00000000000..4ea3cbde7b7 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/InitializingHook.java @@ -0,0 +1,59 @@ +/** + * 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.test.stepdef.hook; + +import io.cucumber.java.AfterAll; +import io.cucumber.java.Before; +import io.cucumber.java.BeforeAll; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.test.initializer.FineractInitializerFactory; +import org.apache.fineract.test.initializer.InitializerProperties; +import org.apache.fineract.test.support.PropertiesFactory; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.support.ResourcePropertySource; + +@Slf4j +@SuppressWarnings({ "HideUtilityClassConstructor" }) +public class InitializingHook { + + @BeforeAll + public static void beforeAll() throws Exception { + StandardEnvironment environment = new StandardEnvironment(); + environment.getPropertySources().addFirst(new ResourcePropertySource("classpath:fineract-test-application.properties")); + InitializerProperties initializerProperties = PropertiesFactory.get(environment, InitializerProperties.class); + if (initializerProperties.isEnabled()) { + log.info("Setting up defaults for Fineract"); + FineractInitializerFactory.get().setupGlobalDefaults(); + } else { + log.info("Skipping defaults for Fineract"); + } + + FineractInitializerFactory.get().setupDefaultsForSuite(); + } + + @Before + public static void before() throws Exception { + FineractInitializerFactory.get().setupDefaultsForScenario(); + } + + @AfterAll + public static void afterAll() throws Exception { + FineractInitializerFactory.get().resetDefaultsAfterSuite(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/MessagingHook.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/MessagingHook.java new file mode 100644 index 00000000000..4004c0f5c57 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/MessagingHook.java @@ -0,0 +1,34 @@ +/** + * 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.test.stepdef.hook; + +import io.cucumber.java.Before; +import org.apache.fineract.test.messaging.store.EventStore; +import org.springframework.beans.factory.annotation.Autowired; + +public class MessagingHook { + + @Autowired + private EventStore eventStore; + + @Before + public void emptyEventStore() { + eventStore.reset(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/TestContextLifecycleHook.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/TestContextLifecycleHook.java new file mode 100644 index 00000000000..5cc409725aa --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/hook/TestContextLifecycleHook.java @@ -0,0 +1,30 @@ +/** + * 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.test.stepdef.hook; + +import io.cucumber.java.After; +import org.apache.fineract.test.support.TestContext; + +public class TestContextLifecycleHook { + + @After + public void tearDown() { + TestContext.INSTANCE.reset(); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/EnumResolver.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/EnumResolver.java new file mode 100644 index 00000000000..2f163515498 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/EnumResolver.java @@ -0,0 +1,36 @@ +/** + * 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.test.support; + +import java.util.Arrays; +import java.util.function.Function; + +public final class EnumResolver { + + private EnumResolver() {} + + public static > T from(Class clazz, String str, Function fn) { + return Arrays.stream(clazz.getEnumConstants()).filter(c -> fn.apply(c).equals(str)).findAny() + .orElseThrow(() -> new IllegalArgumentException("Enum not found for string [%s]".formatted(str))); + } + + public static > T fromString(Class clazz, String str) { + return Enum.valueOf(clazz, str.trim().toUpperCase()); + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesCondition.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesCondition.java new file mode 100644 index 00000000000..722d433146d --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesCondition.java @@ -0,0 +1,36 @@ +/** + * 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.test.support; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public abstract class PropertiesCondition implements Condition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + T properties = PropertiesFactory.get(context.getEnvironment(), getPropertiesClass()); + return matches(properties); + } + + protected abstract Class getPropertiesClass(); + + protected abstract boolean matches(T properties); +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesFactory.java new file mode 100644 index 00000000000..001366d9773 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/PropertiesFactory.java @@ -0,0 +1,55 @@ +/** + * 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.test.support; + +import java.lang.reflect.Constructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.core.env.Environment; +import org.springframework.util.ReflectionUtils; + +public final class PropertiesFactory { + + private static final ConversionService CONVERSION_SERVICE = new DefaultConversionService(); + + private PropertiesFactory() {} + + public static T get(Environment environment, Class clazz) { + try { + Constructor constructor = ReflectionUtils.accessibleConstructor(clazz); + T object = constructor.newInstance(); + ReflectionUtils.doWithFields(clazz, field -> { + field.setAccessible(true); + Value valueAnnotation = field.getAnnotation(Value.class); + if (valueAnnotation != null) { + String expressionString = valueAnnotation.value(); + String propertyValue = environment.resolveRequiredPlaceholders(expressionString); + Object valueToSet = CONVERSION_SERVICE.convert(propertyValue, field.getType()); + field.set(object, valueToSet); + } + }); + return object; + } catch (NoSuchMethodException e) { + throw new RuntimeException("No no-arg constructor is available for class " + clazz.getSimpleName(), e); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java index ac1c7472ef0..daadfe2d1d6 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java @@ -67,6 +67,7 @@ public abstract class TestContextKey { public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_NEXT_REPAYMENTS = "loanProductCreateResponsePin30InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleNextRepayments"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN30_INTEREST_DECLINING_PERIOD_DAILY = "loanProductCreateResponsePin30InterestDecliningPeriodDaily"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION = "loanProductCreateResponsePin4DownPaymentAutoAdvancedPaymentAllocation"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION = "loanProductCreateResponsePin4DownPaymentAdvancedPaymentAllocation"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT = "loanProductCreateResponsePin4DownPayment"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST = "loanProductCreateResponsePin4DownPaymentInterest"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_INTEREST_AUTO = "loanProductCreateResponsePin4DownPaymentInterestAuto"; @@ -75,6 +76,7 @@ public abstract class TestContextKey { public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleVertical"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_INSTALLMENT_LEVEL_DELINQUENCY = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleInstallmentLevelDelinquency"; public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleHorizontalInstallmentLevelDelinquencyCreditAllocation"; + public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_PIN4_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH = "loanProductCreateResponsePin4DownPaymentProgressiveLoanScheduleFixedLength"; public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse"; public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse"; public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse"; diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/FineractConfigLoader.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/FineractConfigLoader.java new file mode 100644 index 00000000000..e0681c8a13b --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/FineractConfigLoader.java @@ -0,0 +1,64 @@ +/** + * 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.test.support.loader; + +import static org.apache.commons.collections4.CollectionUtils.isEmpty; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public final class FineractConfigLoader { + + public static final String FINERACT_TEST_CONFIG_LOCATION = "META-INF/fineract-test.config"; + + public static final String INITIALIZER_CONFIG_KEY = "org.apache.fineract.test.initializer.Configuration"; + + private FineractConfigLoader() {} + + public static Set> getInitializerConfigurationClasses() { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader.getResource(FINERACT_TEST_CONFIG_LOCATION) == null) { + throw new IllegalStateException(""" + Unable to load configuration from [%s] + """.formatted(FINERACT_TEST_CONFIG_LOCATION)); + } + + Map> configurations = PropertiesResourceLoader.load(FINERACT_TEST_CONFIG_LOCATION, classLoader); + List initializerConfigs = configurations.get(INITIALIZER_CONFIG_KEY); + if (isEmpty(initializerConfigs)) { + throw new IllegalStateException(""" + Initializer configuration under key [%s] is missing from [%s] + """.formatted(INITIALIZER_CONFIG_KEY, FINERACT_TEST_CONFIG_LOCATION)); + } + Set> result = new HashSet<>(); + for (String initializerConfigClassName : initializerConfigs) { + try { + Class resolvedClass = classLoader.loadClass(initializerConfigClassName); + result.add(resolvedClass); + } catch (ClassNotFoundException e) { + throw new RuntimeException(""" + Unable to load [%s] initializer configuration class specified in [%s] + """.formatted(initializerConfigClassName, FINERACT_TEST_CONFIG_LOCATION), e); + } + } + return result; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/PropertiesResourceLoader.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/PropertiesResourceLoader.java new file mode 100644 index 00000000000..7f47b68131c --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/loader/PropertiesResourceLoader.java @@ -0,0 +1,67 @@ +/** + * 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.test.support.loader; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.stream.Collectors; +import org.springframework.core.io.UrlResource; +import org.springframework.core.io.support.PropertiesLoaderUtils; +import org.springframework.util.StringUtils; + +public final class PropertiesResourceLoader { + + private PropertiesResourceLoader() {} + + public static Map> load(String resourceLocation, ClassLoader classLoader) { + + Map> result = new HashMap<>(); + try { + Enumeration urls = classLoader.getResources(resourceLocation); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + UrlResource resource = new UrlResource(url); + Properties properties = PropertiesLoaderUtils.loadProperties(resource); + for (Map.Entry entry : properties.entrySet()) { + String factoryTypeName = ((String) entry.getKey()).trim(); + String[] names = StringUtils.commaDelimitedListToStringArray((String) entry.getValue()); + for (String name : names) { + result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()).add(name.trim()); + } + } + } + + result.replaceAll((type, implementations) -> implementations.stream().distinct() + .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); + } catch (IOException ex) { + throw new IllegalArgumentException(""" + Unable to load properties from location [%s] + """.formatted(resourceLocation), ex); + } + return result; + } + +} diff --git a/fineract-e2e-tests-runner/src/test/resources/features/BatchApi.feature b/fineract-e2e-tests-runner/src/test/resources/features/BatchApi.feature new file mode 100644 index 00000000000..0923a1f4459 --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/features/BatchApi.feature @@ -0,0 +1,80 @@ +@BatchApiFeature +Feature: Batch API + + @TestRailId:C63 + Scenario: As a user I would like to run a sample Batch API scenario + When Batch API sample call ran + Then Admin checks that all steps result 200OK + + @TestRailId:C2484 @idempotency + Scenario: As admin I would like to verify that idempotency applies correctly in case of BatchAPI call with the same idempotency key on two repayments + When Batch API call runs with idempotency key + Then Admin checks that all steps result 200OK for Batch API idempotency request + Then Batch API response has boolean value in header "x-served-from-cache": "true" in segment with requestId 6 + Then Batch API response has 200 EUR value for transaction amount in segment with requestId 6 + Then Batch API response has the same clientId and loanId in segment with requestId 6 as in segment with requestId 5 + Then Batch API response has the same idempotency key in segment with requestId 6 as in segment with requestId 5 + Then Loan has 1 "REPAYMENT" transactions on Transactions tab after Batch API run + + @TestRailId:C2640 + Scenario: Verify Batch API call in case of enclosing transaction is TRUE and all steps result 200OK + When Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "true" + Then Admin checks that all steps result 200OK + + @TestRailId:C2641 + Scenario: Verify Batch API call in case of enclosing transaction is TRUE and one of the steps fails + When Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "true", with failed approve step + Then Verify that step 3 throws an error with error code 404 + Then Nr. 1 Client creation was rolled back + Then Nr. 1 Loan creation was rolled back + + @TestRailId:C2642 + Scenario: Verify Batch API call in case of enclosing transaction is FALSE and all steps result 200OK + When Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "false" + Then Admin checks that all steps result 200OK + + @TestRailId:C2643 + Scenario: Verify Batch API call in case of enclosing transaction is FALSE, there is only one reference-tree and one of the steps fails + When Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "false", with failed approve step + Then Verify that step Nr. 1 results 200 + Then Verify that step Nr. 2 results 200 + Then Verify that step 3 throws an error with error code 404 + Then Verify that step Nr. 4 results 200 + Then Nr. 1 Client was created + Then Nr. 1 Loan was created + + @TestRailId:C2644 + Scenario: Verify Batch API call in case of enclosing transaction is FALSE, there are two reference-trees and all steps result 200 + When Batch API call with steps done twice: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "false" + Then Admin checks that all steps result 200OK + + @TestRailId:C2645 + Scenario: Verify Batch API call in case of enclosing transaction is FALSE, there are two reference-trees and one of the steps in second tree fails + When Batch API call with steps done twice: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "false", with failed approve step in second tree + Then Verify that step Nr. 1 results 200 + Then Verify that step Nr. 2 results 200 + Then Verify that step Nr. 3 results 200 + Then Verify that step Nr. 4 results 200 + Then Verify that step Nr. 5 results 200 + Then Verify that step Nr. 6 results 200 + Then Verify that step 7 throws an error with error code 404 + Then Verify that step Nr. 8 results 200 + Then Nr. 1 Client was created + Then Nr. 1 Loan was created + Then Nr. 1 Loan was approved + Then Nr. 2 Client was created + Then Nr. 2 Loan was created + + @TestRailId:C2646 + Scenario: Verify Batch API call in case of enclosing transaction is FALSE and one of the steps is doubled + When Batch API call with steps: createClient, createLoan, approveLoan, getLoanDetails runs with enclosingTransaction: "false", and approveLoan is doubled + Then Admin checks that all steps result 200OK + Then Batch API response has no "x-served-from-cache" field in segment with requestId 3 + Then Batch API response has boolean value in header "x-served-from-cache": "true" in segment with requestId 4 + + @TestRailId:C2840 + Scenario: Verify datatable Batch API calls, when the second request relies on the first response, but the first response is empty + When A datatable for "Loan" is created + And Batch API call with steps: queryDatatable, updateDatatable runs, with empty queryDatatable response + Then Verify that step Nr. 1 results 200 + Then Verify that step Nr. 2 results 400 diff --git a/fineract-e2e-tests-runner/src/test/resources/features/Client.feature b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature index 2728bd0bd45..1a14f23cb31 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/Client.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/Client.feature @@ -26,4 +26,13 @@ Feature: Client Then Client is created successfully Examples: | firstName | lastName | - | "FirstName1" | "Test1" | \ No newline at end of file + | "FirstName1" | "Test1" | + + @TestRailId:C15 + Scenario Outline: Client creation with address functionality for Fineract + When Global configuration "Enable-Address" is enabled + When Admin creates a client with Firstname and Lastname with address + Then Client is created successfully + Examples: + | firstName | lastName | + | "FirstName2" | "Test2" | \ No newline at end of file diff --git a/fineract-e2e-tests-runner/src/test/resources/features/Datatables.feature b/fineract-e2e-tests-runner/src/test/resources/features/Datatables.feature new file mode 100644 index 00000000000..eb157eb12ba --- /dev/null +++ b/fineract-e2e-tests-runner/src/test/resources/features/Datatables.feature @@ -0,0 +1,48 @@ +Feature: Datatables + + Scenario: Datatable's primary key is unique and indexed + When A datatable for "Loan" is created + Then The following column definitions match: + | Name | Primary key | Unique | Indexed | + | loan_id | true | true | true | + + Scenario: Multirow datatable's primary key is unique and indexed + When A multirow datatable for "Loan" is created + Then The following column definitions match: + | Name | Primary key | Unique | Indexed | + | id | true | true | true | + + Scenario: Multirow datatable has the foreign key indexed + When A multirow datatable for "Loan" is created + Then The following column definitions match: + | Name | Primary key | Unique | Indexed | + | loan_id | false | false | true | + + Scenario: Datatable with unique constrained column is indexed + When A datatable for "Loan" is created with the following extra columns: + | Name | Type | Length | Unique | Indexed | + | col1 | string | 10 | true | false | + + Then The following column definitions match: + | Name | Primary key | Unique | Indexed | + | col1 | false | true | true | + + Scenario: Datatable with indexed column + When A datatable for "Loan" is created with the following extra columns: + | Name | Type | Length | Unique | Indexed | + | col1 | string | 10 | false | true | + + Then The following column definitions match: + | Name | Primary key | Unique | Indexed | + | col1 | false | false | true | + + Scenario Outline: Query data from datatable with invalid filter + When A datatable for "Loan" is created + And The client calls the query endpoint for the created datatable with "" column filter, and "" value filter + Then The status of the HTTP response should be 400 + And The response body should contain the following message: "" + Examples: + | column_filter | value_filter | error_message | + | loan_id | InvalidInput | validation.msg.invalid.integer.format | + | created_at | InvalidInput | validation.msg.invalid.dateFormat.format | + | invalidColumn | InvalidInput | validation.msg.validation.errors.exist |