FINERACT-2070: More test cases

This commit is contained in:
Arnold Galovics
2024-03-26 11:01:21 +01:00
committed by Arnold Gálovics
parent 86bd2763f0
commit 5c54a9dbea
153 changed files with 10565 additions and 3 deletions
+4
View File
@@ -62,3 +62,7 @@ dependencies {
testImplementation 'org.apache.commons:commons-collections4:4.4'
}
tasks.withType(JavaCompile).configureEach {
options.compilerArgs.add("-parameters")
}
@@ -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 class ApiConfiguration {
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);
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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);
}
}
@@ -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<Integer, LoanStatus> BY_VALUE = new HashMap<>();
static {
for (LoanStatus e : values()) {
BY_VALUE.put(e.value, e);
}
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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();
}
@@ -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<List<GetGLAccountsResponse>> 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<GetGLAccountsResponse> 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);
}
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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();
}
@@ -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<List<GetJobsResponse>> response = schedulerJobApi.retrieveAll8().execute();
if (!response.isSuccessful()) {
throw new IllegalStateException("Unable to get jobs list. Status code was HTTP " + response.code());
}
List<GetJobsResponse> 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);
}
}
}
@@ -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();
}
}
@@ -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();
}
@@ -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<List<GetLoanProductsResponse>> response = loanProductsApi.retrieveAllLoanProducts().execute();
if (!response.isSuccessful()) {
throw new IllegalStateException("Unable to get loan products. Status code was HTTP " + response.code());
}
List<GetLoanProductsResponse> 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);
}
}
}
@@ -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();
}
}
@@ -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();
}
@@ -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<List<GetPaymentTypesResponse>> response = paymentTypeApi.getAllPaymentTypes(false).execute();
if (!response.isSuccessful()) {
throw new IllegalStateException("Unable to get payment types. Status code was HTTP " + response.code());
}
List<GetPaymentTypesResponse> 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);
}
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
List<Integer> interestRateVariationsForBorrowerCycle = new ArrayList<>();
List<ChargeData> charges = new ArrayList<>();
List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new ArrayList<>();
List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = new ArrayList<>();
List<GetLoanPaymentChannelToFundSourceMappings> 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));//
}
}
@@ -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");
}
}
@@ -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;
}
}
@@ -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<BusinessDateResponse> 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);
}
}
@@ -21,6 +21,8 @@ package org.apache.fineract.test.helper;
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 final class ErrorHelper {
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<List<BatchResponse>> batchResponseList) {
batchResponseList.body().forEach(response -> {
assertThat(response.getStatusCode()).as(ErrorMessageHelper.batchRequestFailedWithCode(response)).isEqualTo(200);
});
}
}
@@ -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 final class ErrorMessageHelper {
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<String, String> entryPairs,
List<GetJournalEntriesTransactionIdResponse> 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<Header> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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<List<List<String>>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<List<String>> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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<GetLoanAccountLockResponse> 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<GetLoanAccountLockResponse> 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<String> actual, List<String> 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<String> actual, List<String> 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<String> actual, List<String> 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<List<String>> actual, List<String> expected) {
String lineStr = String.valueOf(line);
String expectedStr = expected.toString();
StringBuilder sb = new StringBuilder();
for (List<String> 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);
}
}
@@ -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<Error> 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;
}
}
@@ -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<GlobalConfigurationPropertyData> configuration = globalConfigurationApi.retrieveOneByName(configKey).execute();
ErrorHelper.checkSuccessfulApiCall(configuration);
Long configId = configuration.body().getId();
PutGlobalConfigurationsRequest updateRequest = new PutGlobalConfigurationsRequest().enabled(enabled).value(value);
Response<PutGlobalConfigurationsResponse> updateResponse = globalConfigurationApi.updateConfiguration1(configId, updateRequest)
.execute();
assertThat(updateResponse.code()).isEqualTo(HttpStatus.SC_OK);
Response<GlobalConfigurationPropertyData> 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<GlobalConfigurationPropertyData> configuration = globalConfigurationApi.retrieveOneByName(configKey).execute();
ErrorHelper.checkSuccessfulApiCall(configuration);
Long configId = configuration.body().getId();
PutGlobalConfigurationsRequest updateRequest = new PutGlobalConfigurationsRequest().enabled(true).stringValue(value);
Response<PutGlobalConfigurationsResponse> updateResponse = globalConfigurationApi.updateConfiguration1(configId, updateRequest)
.execute();
assertThat(updateResponse.code()).isEqualTo(HttpStatus.SC_OK);
Response<GlobalConfigurationPropertyData> updatedConfiguration = globalConfigurationApi.retrieveOneByName(configKey).execute();
boolean isEnabled = BooleanUtils.toBoolean(updatedConfiguration.body().getEnabled());
assertThat(isEnabled).isEqualTo(true);
}
}
@@ -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 {
}
@@ -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<Class<?>> initializerConfigurationClasses = FineractConfigLoader.getInitializerConfigurationClasses();
ApplicationContext context = new AnnotationConfigApplicationContext(initializerConfigurationClasses.toArray(new Class<?>[0]));
INSTANCE = context.getBean(FineractInitializer.class);
}
}
public static FineractInitializer get() {
return Holder.INSTANCE;
}
}
@@ -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;
}
@@ -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<FineractGlobalInitializerStep> globalInitializerSteps,
List<FineractSuiteInitializerStep> suiteInitializerSteps, List<FineractScenarioInitializerStep> scenarioInitializerSteps,
BusinessDateHelper businessDateHelper) {
return new FineractInitializer(globalInitializerSteps, suiteInitializerSteps, scenarioInitializerSteps, businessDateHelper);
}
}
@@ -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<FineractGlobalInitializerStep> globalInitializerSteps;
private final List<FineractSuiteInitializerStep> suiteInitializerSteps;
private final List<FineractScenarioInitializerStep> 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();
}
}
@@ -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<ChargeProductAppliesTo> CHARGE_APPLIES_TO_LOAN = ChargeProductAppliesTo.LOAN;
public static final Enum<ChargeProductAppliesTo> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> 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<PostChargesResponse> responseClientFixed = chargesApi.createCharge(requestClientFixed).execute();
TestContext.INSTANCE.set(TestContextKey.CHARGE_FOR_CLIENT_FIXED_FEE_CREATE_RESPONSE, responseClientFixed);
}
public static PostChargesRequest defaultChargesRequest(Enum<ChargeProductAppliesTo> 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;
}
}
@@ -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<String> 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<String> countryNames = new ArrayList<>();
countryNames.add(CODE_VALUE_COUNTRY_GERMANY);
createCodeValues(CODE_VALUE_COUNTRY_ID, countryNames);
// State
List<String> stateNames = new ArrayList<>();
stateNames.add(CODE_VALUE_STATE_BERLIN);
createCodeValues(CODE_VALUE_STATE_ID, stateNames);
// financial instrument
List<String> 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<String> transactionTypeNames = new ArrayList<>();
transactionTypeNames.add(CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT);
createCodeValues(CODE_VALUE_TRANSACTION_TYPE_ID, transactionTypeNames);
// bankruptcy tag
List<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> genderNames = new ArrayList<>();
genderNames.add(CODE_VALUE_GENDER_FEMALE);
genderNames.add(CODE_VALUE_GENDER_MALE);
createCodeValues(CODE_VALUE_GENDER_ID, genderNames);
// client type
List<String> 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<String> 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<String> 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<String> 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<String> 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<String> constitutionNames = new ArrayList<>();
constitutionNames.add(CODE_VALUE_CONSTITUTION_TEST);
createCodeValues(CODE_VALUE_CONSTITUTION_ID, constitutionNames);
// add LoanRescheduleReason
List<String> rescheduleReasonNames = new ArrayList<>();
rescheduleReasonNames.add(CODE_VALUE_RESCHEDULE_REASON_TEST);
createCodeValues(CODE_VALUE_RESCHEDULE_REASON_ID, rescheduleReasonNames);
}
public void createCodeValues(Long codeId, List<String> 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<String> 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<String> 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);
}
});
}
}
@@ -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<String> CURRENCIES = Arrays.asList("EUR", "USD");
private final CurrencyApi currencyApi;
@Override
public void initialize() throws Exception {
PutCurrenciesRequest putCurrenciesRequest = new PutCurrenciesRequest();
Response<PutCurrenciesResponse> putCurrenciesResponse = currencyApi.updateCurrencies(putCurrenciesRequest.currencies(CURRENCIES))
.execute();
TestContext.INSTANCE.set(TestContextKey.PUT_CURRENCIES_RESPONSE, putCurrenciesResponse);
}
}
@@ -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<PostColumnHeaderData> 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<PostColumnHeaderData> 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<PostColumnHeaderData> 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();
}
}
@@ -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<Integer> 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<Long> 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();
}
}
@@ -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();
}
}
@@ -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;
}
@@ -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<String> 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);
}
});
}
}
@@ -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();
}
}
@@ -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);
}
}
@@ -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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<ChargeData> charges = new ArrayList<>();
charges.add(new ChargeData().id(ChargeProductType.LOAN_PERCENTAGE_LATE_FEE.value));
PostLoanProductsRequest loanProductsRequestInterestFlatOverdueFeeAmount = loanProductsRequestFactory
.defaultLoanProductsRequestPin30InterestFlat()//
.name(name13)//
.charges(charges);//
Response<PostLoanProductsResponse> 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<ChargeData> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PostLoanProductsResponse> 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<PaymentAllocationOrder> 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<String> creditAllocationRules) {
CreditAllocationData creditAllocationData = new CreditAllocationData();
creditAllocationData.setTransactionType(transactionType);
List<CreditAllocationOrder> 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<PaymentAllocationOrder> 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();
}
}
@@ -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<String> 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);
}
});
}
}
@@ -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);
}
}
@@ -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;
}
@@ -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);
}
}
@@ -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<String, Boolean> eventConfigMap = new HashMap<>();
Response<GetExternalEventConfigurationsResponse> response = eventConfigurationApi.retrieveExternalEventConfiguration().execute();
if (!response.isSuccessful()) {
String responseBody = response.errorBody().string();
throw new RuntimeException("Cannot configure external events due to " + lineSeparator() + responseBody);
}
List<ExternalEventConfigurationItemData> externalEventConfiguration = response.body().getExternalEventConfiguration();
externalEventConfiguration.forEach(e -> {
eventConfigMap.put(e.getType(), true);
});
PutExternalEventConfigurationsRequest request = new PutExternalEventConfigurationsRequest()
.externalEventConfigurations(eventConfigMap);
eventConfigurationApi.updateExternalEventConfigurationsDetails(request).execute();
}
}
@@ -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
}
}
@@ -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();
}
}
@@ -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<Object> {
public EmptyEventMessage() {
super(null, null, null);
}
}
@@ -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 <R, T extends Event<R>> void assertEventRaised(Class<T> eventClazz, Long id) {
internalAssertEventRaised(eventClazz, id, true);
}
public <R, T extends Event<R>> void assertEventNotRaised(Class<T> eventClazz, Long id) {
internalAssertEventNotRaised(eventClazz, id);
}
private <R, T extends Event<R>> void internalAssertEventRaised(Class<T> 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 <R, T extends Event<R>> void internalAssertEventNotRaised(Class<T> 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 <R, T extends Event<R>> EventAssertionBuilder<R> assertEvent(Class<T> eventClazz, Long id) {
EventMessage<R> eventMessage;
if (eventProperties.isEventVerificationEnabled()) {
internalAssertEventRaised(eventClazz, id, false);
T event = eventFactory.create(eventClazz);
eventMessage = eventStore.removeEventById(event, id).get();
} else {
eventMessage = (EventMessage<R>) new EmptyEventMessage();
}
return new EventAssertionBuilder<>(eventMessage);
}
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class EventAssertionBuilder<R> {
private final EventMessage<R> eventMessage;
public EventAssertionBuilder<R> isRaisedOnBusinessDate(LocalDate businessDate) {
if (eventProperties.isEventVerificationEnabled()) {
Assertions.assertThat(eventMessage.getBusinessDate()).isEqualTo(businessDate);
}
return this;
}
public <V> EventDataAssertionBuilder<R, V> extractingData(Function<R, V> valueExtractor) {
V dataValue;
if (eventProperties.isEventVerificationEnabled()) {
dataValue = valueExtractor.apply(eventMessage.getData());
} else {
dataValue = null;
}
return new EventDataAssertionBuilder<>(eventMessage, dataValue);
}
public EventBigDecimalAssertionBuilder<R> extractingBigDecimal(Function<R, BigDecimal> 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<R, V> {
private final EventMessage<R> eventMessage;
private final V extractedValue;
public EventAssertionBuilder<R> isEqualTo(V value) {
if (eventProperties.isEventVerificationEnabled()) {
Assertions.assertThat(extractedValue).isEqualTo(value);
}
return new EventAssertionBuilder<>(eventMessage);
}
public EventAssertionBuilder<R> isNotEqualTo(V value) {
if (eventProperties.isEventVerificationEnabled()) {
Assertions.assertThat(extractedValue).isNotEqualTo(value);
}
return new EventAssertionBuilder<>(eventMessage);
}
}
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class EventBigDecimalAssertionBuilder<R> {
private final EventMessage<R> eventMessage;
private final BigDecimal extractedValue;
public EventAssertionBuilder<R> isEqualTo(BigDecimal value) {
if (eventProperties.isEventVerificationEnabled()) {
Assertions.assertThat(extractedValue).isEqualByComparingTo(value);
}
return new EventAssertionBuilder<>(eventMessage);
}
public EventAssertionBuilder<R> isNotEqualTo(BigDecimal value) {
if (eventProperties.isEventVerificationEnabled()) {
Assertions.assertThat(extractedValue).isNotEqualByComparingTo(value);
}
return new EventAssertionBuilder<>(eventMessage);
}
}
}
@@ -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<T> {
private final String type;
private final LocalDate businessDate;
private final T data;
}
@@ -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();
}
}
@@ -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<EventProperties> {
@Override
protected Class<EventProperties> getPropertiesClass() {
return EventProperties.class;
}
@Override
protected boolean matches(EventProperties properties) {
return properties.isEventVerificationEnabled();
}
}
@@ -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());
}
}
@@ -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");
}
}
}
}
@@ -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<T> {
String getEventName();
Class<T> getDataClass();
Function<T, Long> getIdExtractor();
}
@@ -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<PostClientsResponse> clientCreationResponse) throws IOException {
Response<GetClientsClientIdResponse> 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<PostLoansResponse> createLoanResponse) throws IOException {
Response<GetLoansLoanIdResponse> 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<PostLoansLoanIdResponse> loanApproveResponse) throws IOException {
Response<GetLoansLoanIdResponse> 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<PostLoansLoanIdResponse> loanDisburseResponse) throws IOException {
Response<GetLoansLoanIdResponse> 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<PostLoansLoanIdResponse> loanDisburseResponse) throws IOException {
Long disbursementTransactionId = loanDisburseResponse.body().getSubResourceId();
Response<GetLoansLoanIdResponse> loanDetails = loansApi
.retrieveLoan(loanDisburseResponse.body().getLoanId(), false, "transactions", "", "").execute();
GetLoansLoanIdResponse body = loanDetails.body();
List<GetLoansLoanIdTransactions> 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<LoanTransactionDataV1> transactionEventCheck(
Response<PostLoansLoanIdTransactionsResponse> transactionResponse, TransactionType transactionType, String externalOwnerId)
throws IOException {
Long loanId = transactionResponse.body().getLoanId();
Long transactionId = transactionResponse.body().getResourceId();
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
GetLoansLoanIdTransactions transactionFound = transactions//
.stream()//
.filter(t -> t.getId().equals(transactionId))//
.findAny()//
.orElseThrow(() -> new IllegalStateException("Transaction cannot be found"));//
Class<? extends AbstractLoanTransactionEvent> 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<LoanTransactionDataV1> 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<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
List<ExternalTransferData> 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<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
List<ExternalTransferData> 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<PageExternalTransferData> response = externalAssetOwnersApi.getTransfers(null, loanId, null, null, null).execute();
List<ExternalTransferData> 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<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
List<GetLoansLoanIdDelinquencyPausePeriod> delinquencyPausePeriodsActual = loanDetails.body().getDelinquent()
.getDelinquencyPausePeriods();
eventAssertion.assertEvent(LoanDelinquencyPauseChangedEvent.class, loanId)//
.extractingData(LoanAccountDataV1::getId).isEqualTo(loanId)//
.extractingData(loanAccountDataV1 -> {
List<DelinquencyPausePeriodV1> 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);
}
}
@@ -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 extends Event<?>> T create(Class<T> eventClass) {
try {
Constructor<T> 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);
}
}
}
@@ -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<LoanOwnershipTransferDataV1> {
@Override
public Class<LoanOwnershipTransferDataV1> getDataClass() {
return LoanOwnershipTransferDataV1.class;
}
@Override
public Function<LoanOwnershipTransferDataV1, Long> getIdExtractor() {
return loanOwnershipTransferDataV1 -> (Long) loanOwnershipTransferDataV1.getLoanId();
}
}

Some files were not shown because too many files have changed in this diff Show More