FINERACT-2070: e2e test framework update
This commit is contained in:
+4
-1
@@ -20,7 +20,10 @@ package org.apache.fineract.test.data;
|
||||
|
||||
public enum AdvancePaymentsAdjustmentType {
|
||||
|
||||
RESCHEDULE_NEXT_REPAYMENTS(1), REDUCE_NUMBER_OF_INSTALLMENTS(2), REDUCE_EMI_AMOUNT(3), ADJUST_LAST_UNPAID_PERIOD(4);
|
||||
RESCHEDULE_NEXT_REPAYMENTS(1), //
|
||||
REDUCE_NUMBER_OF_INSTALLMENTS(2), //
|
||||
REDUCE_EMI_AMOUNT(3), //
|
||||
ADJUST_LAST_UNPAID_PERIOD(4);//
|
||||
|
||||
public final Integer value;
|
||||
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT 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 CobBusinessStep {
|
||||
|
||||
APPLY_CHARGE_TO_OVERDUE_LOANS("APPLY_CHARGE_TO_OVERDUE_LOANS"), //
|
||||
LOAN_DELINQUENCY_CLASSIFICATION("LOAN_DELINQUENCY_CLASSIFICATION"), //
|
||||
CHECK_LOAN_REPAYMENT_DUE("CHECK_LOAN_REPAYMENT_DUE"), //
|
||||
CHECK_LOAN_REPAYMENT_OVERDUE("CHECK_LOAN_REPAYMENT_OVERDUE"), //
|
||||
UPDATE_LOAN_ARREARS_AGING("UPDATE_LOAN_ARREARS_AGING"), //
|
||||
ADD_PERIODIC_ACCRUAL_ENTRIES("ADD_PERIODIC_ACCRUAL_ENTRIES"), //
|
||||
EXTERNAL_ASSET_OWNER_TRANSFER("EXTERNAL_ASSET_OWNER_TRANSFER"), //
|
||||
CHECK_DUE_INSTALLMENTS("CHECK_DUE_INSTALLMENTS"), //
|
||||
ACCRUAL_ACTIVITY_POSTING("ACCRUAL_ACTIVITY_POSTING"), //
|
||||
LOAN_INTEREST_RECALCULATION("LOAN_INTEREST_RECALCULATION");//
|
||||
|
||||
public final String value;
|
||||
|
||||
CobBusinessStep(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
+19
-6
@@ -20,16 +20,29 @@ 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");
|
||||
LOAN_CHARGED_OFF("Loan: %s reschedule installment is not allowed. Loan Account is Charged-off"), //
|
||||
LOAN_RESCHEDULE_DATE_NOT_IN_FUTURE("Loan Reschedule From date (%s) for Loan: %s should be in the future."), //
|
||||
LOAN_LOCKED_BY_COB("Loan is locked by the COB job. Loan ID: %s");//
|
||||
|
||||
public final String value;
|
||||
private final String messageTemplate;
|
||||
|
||||
LoanRescheduleErrorMessage(String value) {
|
||||
this.value = value;
|
||||
LoanRescheduleErrorMessage(String messageTemplate) {
|
||||
this.messageTemplate = messageTemplate;
|
||||
}
|
||||
|
||||
public String getValue(Object... params) {
|
||||
return String.format(this.value, params);
|
||||
if (params.length != getExpectedParameterCount()) {
|
||||
throw new IllegalArgumentException("Expected " + getExpectedParameterCount() + " parameters, but got " + params.length);
|
||||
}
|
||||
return String.format(this.messageTemplate, params);
|
||||
}
|
||||
|
||||
public int getExpectedParameterCount() {
|
||||
// Count the number of placeholders (%s) in the message template
|
||||
return (int) messageTemplate.chars().filter(ch -> ch == '%').count();
|
||||
}
|
||||
|
||||
public String getMessageTemplate() {
|
||||
return messageTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,15 @@ 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);
|
||||
NONE(0), //
|
||||
SUBMITTED_AND_PENDING_APPROVAL(100), //
|
||||
APPROVED(200), //
|
||||
ACTIVE(300), //
|
||||
WITHDRAWN(400), //
|
||||
REJECTED(500), //
|
||||
CLOSED_OBLIGATIONS_MET(600), //
|
||||
OVERPAID(700), //
|
||||
CLOSED_WRITTEN_OFF(601);//
|
||||
|
||||
public final Integer value;
|
||||
|
||||
|
||||
+13
-3
@@ -20,9 +20,19 @@ 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");
|
||||
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"), //
|
||||
CHARGE_ADJUSTMENT("chargeAdjustment"), //
|
||||
INTEREST_PAYMENT_WAIVER("interestPaymentWaiver");//
|
||||
|
||||
public final String value;
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ public enum DefaultJob implements Job {
|
||||
INCREASE_BUSINESS_DAY("Increase Business Date by 1 day", "BDT_INC1"), //
|
||||
LOAN_DELINQUENCY_CLASSIFICATION("Loan Delinquency Classification", "LA_DECL"), //
|
||||
LOAN_COB("Loan COB", "LA_ECOB"), //
|
||||
;
|
||||
ACCRUAL_ACTIVITY_POSTING("Accrual Activity Posting", "ACC_ACPO");
|
||||
|
||||
private final String customName;
|
||||
private final String shortName;
|
||||
|
||||
+26
-8
@@ -25,6 +25,8 @@ public enum DefaultLoanProduct implements LoanProduct {
|
||||
LP1_INTEREST_FLAT, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_PERIOD_SAME_AS_PAYMENT, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_PERIOD_DAILY, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_PERIOD_DAILY_ACCRUAL_ACTIVITY, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_ACCRUAL_ACTIVITY, //
|
||||
LP1_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE, //
|
||||
LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INST, //
|
||||
@@ -37,21 +39,37 @@ public enum DefaultLoanProduct implements LoanProduct {
|
||||
LP1_PAYMENT_STRATEGY_DUE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_INTEREST_FLAT, //
|
||||
LP1_INTEREST_FLAT_OVERDUE_FROM_AMOUNT, //
|
||||
LP1_INTEREST_FLAT_OVERDUE_FROM_AMOUNT_INTEREST, //
|
||||
LP2_DOWNPAYMENT, LP2_DOWNPAYMENT_AUTO, //
|
||||
LP2_DOWNPAYMENT, //
|
||||
LP2_DOWNPAYMENT_AUTO, //
|
||||
LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION, //
|
||||
LP2_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION, //
|
||||
LP2_DOWNPAYMENT_INTEREST, LP2_DOWNPAYMENT_INTEREST_AUTO, //
|
||||
LP2_ADV_CUST_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_DOWNPAYMENT_INTEREST, //
|
||||
LP2_DOWNPAYMENT_INTEREST_AUTO, //
|
||||
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL, //
|
||||
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_INSTALLMENT_LEVEL_DELINQUENCY, //
|
||||
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION, //
|
||||
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY, //
|
||||
LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
;
|
||||
LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION_REPAYMENT_START_SUBMITTED, //
|
||||
LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_PMT_ALLOC_1, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_PRECLOSE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_REST_FREQUENCY_DATE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_FULL, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_DOWNPAYMENT, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_365_ACTUAL, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND, //
|
||||
LP1_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM, //
|
||||
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY;//
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
+122
-149
@@ -62,29 +62,30 @@ public class LoanProductsRequestFactory {
|
||||
|
||||
public static final String NAME_PREFIX = "LP1-";
|
||||
public static final String NAME_PREFIX_LP2 = "LP2-";
|
||||
public static final String NAME_PREFIX_LP2_EMI = "LP2Emi-";
|
||||
public static final String NAME_PREFIX_INTEREST_FLAT = "LP1InterestFlat-";
|
||||
public static final String NAME_PREFIX_INTEREST_FLAT_LP2 = "LP2InterestFlat-";
|
||||
public static final String NAME_PREFIX_INTEREST_DECLINING = "LP1InterestDeclining-";
|
||||
public static final String NAME_PREFIX_INTEREST_DECLINING_RECALCULATION = "LP1InterestDecliningRecalculation-";
|
||||
public static final String NAME_PREFIX_INTEREST_RECALCULATION_WITH_DOWN_PAYMENT_LP3 = "LP3InterestRecalculationWithDownPayment-";
|
||||
public static final String NAME_PREFIX_LP2_EMI = "LP2Emi-";
|
||||
public static final String NAME_PREFIX_INTEREST_RECALCULATION = "LP2InterestRecalculation-";
|
||||
public static final String SHORT_NAME_PREFIX = "p";
|
||||
public static final String SHORT_NAME_PREFIX_INTEREST = "i";
|
||||
public static final String SHORT_NAME_PREFIX_EMI = "e";
|
||||
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||
public static final String LOCALE_EN = "en";
|
||||
public static final String DESCRIPTION = "LP1 product";
|
||||
public static final String DESCRIPTION_LP2 = "LP2 product";
|
||||
public static final String DESCRIPTION_INTEREST_FLAT = "LP1 product with 12% interest - FLAT";
|
||||
public static final String DESCRIPTION_INTEREST_FLAT_LP2 = "LP2 product with 12% interest - FLAT";
|
||||
public static final String DESCRIPTION_INTEREST_DECLINING = "LP1 product with 12% interest - DECLINING BALANCE";
|
||||
public static final String DESCRIPTION = "30 days repayment";
|
||||
public static final String DESCRIPTION_LP2 = "4 installments repayment";
|
||||
public static final String DESCRIPTION_LP2_EMI = "4 installments repayment with EMI";
|
||||
public static final String DESCRIPTION_INTEREST_FLAT = "30 days repayment with 12% interest - FLAT";
|
||||
public static final String DESCRIPTION_INTEREST_FLAT_LP2 = "4 installments repayment with 12% interest - FLAT";
|
||||
public static final String DESCRIPTION_INTEREST_DECLINING = "30 days repayment with 12% interest - DECLINING BALANCE";
|
||||
public static final String DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY = "LP1-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 = "LP1 with 12% DECLINING BALANCE interest, interest period: Daily, Interest recalculation-Daily, Compounding:none";
|
||||
public static final String DESCRIPTION_LP2_EMI = "LP2 product with EMI";
|
||||
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 Integer INTEREST_RATE_FREQUENCY_TYPE_WHOLE_TERM = InterestRateFrequencyType.WHOLE_TERM.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;
|
||||
@@ -94,10 +95,10 @@ public class LoanProductsRequestFactory {
|
||||
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 String TRANSACTION_PROCESSING_STRATEGY_CODE_ADVANCED = TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION.value;
|
||||
public static final Integer DAYS_IN_YEAR_TYPE = DaysInYearType.ACTUAL.value;
|
||||
public static final Integer DAYS_IN_YEAR_TYPE_360 = DaysInYearType.DAYS360.value;
|
||||
public static final Integer DAYS_IN_MONTH_TYPE = DaysInMonthType.ACTUAL.value;
|
||||
public static final Integer DAYS_IN_YEAR_TYPE = DaysInYearType.ACTUAL.value;
|
||||
public static final Integer DAYS_IN_MONTH_TYPE_30 = DaysInMonthType.DAYS30.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 Integer LOAN_ACCOUNTING_RULE_NONE = AccountingRule.NONE.value;
|
||||
public static final String OVER_APPLIED_CALCULATION_TYPE = "percentage";
|
||||
@@ -661,36 +662,119 @@ public class LoanProductsRequestFactory {
|
||||
.recalculationRestFrequencyInterval(1);//
|
||||
}
|
||||
|
||||
public PostLoanProductsRequest defaultLoanProductsRequestLP2InterestDailyRecalculationWithDownPayment() {
|
||||
final String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_RECALCULATION_WITH_DOWN_PAYMENT_LP3, 4);
|
||||
public PostLoanProductsRequest defaultLoanProductsRequestLP2InterestDailyRecalculation() {
|
||||
final String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_RECALCULATION, 4);
|
||||
final String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3);
|
||||
|
||||
return new PostLoanProductsRequest().name(name).shortName(shortName)
|
||||
.description(DESCRIPTION_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE).startDate(null).closeDate(null)
|
||||
.accountMovesOutOfNPAOnlyOnArrearsCompletion(false).accountingRule(LOAN_ACCOUNTING_RULE_NONE)
|
||||
.allowApprovedDisbursedAmountsOverApplied(true)
|
||||
.allowAttributeOverrides(new AllowAttributeOverrides().amortizationType(true).interestType(true)
|
||||
.transactionProcessingStrategyCode(true).interestCalculationPeriodType(true).inArrearsTolerance(true)
|
||||
.repaymentEvery(true).graceOnPrincipalAndInterestPayment(true).graceOnArrearsAgeing(true))
|
||||
.allowPartialPeriodInterestCalcualtion(false).allowVariableInstallments(false).amortizationType(AMORTIZATION_TYPE)
|
||||
.canDefineInstallmentAmount(true).canUseForTopup(false).charges(new ArrayList<>()).creditAllocation(new ArrayList<>())
|
||||
.currencyCode(CURRENCY_CODE).dateFormat(DATE_FORMAT).daysInMonthType(DAYS_IN_MONTH_TYPE_30)
|
||||
.daysInYearType(DAYS_IN_YEAR_TYPE_360).delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue()).digitsAfterDecimal(2)
|
||||
.disallowExpectedDisbursements(true).dueDaysForRepaymentEvent(1).enableDownPayment(false)
|
||||
.enableInstallmentLevelDelinquency(true).fixedLength(null).holdGuaranteeFunds(false).inMultiplesOf(0)
|
||||
.includeInBorrowerCycle(false).interestCalculationPeriodType(0).interestRateFrequencyType(3).interestRatePerPeriod(9.99)
|
||||
.interestRateVariationsForBorrowerCycle(new ArrayList<>()).interestRecalculationCompoundingMethod(0).interestType(0)
|
||||
.isArrearsBasedOnOriginalSchedule(false).isEqualAmortization(false).isInterestRecalculationEnabled(true)
|
||||
.isLinkedToFloatingInterestRates(false).loanScheduleProcessingType("HORIZONTAL").loanScheduleType("PROGRESSIVE")
|
||||
.locale(LOCALE_EN).maxInterestRatePerPeriod((double) 50).maxNumberOfRepayments(48).maxPrincipal((double) 10000)
|
||||
.maxTrancheCount(10).minInterestRatePerPeriod((double) 0).minNumberOfRepayments(1).minPrincipal((double) 1)
|
||||
.multiDisburseLoan(true).numberOfRepaymentVariationsForBorrowerCycle(new ArrayList<>()).numberOfRepayments(3)
|
||||
.outstandingLoanBalance((double) 10000).overAppliedCalculationType("flat").overAppliedNumber(10000)
|
||||
.overDueDaysForRepaymentEvent(2).preClosureInterestCalculationStrategy(1).principal((double) 40)
|
||||
.principalThresholdForLastInstallment(50).principalVariationsForBorrowerCycle(new ArrayList<>())
|
||||
.recalculationRestFrequencyInterval(1).recalculationRestFrequencyType(2).repaymentEvery(1).repaymentFrequencyType(2L)
|
||||
.repaymentStartDateType(2).rescheduleStrategyMethod(4).supportedInterestRefundTypes(new ArrayList<>())
|
||||
.transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE_ADVANCED).useBorrowerCycle(false);
|
||||
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)//
|
||||
.startDate(null)//
|
||||
.closeDate(null)//
|
||||
.accountMovesOutOfNPAOnlyOnArrearsCompletion(false)//
|
||||
.allowApprovedDisbursedAmountsOverApplied(true)//
|
||||
.allowAttributeOverrides(new AllowAttributeOverrides()//
|
||||
.amortizationType(true)//
|
||||
.interestType(true)//
|
||||
.transactionProcessingStrategyCode(true)//
|
||||
.interestCalculationPeriodType(true)//
|
||||
.inArrearsTolerance(true)//
|
||||
.repaymentEvery(true)//
|
||||
.graceOnPrincipalAndInterestPayment(true)//
|
||||
.graceOnArrearsAgeing(true))//
|
||||
.allowPartialPeriodInterestCalcualtion(false)//
|
||||
.allowVariableInstallments(false)//
|
||||
.amortizationType(AMORTIZATION_TYPE)//
|
||||
.canDefineInstallmentAmount(true)//
|
||||
.canUseForTopup(false)//
|
||||
.charges(new ArrayList<>()).creditAllocation(new ArrayList<>())//
|
||||
.currencyCode(CURRENCY_CODE)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.daysInMonthType(DAYS_IN_MONTH_TYPE_30)//
|
||||
.daysInYearType(DAYS_IN_YEAR_TYPE_360)//
|
||||
.delinquencyBucketId(DELINQUENCY_BUCKET_ID.longValue())//
|
||||
.digitsAfterDecimal(2)//
|
||||
.disallowExpectedDisbursements(true)//
|
||||
.dueDaysForRepaymentEvent(1)//
|
||||
.enableDownPayment(false)//
|
||||
.enableInstallmentLevelDelinquency(true)//
|
||||
.fixedLength(null).holdGuaranteeFunds(false)//
|
||||
.inMultiplesOf(0)//
|
||||
.includeInBorrowerCycle(false)//
|
||||
.interestCalculationPeriodType(0)//
|
||||
.interestRateFrequencyType(3)//
|
||||
.interestRatePerPeriod(9.99)//
|
||||
.interestRateVariationsForBorrowerCycle(new ArrayList<>())//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.interestType(0)//
|
||||
.isArrearsBasedOnOriginalSchedule(false)//
|
||||
.isEqualAmortization(false)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.isLinkedToFloatingInterestRates(false)//
|
||||
.loanScheduleProcessingType("HORIZONTAL")//
|
||||
.loanScheduleType("PROGRESSIVE")//
|
||||
.locale(LOCALE_EN)//
|
||||
.maxInterestRatePerPeriod((double) 50)//
|
||||
.maxNumberOfRepayments(48)//
|
||||
.maxPrincipal((double) 10000)//
|
||||
.maxTrancheCount(10)//
|
||||
.minInterestRatePerPeriod((double) 0)//
|
||||
.minNumberOfRepayments(1)//
|
||||
.minPrincipal((double) 1)//
|
||||
.multiDisburseLoan(true)//
|
||||
.numberOfRepaymentVariationsForBorrowerCycle(new ArrayList<>())//
|
||||
.numberOfRepayments(3)//
|
||||
.outstandingLoanBalance((double) 10000)//
|
||||
.overAppliedCalculationType("flat")//
|
||||
.overAppliedNumber(10000)//
|
||||
.overDueDaysForRepaymentEvent(2)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.principal((double) 40)//
|
||||
.principalThresholdForLastInstallment(50)//
|
||||
.principalVariationsForBorrowerCycle(new ArrayList<>())//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.repaymentEvery(1)//
|
||||
.repaymentFrequencyType(2L)//
|
||||
.repaymentStartDateType(2)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.supportedInterestRefundTypes(new ArrayList<>())//
|
||||
.transactionProcessingStrategyCode(TRANSACTION_PROCESSING_STRATEGY_CODE_ADVANCED)//
|
||||
.useBorrowerCycle(false)//
|
||||
.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))//
|
||||
.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 defaultLoanProductsRequestLP2() {
|
||||
@@ -806,116 +890,6 @@ public class LoanProductsRequestFactory {
|
||||
.incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));//
|
||||
}
|
||||
|
||||
public PostLoanProductsRequest defaultLoanProductsRequestLP2NoDown() {
|
||||
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_LP2)//
|
||||
.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 defaultLoanProductsRequestLP2InterestFlat() {
|
||||
String name = Utils.randomNameGenerator(NAME_PREFIX_INTEREST_FLAT_LP2, 4);
|
||||
String shortName = Utils.randomNameGenerator(SHORT_NAME_PREFIX_INTEREST, 3);
|
||||
@@ -1136,5 +1110,4 @@ public class LoanProductsRequestFactory {
|
||||
.chargeOffFraudExpenseAccountId(accountTypeResolver.resolve(DefaultAccountType.CREDIT_LOSS_BAD_DEBT_FRAUD))//
|
||||
.incomeFromChargeOffPenaltyAccountId(accountTypeResolver.resolve(DefaultAccountType.FEE_CHARGE_OFF));//
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-5
@@ -19,8 +19,6 @@
|
||||
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;
|
||||
@@ -39,6 +37,7 @@ 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.apache.fineract.test.helper.Utils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -79,8 +78,10 @@ public class LoanRequestFactory {
|
||||
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 static final String DATE_SUBMIT_STRING = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
public static final String DATE_REJECT_STRING = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
public static final String DATE_WITHDRAWN_STRING = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
public static final String DEFAULT_TRANSACTION_DATE = FORMATTER.format(Utils.now().minusMonths(1L));
|
||||
|
||||
public PostLoansRequest defaultLoansRequest(Long clientId) {
|
||||
return new PostLoansRequest()//
|
||||
@@ -108,7 +109,7 @@ public class LoanRequestFactory {
|
||||
|
||||
public PutLoansLoanIdRequest modifySubmittedOnDateOnLoan(Long clientId, String newSubmittedOnDate) {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
String dateDisburseStr = formatter.format(LocalDate.now(Clock.systemUTC()));
|
||||
String dateDisburseStr = formatter.format(Utils.now());
|
||||
|
||||
return new PutLoansLoanIdRequest()//
|
||||
.productId(loanProductResolver.resolve(DEFAULT_LOAN_PRODUCT))//
|
||||
@@ -162,6 +163,20 @@ public class LoanRequestFactory {
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostLoansLoanIdRequest defaultLoanRejectRequest() {
|
||||
return new PostLoansLoanIdRequest()//
|
||||
.rejectedOnDate(DATE_REJECT_STRING)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostLoansLoanIdRequest defaultLoanWithdrawnRequest() {
|
||||
return new PostLoansLoanIdRequest()//
|
||||
.withdrawnOnDate(DATE_WITHDRAWN_STRING)//
|
||||
.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);
|
||||
|
||||
+91
@@ -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.factory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsAccountIdRequest;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsRequest;
|
||||
|
||||
public final class SavingsAccountRequestFactory {
|
||||
|
||||
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||
public static final String DEFAULT_LOCALE = "en";
|
||||
public static final String DEFAULT_TRANSACTION_DATE = "";
|
||||
public static final Integer DEFAULT_CLIENT_ID = 1;
|
||||
public static final String DEFAULT_SUBMITTED_ON_DATE = "";
|
||||
public static final String DEFAULT_APPROVED_ON_DATE = "";
|
||||
public static final String DEFAULT_ACTIVATED_ON_DATE = "";
|
||||
public static final BigDecimal DEFAULT_REPAYMENT_TRANSACTION_AMOUNT = new BigDecimal(1);
|
||||
public static final Integer DEFAULT_PAYMENT_TYPE_ID = 2;
|
||||
public static final Integer EUR_SAVING_PRODUCT_ID = 1;
|
||||
public static final Integer USD_SAVING_PRODUCT_ID = 2;
|
||||
|
||||
private SavingsAccountRequestFactory() {}
|
||||
|
||||
public static PostSavingsAccountsRequest defaultEURSavingsAccountRequest() {
|
||||
return new PostSavingsAccountsRequest()//
|
||||
.clientId(DEFAULT_CLIENT_ID)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.productId(EUR_SAVING_PRODUCT_ID)//
|
||||
.submittedOnDate(DEFAULT_SUBMITTED_ON_DATE)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostSavingsAccountsRequest defaultUSDSavingsAccountRequest() {
|
||||
return new PostSavingsAccountsRequest()//
|
||||
.clientId(DEFAULT_CLIENT_ID)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.productId(USD_SAVING_PRODUCT_ID)//
|
||||
.submittedOnDate(DEFAULT_SUBMITTED_ON_DATE)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostSavingsAccountsAccountIdRequest defaultApproveRequest() {
|
||||
return new PostSavingsAccountsAccountIdRequest()//
|
||||
.approvedOnDate(DEFAULT_APPROVED_ON_DATE)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostSavingsAccountsAccountIdRequest defaultActivateRequest() {
|
||||
return new PostSavingsAccountsAccountIdRequest()//
|
||||
.activatedOnDate(DEFAULT_ACTIVATED_ON_DATE)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostSavingsAccountTransactionsRequest defaultDepositRequest() {
|
||||
return new PostSavingsAccountTransactionsRequest()//
|
||||
.transactionDate(DEFAULT_TRANSACTION_DATE)//
|
||||
.transactionAmount(DEFAULT_REPAYMENT_TRANSACTION_AMOUNT)//
|
||||
.paymentTypeId(DEFAULT_PAYMENT_TYPE_ID)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
|
||||
public static PostSavingsAccountTransactionsRequest defaultWithdrawRequest() {
|
||||
return new PostSavingsAccountTransactionsRequest()//
|
||||
.transactionDate(DEFAULT_TRANSACTION_DATE)//
|
||||
.transactionAmount(DEFAULT_REPAYMENT_TRANSACTION_AMOUNT)//
|
||||
.paymentTypeId(DEFAULT_PAYMENT_TYPE_ID)//
|
||||
.dateFormat(DATE_FORMAT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
}
|
||||
}
|
||||
+63
@@ -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.factory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.client.models.PostSavingsCharges;
|
||||
import org.apache.fineract.client.models.PostSavingsProductsRequest;
|
||||
|
||||
public final class SavingsProductRequestFactory {
|
||||
|
||||
public static final String DEFAULT_SAVINGS_PRODUCT_NAME = "CEUR";
|
||||
|
||||
public static final String DEFAULT_SAVINGS_PRODUCT_SHORT_NAME = "CEU";
|
||||
public static final String DEFAULT_SAVINGS_PRODUCT_DESCRIPTION = "";
|
||||
public static final String DEFAULT_SAVINGS_PRODUCT_CURRENCY_CODE = "EUR";
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_DIGITS_AFTER_DECIMAL = 2;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_IN_MULTIPLES_OF = 0;
|
||||
public static final Double DEFAULT_SAVINGS_PRODUCT_NOMINAL_ANNUAL_INTEREST_RATE = 0.0;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_INTEREST_COMPOUNDING_PERIOD_TIME = 1;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_INTEREST_POSTING_PERIOD_TIME = 4;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_INTEREST_CALCULATION_TYPE = 1;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_INTEREST_CALCULATION_DAYS_IN_YEAR_TYPE = 365;
|
||||
public static final Integer DEFAULT_SAVINGS_PRODUCT_ACCOUNTING_RULE = 1;
|
||||
public static final String LOCALE_EN = "en";
|
||||
|
||||
private SavingsProductRequestFactory() {}
|
||||
|
||||
public static PostSavingsProductsRequest defaultSavingsProductRequest() {
|
||||
Set<PostSavingsCharges> charges = new HashSet<>();
|
||||
|
||||
return new PostSavingsProductsRequest().name(DEFAULT_SAVINGS_PRODUCT_NAME)//
|
||||
.shortName(DEFAULT_SAVINGS_PRODUCT_SHORT_NAME)//
|
||||
.description(DEFAULT_SAVINGS_PRODUCT_DESCRIPTION)//
|
||||
.currencyCode(DEFAULT_SAVINGS_PRODUCT_CURRENCY_CODE)//
|
||||
.digitsAfterDecimal(DEFAULT_SAVINGS_PRODUCT_DIGITS_AFTER_DECIMAL)//
|
||||
.inMultiplesOf(DEFAULT_SAVINGS_PRODUCT_IN_MULTIPLES_OF)//
|
||||
.nominalAnnualInterestRate(DEFAULT_SAVINGS_PRODUCT_NOMINAL_ANNUAL_INTEREST_RATE)//
|
||||
.interestCompoundingPeriodType(DEFAULT_SAVINGS_PRODUCT_INTEREST_COMPOUNDING_PERIOD_TIME)//
|
||||
.interestPostingPeriodType(DEFAULT_SAVINGS_PRODUCT_INTEREST_POSTING_PERIOD_TIME)//
|
||||
.interestCalculationType(DEFAULT_SAVINGS_PRODUCT_INTEREST_CALCULATION_TYPE)//
|
||||
.interestCalculationDaysInYearType(DEFAULT_SAVINGS_PRODUCT_INTEREST_CALCULATION_DAYS_IN_YEAR_TYPE)//
|
||||
.charges(charges)//
|
||||
.accountingRule(DEFAULT_SAVINGS_PRODUCT_ACCOUNTING_RULE)//
|
||||
.locale(LOCALE_EN);//
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -19,8 +19,6 @@
|
||||
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;
|
||||
@@ -53,7 +51,7 @@ public class BusinessDateHelper {
|
||||
|
||||
public void setBusinessDateToday() throws IOException {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
String today = formatter.format(LocalDate.now(Clock.systemUTC()));
|
||||
String today = formatter.format(Utils.now());
|
||||
setBusinessDate(today);
|
||||
}
|
||||
|
||||
|
||||
+26
-17
@@ -24,7 +24,6 @@ import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.client.models.BatchResponse;
|
||||
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
|
||||
@@ -63,14 +62,14 @@ public final class ErrorMessageHelper {
|
||||
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 disbursePastDateFailure(Integer loanId, String actualDisbursementDate) {
|
||||
return String.format("The date on which a loan is disbursed cannot be before its approval date: %s", actualDisbursementDate);
|
||||
}
|
||||
|
||||
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.";
|
||||
}
|
||||
@@ -787,6 +786,26 @@ public final class ErrorMessageHelper {
|
||||
sb.toString(), expectedStr);
|
||||
}
|
||||
|
||||
public static String wrongValueInLineInLoanTermVariations(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 Loan Term Variations line %s. %nActual values in line: %s %nExpected values in line: %s",
|
||||
lineStr, sb.toString(), expectedStr);
|
||||
}
|
||||
|
||||
public static String wrongNumberOfLinesInLoanTermVariations(int actual, int expected) {
|
||||
String actualStr = String.valueOf(actual);
|
||||
String expectedStr = String.valueOf(expected);
|
||||
return String.format("Number of items (lines) in Loan Term Variations is not correct. Actual value is: %s - Expected value is: %s",
|
||||
actualStr, expectedStr);
|
||||
}
|
||||
|
||||
public static String nrOfLinesWrongInLoanDelinquencyPauseData(int actual, int expected) {
|
||||
String actualStr = String.valueOf(actual);
|
||||
String expectedStr = String.valueOf(expected);
|
||||
@@ -866,17 +885,7 @@ public final class ErrorMessageHelper {
|
||||
expectedToStr);
|
||||
}
|
||||
|
||||
public static String wrongValueInLineInLoanTermVariations(final int line, final List<List<String>> actual,
|
||||
final List<String> expected) {
|
||||
final String actualValues = actual.stream().map(List::toString).collect(Collectors.joining(System.lineSeparator()));
|
||||
|
||||
return String.format(
|
||||
"%nWrong value in loan term variations tab line %d.%nActual values in line (with the same term variation applicable from) are:%n%s%nExpected values in line:%n%s",
|
||||
line, actualValues, expected);
|
||||
}
|
||||
|
||||
public static String wrongNumberOfLinesInLoanTermVariations(final int actual, final int expected) {
|
||||
return String.format("Number of lines in loan term variations is not correct. Actual value is: %d - Expected value is: %d", actual,
|
||||
expected);
|
||||
public static String downpaymentDisabledOnProductErrorCodeMsg() {
|
||||
return "The Loan can not override the downpayment properties because in the Loan Product the downpayment is disabled";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
package org.apache.fineract.test.helper;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public final class Utils {
|
||||
|
||||
@@ -42,4 +44,8 @@ public final class Utils {
|
||||
public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) {
|
||||
return randomStringGenerator(prefix, lenOfRandomSuffix);
|
||||
}
|
||||
|
||||
public static LocalDate now() {
|
||||
return LocalDate.now(Clock.systemUTC());
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.helper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.client.models.BusinessStep;
|
||||
import org.apache.fineract.client.models.GetBusinessStepConfigResponse;
|
||||
import org.apache.fineract.client.services.BusinessStepConfigurationApi;
|
||||
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 WorkFlowJobHelper {
|
||||
|
||||
private static final String WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS = "LOAN_CLOSE_OF_BUSINESS";
|
||||
|
||||
private final BusinessStepConfigurationApi businessStepConfigurationApi;
|
||||
|
||||
public void saveOriginalCOBWorkflowJobBusinessStepList() throws IOException {
|
||||
Response<GetBusinessStepConfigResponse> businessStepConfigResponse = businessStepConfigurationApi
|
||||
.retrieveAllConfiguredBusinessStep(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS).execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(businessStepConfigResponse);
|
||||
List<BusinessStep> businessSteps = businessStepConfigResponse.body().getBusinessSteps();
|
||||
businessSteps.sort(Comparator.comparingLong(BusinessStep::getOrder));
|
||||
TestContext.GLOBAL.set(TestContextKey.ORIGINAL_COB_WORKFLOW_JOB_BUSINESS_STEP_LIST, businessSteps);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -21,6 +21,7 @@ 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.helper.WorkFlowJobHelper;
|
||||
import org.apache.fineract.test.initializer.global.FineractGlobalInitializerStep;
|
||||
import org.apache.fineract.test.initializer.scenario.FineractScenarioInitializerStep;
|
||||
import org.apache.fineract.test.initializer.suite.FineractSuiteInitializerStep;
|
||||
@@ -39,7 +40,8 @@ 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);
|
||||
BusinessDateHelper businessDateHelper, WorkFlowJobHelper workFlowJobHelper) {
|
||||
return new FineractInitializer(globalInitializerSteps, suiteInitializerSteps, scenarioInitializerSteps, businessDateHelper,
|
||||
workFlowJobHelper);
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -23,6 +23,7 @@ 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.helper.WorkFlowJobHelper;
|
||||
import org.apache.fineract.test.initializer.global.FineractGlobalInitializerStep;
|
||||
import org.apache.fineract.test.initializer.scenario.FineractScenarioInitializerStep;
|
||||
import org.apache.fineract.test.initializer.suite.FineractSuiteInitializerStep;
|
||||
@@ -38,6 +39,7 @@ public class FineractInitializer implements InitializingBean {
|
||||
private final List<FineractSuiteInitializerStep> suiteInitializerSteps;
|
||||
private final List<FineractScenarioInitializerStep> scenarioInitializerSteps;
|
||||
private final BusinessDateHelper businessDateHelper;
|
||||
private final WorkFlowJobHelper workFlowJobHelper;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
@@ -71,6 +73,7 @@ public class FineractInitializer implements InitializingBean {
|
||||
}
|
||||
|
||||
businessDateHelper.setBusinessDateToday();
|
||||
workFlowJobHelper.saveOriginalCOBWorkflowJobBusinessStepList();
|
||||
}
|
||||
|
||||
public void setupDefaultsForScenario() throws Exception {
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.initializer.global;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.client.models.BusinessStep;
|
||||
import org.apache.fineract.client.models.GetBusinessStepConfigResponse;
|
||||
import org.apache.fineract.client.models.UpdateBusinessStepConfigRequest;
|
||||
import org.apache.fineract.client.services.BusinessStepConfigurationApi;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
import retrofit2.Response;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class CobBusinessStepInitializerStep implements FineractGlobalInitializerStep {
|
||||
|
||||
private static final String WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS = "LOAN_CLOSE_OF_BUSINESS";
|
||||
private static final String BUSINESS_STEP_NAME_ACCRUAL_ACTIVITY_POSTING = "ACCRUAL_ACTIVITY_POSTING";
|
||||
private final BusinessStepConfigurationApi businessStepConfigurationApi;
|
||||
|
||||
@Override
|
||||
public void initialize() throws Exception {
|
||||
// --- Adding ACCRUAL_ACTIVITY_POSTING to default COB steps ---
|
||||
Response<GetBusinessStepConfigResponse> businessStepConfigResponse = businessStepConfigurationApi
|
||||
.retrieveAllConfiguredBusinessStep(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS).execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(businessStepConfigResponse);
|
||||
List<BusinessStep> businessSteps = businessStepConfigResponse.body().getBusinessSteps();
|
||||
businessSteps.sort(Comparator.comparingLong(BusinessStep::getOrder));
|
||||
Long lastOrder = businessSteps.get(businessSteps.size() - 1).getOrder();
|
||||
|
||||
BusinessStep accrualActivityPosting = new BusinessStep().stepName(BUSINESS_STEP_NAME_ACCRUAL_ACTIVITY_POSTING).order(lastOrder + 1);
|
||||
businessSteps.add(accrualActivityPosting);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
}
|
||||
}
|
||||
+464
-36
@@ -19,7 +19,9 @@
|
||||
package org.apache.fineract.test.initializer.global;
|
||||
|
||||
import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
|
||||
import static org.apache.fineract.test.factory.LoanProductsRequestFactory.INTEREST_RATE_FREQUENCY_TYPE_WHOLE_TERM;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -479,13 +481,243 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH,
|
||||
responseLoanProductsRequestDownPaymentAdvPmtAllocFixedLength);
|
||||
|
||||
// LP2 with Down-payment+autopayment + advanced payment allocation + repayment start date SUBMITTED ON DATE
|
||||
// (LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION_REPAYMENT_START_SUBMITTED)
|
||||
String name26 = DefaultLoanProduct.LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION_REPAYMENT_START_SUBMITTED.getName();
|
||||
PostLoanProductsRequest loanProductsRequestDownPaymentAutoAdvPaymentAllocationRepaymentStartSubmitted = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2()//
|
||||
.name(name26)//
|
||||
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
|
||||
.loanScheduleType("PROGRESSIVE") //
|
||||
.repaymentStartDateType(2)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestDownPaymentAutoAdvPaymentAllocationRepaymentStartSubmitted = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestDownPaymentAutoAdvPaymentAllocationRepaymentStartSubmitted).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_AUTO_ADVANCED_REPAYMENT_ALLOCATION_PAYMENT_START_SUBMITTED,
|
||||
responseLoanProductsRequestDownPaymentAutoAdvPaymentAllocationRepaymentStartSubmitted);
|
||||
|
||||
// LP2 with Down-payment + advanced payment allocation + progressive loan schedule + horizontal + interest Flat
|
||||
// (LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC)
|
||||
String name27 = DefaultLoanProduct.LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC.getName();
|
||||
PostLoanProductsRequest loanProductsRequestDownPaymentAdvPaymentAllocationInterestFlat = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2InterestFlat()//
|
||||
.name(name27)//
|
||||
.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> responseLoanProductsRequestDownPaymentAdvPaymentAllocationInterestFlat = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestDownPaymentAdvPaymentAllocationInterestFlat).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC,
|
||||
responseLoanProductsRequestDownPaymentAdvPaymentAllocationInterestFlat);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL)
|
||||
String name28 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActual = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name28)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActual = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActual).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActual);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30)
|
||||
String name29 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030 = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name29)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030 = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30 + multidisbursement
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE)
|
||||
String name36 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030MultiDisburse = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name36)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
|
||||
.multiDisburseLoan(true)//
|
||||
.disallowExpectedDisbursements(true)//
|
||||
.maxTrancheCount(10)//
|
||||
.outstandingLoanBalance(10000.0);//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030MultiDisburse = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030MultiDisburse).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030MultiDisburse);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30 + multidisbursement + downpayment
|
||||
// 25%, auto disabled
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT)
|
||||
String name37 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030MultiDisburseDownPayment = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name37)//
|
||||
.enableDownPayment(true)//
|
||||
.disbursedAmountPercentageForDownPayment(new BigDecimal(25))//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
|
||||
.multiDisburseLoan(true)//
|
||||
.disallowExpectedDisbursements(true)//
|
||||
.maxTrancheCount(10)//
|
||||
.outstandingLoanBalance(10000.0);//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030MultiDisburseDownPayment = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030MultiDisburseDownPayment).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030MultiDisburseDownPayment);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 365/Actual
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_365_ACTUAL)
|
||||
String name30 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_365_ACTUAL.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterest365Actual = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name30)//
|
||||
.daysInYearType(DaysInYearType.DAYS365.value)//
|
||||
.daysInMonthType(DaysInMonthType.ACTUAL.value)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmi365Actual = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterest365Actual).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_365_ACTUAL,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmi365Actual);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30 + downpayment 25%
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_DOWNPAYMENT)
|
||||
String name31 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_DOWNPAYMENT.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterest36030Downpayment = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name31)//
|
||||
.enableDownPayment(true)//
|
||||
.disbursedAmountPercentageForDownPayment(new BigDecimal(25))//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmi36030Downpayment = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterest36030Downpayment).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_DOWNPAYMENT,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmi36030Downpayment);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual +
|
||||
// enableAccrualActivityPosting
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY)
|
||||
String name32 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualAccrualActivity = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name32)//
|
||||
.enableAccrualActivityPosting(true)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualAccrualActivity = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualAccrualActivity).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualAccrualActivity);
|
||||
|
||||
// LP1 with 12% DECLINING BALANCE interest, interest period: Daily + enableAccrualActivityPosting
|
||||
// (LP1_INTEREST_DECLINING_BALANCE_PERIOD_DAILY_ACCRUAL_ACTIVITY)
|
||||
String name33 = DefaultLoanProduct.LP1_INTEREST_DECLINING_BALANCE_PERIOD_DAILY_ACCRUAL_ACTIVITY.getName();
|
||||
PostLoanProductsRequest loanProductsRequestInterestDecliningPeriodDailyAccrualActivity = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP1InterestDeclining()//
|
||||
.name(name33)//
|
||||
.enableAccrualActivityPosting(true)//
|
||||
.interestCalculationPeriodType(InterestCalculationPeriodTime.DAILY.value)//
|
||||
.allowPartialPeriodInterestCalcualtion(false);//
|
||||
Response<PostLoanProductsResponse> responseInterestDecliningPeriodDailyAccrualActivity = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestInterestDecliningPeriodDailyAccrualActivity).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_PERIOD_DAILY_ACCRUAL_ACTIVITY,
|
||||
responseInterestDecliningPeriodDailyAccrualActivity);
|
||||
|
||||
// LP1 with 12% DECLINING BALANCE interest, interest period: Daily, Interest
|
||||
// recalculation-Daily, Compounding:none + enableAccrualActivityPosting
|
||||
// (LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_ACCRUAL_ACTIVITY)
|
||||
String name34 = DefaultLoanProduct.LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_ACCRUAL_ACTIVITY.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneAccrualActivity = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP1InterestDecliningBalanceDailyRecalculationCompoundingNone()//
|
||||
.name(name34)//
|
||||
.enableAccrualActivityPosting(true)//
|
||||
.interestCalculationPeriodType(InterestCalculationPeriodTime.DAILY.value)//
|
||||
.allowPartialPeriodInterestCalcualtion(false);//
|
||||
Response<PostLoanProductsResponse> responseLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneAccrualActivity = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneAccrualActivity)
|
||||
.execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_ACCRUAL_ACTIVITY,
|
||||
responseLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneAccrualActivity);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual + interest refund with
|
||||
// Merchant issued and Payment refund
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND)
|
||||
String name35 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND.getName();
|
||||
List<String> supportedInterestRefundTypes = Arrays.asList("MERCHANT_ISSUED_REFUND", "PAYOUT_REFUND");
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefund = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name35)//
|
||||
.supportedInterestRefundTypes(supportedInterestRefundTypes).paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("INTEREST_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefund = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefund).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefund);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till preclose,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Daily, Frequency Interval for recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE)
|
||||
String name38 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcTillPreclose = loanProductsRequestFactory
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE)
|
||||
String name38 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPreclose = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name38)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
@@ -497,20 +729,24 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcTillPreClose = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcTillPreclose).execute();
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillPreCloese = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPreclose).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcTillPreClose);
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillPreCloese);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till rest frequency,
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till rest frequency date,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Daily, Frequency Interval for recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY)
|
||||
String name39 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcTillRestFrequency = loanProductsRequestFactory
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE)
|
||||
String name39 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE
|
||||
.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillRestFrequencyDate = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name39)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
@@ -526,16 +762,78 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcTillRestFrequency = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcTillRestFrequency).execute();
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillRestFrequencyDate = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillRestFrequencyDate).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcTillRestFrequency);
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillRestFrequencyDate);
|
||||
|
||||
String name40 = DefaultLoanProduct.LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvPmtAllocProgressiveLoanScheduleHorizontal = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2NoDown()//
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till preclose,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Same as repayment period, Frequency Interval for
|
||||
// recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_PRECLOSE)
|
||||
String name40 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_PRECLOSE.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcSameAsRepTillPreclose = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name40)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(1)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcSameAsRepTillPreCloese = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcSameAsRepTillPreclose).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SAME_AS_REP_TILL_PRECLOSE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcSameAsRepTillPreCloese);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till rest frequency date,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Same as repayment period, Frequency Interval for
|
||||
// recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_REST_FREQUENCY_DATE)
|
||||
String name41 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SARP_TILL_REST_FREQUENCY_DATE
|
||||
.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcSameAsRepTillRestFrequencyDate = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name41)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(2)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(1)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcSameAsRepTillRestFrequencyDate = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcSameAsRepTillRestFrequencyDate)
|
||||
.execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SAME_AS_REP_TILL_REST_FREQUENCY_DATE,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcSameAsRepTillRestFrequencyDate);
|
||||
|
||||
// LP1 advanced payment allocation + progressive loan schedule + horizontal
|
||||
// (LP1_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL)
|
||||
String name42 = DefaultLoanProduct.LP1_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP1AdvPmtAllocProgressiveLoanScheduleHorizontal = loanProductsRequestFactory//
|
||||
.defaultLoanProductsRequestLP1()//
|
||||
.name(name42)//
|
||||
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.getValue())//
|
||||
.loanScheduleType("PROGRESSIVE") //
|
||||
.loanScheduleProcessingType("HORIZONTAL")//
|
||||
@@ -544,20 +842,22 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLP2AdvPmtAllocProgressiveLoanScheduleHorizontal = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvPmtAllocProgressiveLoanScheduleHorizontal).execute();
|
||||
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL,
|
||||
responseLP2AdvPmtAllocProgressiveLoanScheduleHorizontal);
|
||||
Response<PostLoanProductsResponse> responseLP1AdvPmtAllocProgressiveLoanScheduleHorizontal = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP1AdvPmtAllocProgressiveLoanScheduleHorizontal).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL,
|
||||
responseLP1AdvPmtAllocProgressiveLoanScheduleHorizontal);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till preclose,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Daily, Frequency Interval for recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE)
|
||||
String name41 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY
|
||||
// Frequency for Interest rate - Whole Year
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM)
|
||||
String name43 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM
|
||||
.getName();
|
||||
PostLoanProductsRequest product41 = loanProductsRequestFactory.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name41)//
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseWholeTerm = loanProductsRequestFactory//
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name43)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
@@ -566,19 +866,25 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.interestRatePerPeriod((double) 4)//
|
||||
.interestRateFrequencyType(INTEREST_RATE_FREQUENCY_TYPE_WHOLE_TERM)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "LAST_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> response41 = loanProductsApi.createLoanProduct(product41).execute();
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseWholeTerm = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseWholeTerm).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_LAST,
|
||||
response41);
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM,
|
||||
responseLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseWholeTerm);
|
||||
|
||||
// LP2 with Down-payment + advanced custom payment allocation + progressive loan schedule + horizontal
|
||||
// (LP2_DOWNPAYMENT_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL)
|
||||
String name44 = DefaultLoanProduct.LP2_ADV_CUST_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL.getName();
|
||||
// LP2 + interest recalculation + advanced custom payment allocation + progressive loan schedule + horizontal
|
||||
// (LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL)
|
||||
String name44 = DefaultLoanProduct.LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL.getName();
|
||||
|
||||
PostLoanProductsRequest loanProductsRequestAdvCustomPaymentAllocationProgressiveLoanSchedule = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2InterestDailyRecalculationWithDownPayment()//
|
||||
.defaultLoanProductsRequestLP2InterestDailyRecalculation()//
|
||||
.name(name44)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT",
|
||||
@@ -602,6 +908,88 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE,
|
||||
responseLoanProductsRequestAdvCustomPaymentAllocationProgressiveLoanSchedule);
|
||||
|
||||
String name45 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_FULL.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundFull = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name45)//
|
||||
.multiDisburseLoan(true)//
|
||||
.disallowExpectedDisbursements(true)//
|
||||
.maxTrancheCount(10)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.supportedInterestRefundTypes(supportedInterestRefundTypes).paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("GOODWILL_CREDIT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocation("INTEREST_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundFull = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundFull).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_FULL,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundFull);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till preclose,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// payment allocation order: penalty-fee-interest-principal
|
||||
// Frequency for recalculate Outstanding Principal: Daily, Frequency Interval for recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_PMT_ALLOC_1)
|
||||
String name46 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_PMT_ALLOC_1
|
||||
.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPreclosePmtAlloc1 = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name46)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocationPenFeeIntPrincipal("DEFAULT", "NEXT_INSTALLMENT"), //
|
||||
createPaymentAllocationPenFeeIntPrincipal("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
|
||||
createPaymentAllocationPenFeeIntPrincipal("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
|
||||
createPaymentAllocationPenFeeIntPrincipal("PAYOUT_REFUND", "NEXT_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillPreCloesePmtAlloc1 = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPreclosePmtAlloc1).execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_PMT_ALLOC_1,
|
||||
responseLoanProductsRequestLP2AdvancedpaymentInterest36030InterestRecalcDailyTillPreCloesePmtAlloc1);
|
||||
|
||||
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30, LAST INSTALLMENT strategy
|
||||
// + interest recalculation, preClosureInterestCalculationStrategy= till preclose,
|
||||
// interestRecalculationCompoundingMethod = none
|
||||
// Frequency for recalculate Outstanding Principal: Daily, Frequency Interval for recalculation: 1
|
||||
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY)
|
||||
String name47 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY
|
||||
.getName();
|
||||
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseLastInstallment = loanProductsRequestFactory
|
||||
.defaultLoanProductsRequestLP2Emi()//
|
||||
.name(name47)//
|
||||
.daysInYearType(DaysInYearType.DAYS360.value)//
|
||||
.daysInMonthType(DaysInMonthType.DAYS30.value)//
|
||||
.isInterestRecalculationEnabled(true)//
|
||||
.preClosureInterestCalculationStrategy(1)//
|
||||
.rescheduleStrategyMethod(4)//
|
||||
.interestRecalculationCompoundingMethod(0)//
|
||||
.recalculationRestFrequencyType(2)//
|
||||
.recalculationRestFrequencyInterval(1)//
|
||||
.paymentAllocation(List.of(//
|
||||
createPaymentAllocation("DEFAULT", "LAST_INSTALLMENT")));//
|
||||
Response<PostLoanProductsResponse> loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseLastInstallmentResponse = loanProductsApi
|
||||
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseLastInstallment)
|
||||
.execute();
|
||||
TestContext.INSTANCE.set(
|
||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT,
|
||||
loanProductsRequestLP2AdvancedpaymentInterestEmi36030InterestRecalcDailyTillPrecloseLastInstallmentResponse);
|
||||
}
|
||||
|
||||
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
||||
@@ -634,6 +1022,46 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
return advancedPaymentData;
|
||||
}
|
||||
|
||||
public static AdvancedPaymentData createPaymentAllocationPenFeeIntPrincipal(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_INTEREST, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PENALTY, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_FEE, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_INTEREST, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_INTEREST, //
|
||||
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL);//
|
||||
} else {
|
||||
paymentAllocationOrders = getPaymentAllocationOrder(rules);
|
||||
}
|
||||
|
||||
advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
|
||||
|
||||
return advancedPaymentData;
|
||||
}
|
||||
|
||||
public static AdvancedPaymentData editPaymentAllocationFutureInstallment(String transactionType, String futureInstallmentAllocationRule,
|
||||
List<PaymentAllocationOrder> paymentAllocationOrder) {
|
||||
AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
|
||||
advancedPaymentData.setTransactionType(transactionType);
|
||||
advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule);
|
||||
advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrder);
|
||||
|
||||
return advancedPaymentData;
|
||||
}
|
||||
|
||||
private static CreditAllocationData createCreditAllocation(String transactionType, List<String> creditAllocationRules) {
|
||||
CreditAllocationData creditAllocationData = new CreditAllocationData();
|
||||
creditAllocationData.setTransactionType(transactionType);
|
||||
|
||||
+53
@@ -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.initializer.global;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class SavingsProductGlobalInitializer implements FineractGlobalInitializerStep {
|
||||
|
||||
@Override
|
||||
public void initialize() throws Exception {
|
||||
/**
|
||||
* TODO uncomment and check when PS-1088 is done
|
||||
*/
|
||||
// //EUR
|
||||
// PostSavingsProductsRequest savingsProductsRequestEUR =
|
||||
// SavingsProductRequestFactory.defaultSavingsProductRequest();
|
||||
//
|
||||
// Response<PostSavingsProductsResponse> savingsProductsResponseEUR =
|
||||
// savingsProductApi.create13(savingsProductsRequestEUR).execute();
|
||||
// testContext().set(TestContextKey.DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_EUR, savingsProductsResponseEUR);
|
||||
//
|
||||
// //USD
|
||||
// PostSavingsProductsRequest savingsProductsRequestUSD =
|
||||
// SavingsProductRequestFactory.defaultSavingsProductRequest()
|
||||
// .name("CUSD")
|
||||
// .shortName("CUS")
|
||||
// .currencyCode("USD");
|
||||
//
|
||||
// Response<PostSavingsProductsResponse> savingsProductsResponseUSD =
|
||||
// savingsProductApi.create13(savingsProductsRequestUSD).execute();
|
||||
// testContext().set(TestContextKey.DEFAULT_SAVINGS_PRODUCT_CREATE_RESPONSE_USD, savingsProductsResponseUSD);
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -21,6 +21,6 @@ package org.apache.fineract.test.messaging;
|
||||
public class EmptyEventMessage extends EventMessage<Object> {
|
||||
|
||||
public EmptyEventMessage() {
|
||||
super(null, null, null);
|
||||
super(null, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -21,13 +21,13 @@ package org.apache.fineract.test.messaging;
|
||||
import static java.lang.String.format;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.util.function.Function;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.test.messaging.config.EventProperties;
|
||||
import org.apache.fineract.test.messaging.event.Event;
|
||||
import org.apache.fineract.test.messaging.event.EventFactory;
|
||||
@@ -39,7 +39,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
@SuppressFBWarnings({ "VA_FORMAT_STRING_USES_NEWLINE" })
|
||||
@Slf4j
|
||||
public class EventAssertion {
|
||||
|
||||
private final EventStore eventStore;
|
||||
@@ -85,11 +85,8 @@ public class EventAssertion {
|
||||
|
||||
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));
|
||||
Assertions.fail("%s has been received, but it was unexpected. Events received but not verified: %s", event.getEventName(),
|
||||
receivedEventsLogParam);
|
||||
} catch (ConditionTimeoutException e) {
|
||||
// This is the expected outcome here!
|
||||
}
|
||||
@@ -104,6 +101,7 @@ public class EventAssertion {
|
||||
} else {
|
||||
eventMessage = (EventMessage<R>) new EmptyEventMessage();
|
||||
}
|
||||
log.info("Assert event: {}", eventMessage.getIdempotencyKey());
|
||||
return new EventAssertionBuilder<>(eventMessage);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -29,4 +29,5 @@ public class EventMessage<T> {
|
||||
private final String type;
|
||||
private final LocalDate businessDate;
|
||||
private final T data;
|
||||
private final String idempotencyKey;
|
||||
}
|
||||
|
||||
+114
-33
@@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -55,15 +56,21 @@ import org.apache.fineract.test.messaging.event.assetexternalization.LoanAccount
|
||||
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.AbstractLoanEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanApprovedEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent;
|
||||
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.LoanRejectedEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanStatusChangedEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanUndoApprovalEvent;
|
||||
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.LoanTransactionInterestPaymentWaiverPostEvent;
|
||||
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;
|
||||
@@ -111,22 +118,21 @@ public class EventCheckHelper {
|
||||
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, "", "", "")
|
||||
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(createLoanResponse.body().getLoanId(), false, "all", "", "")
|
||||
.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())
|
||||
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(loanAccountDataV1 -> loanAccountDataV1.getPrincipal().longValue())
|
||||
.isEqualTo(body.getPrincipal().longValue())//
|
||||
.extractingData(loanAccountDataV1 -> loanAccountDataV1.getSummary().getCurrency().getCode())
|
||||
.isEqualTo(body.getCurrency().getCode());
|
||||
.isEqualTo(body.getCurrency().getCode());//
|
||||
}
|
||||
|
||||
public void approveLoanEventCheck(Response<PostLoansLoanIdResponse> loanApproveResponse) throws IOException {
|
||||
@@ -134,37 +140,111 @@ public class EventCheckHelper {
|
||||
.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())//
|
||||
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.getSummary().getPrincipalDisbursed().longValue())
|
||||
.isEqualTo(body.getSummary().getPrincipalDisbursed().longValue())//
|
||||
.extractingData(loanAccountDataV1 -> loanAccountDataV1.getTimeline().getActualDisbursementDate())
|
||||
.isEqualTo(FORMATTER_EVENTS.format(body.getTimeline().getActualDisbursementDate()))
|
||||
.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 undoApproveLoanEventCheck(Response<PostLoansLoanIdResponse> loanUndoApproveResponse) throws IOException {
|
||||
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanUndoApproveResponse.body().getLoanId(), false, "", "", "")
|
||||
.execute();
|
||||
GetLoansLoanIdResponse body = loanDetails.body();
|
||||
|
||||
eventAssertion.assertEventRaised(LoanUndoApprovalEvent.class, body.getId());
|
||||
}
|
||||
|
||||
public void loanRejectedEventCheck(Response<PostLoansLoanIdResponse> loanRejectedResponse) throws IOException {
|
||||
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanRejectedResponse.body().getLoanId(), false, "", "", "")
|
||||
.execute();
|
||||
GetLoansLoanIdResponse body = loanDetails.body();
|
||||
|
||||
eventAssertion.assertEventRaised(LoanRejectedEvent.class, body.getId());
|
||||
}
|
||||
|
||||
public void disburseLoanEventCheck(Long loanId) throws IOException {
|
||||
loanAccountDataV1Check(LoanDisbursalEvent.class, loanId);
|
||||
}
|
||||
|
||||
public void loanBalanceChangedEventCheck(Long loanId) throws IOException {
|
||||
loanAccountDataV1Check(LoanBalanceChangedEvent.class, loanId);
|
||||
}
|
||||
|
||||
public void loanStatusChangedEventCheck(Long loanId) throws IOException {
|
||||
loanAccountDataV1Check(LoanStatusChangedEvent.class, loanId);
|
||||
}
|
||||
|
||||
private void loanAccountDataV1Check(Class<? extends AbstractLoanEvent> eventClazz, Long loanId) throws IOException {
|
||||
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "all", "", "").execute();
|
||||
GetLoansLoanIdResponse body = loanDetails.body();
|
||||
|
||||
eventAssertion.assertEvent(eventClazz, loanId)//
|
||||
.extractingData(loanAccountDataV1 -> {
|
||||
Long idActual = loanAccountDataV1.getId();
|
||||
Long idExpected = body.getId();
|
||||
Integer statusIdActual = loanAccountDataV1.getStatus().getId();
|
||||
Integer statusIdExpected = body.getStatus().getId();
|
||||
String statusCodeActual = loanAccountDataV1.getStatus().getCode();
|
||||
String statusCodeExpected = body.getStatus().getCode();
|
||||
Long clientIdActual = loanAccountDataV1.getClientId();
|
||||
Long clientIdExpected = body.getClientId();
|
||||
BigDecimal principalDisbursedActual = loanAccountDataV1.getSummary().getPrincipalDisbursed();
|
||||
Double principalDisbursedExpectedDouble = body.getSummary().getPrincipalDisbursed();
|
||||
BigDecimal principalDisbursedExpected = new BigDecimal(principalDisbursedExpectedDouble, MathContext.DECIMAL64);
|
||||
String actualDisbursementDateActual = loanAccountDataV1.getTimeline().getActualDisbursementDate();
|
||||
String actualDisbursementDateExpected = FORMATTER_EVENTS.format(body.getTimeline().getActualDisbursementDate());
|
||||
String currencyCodeActual = loanAccountDataV1.getSummary().getCurrency().getCode();
|
||||
String currencyCodeExpected = body.getSummary().getCurrency().getCode();
|
||||
BigDecimal totalUnpaidPayableDueInterestActual = loanAccountDataV1.getSummary().getTotalUnpaidPayableDueInterest();
|
||||
BigDecimal totalUnpaidPayableDueInterestExpected = body.getSummary().getTotalUnpaidPayableDueInterest();
|
||||
BigDecimal totalUnpaidPayableNotDueInterestActual = loanAccountDataV1.getSummary()
|
||||
.getTotalUnpaidPayableNotDueInterest();
|
||||
BigDecimal totalUnpaidPayableNotDueInterestExpected = body.getSummary().getTotalUnpaidPayableNotDueInterest();
|
||||
BigDecimal totalInterestPaymentWaiverActual = loanAccountDataV1.getSummary().getTotalInterestPaymentWaiver();
|
||||
Double totalInterestPaymentWaiverExpectedDouble = body.getSummary().getTotalInterestPaymentWaiver();
|
||||
BigDecimal totalInterestPaymentWaiverExpected = new BigDecimal(totalInterestPaymentWaiverExpectedDouble,
|
||||
MathContext.DECIMAL64);
|
||||
BigDecimal delinquentInterestActual = loanAccountDataV1.getDelinquent().getDelinquentInterest();
|
||||
BigDecimal delinquentInterestExpected = body.getDelinquent().getDelinquentInterest();
|
||||
BigDecimal delinquentFeeActual = loanAccountDataV1.getDelinquent().getDelinquentFee();
|
||||
BigDecimal delinquentFeeExpected = body.getDelinquent().getDelinquentFee();
|
||||
BigDecimal delinquentPenaltyActual = loanAccountDataV1.getDelinquent().getDelinquentPenalty();
|
||||
BigDecimal delinquentPenaltyExpected = body.getDelinquent().getDelinquentPenalty();
|
||||
|
||||
assertThat(idActual).isEqualTo(idExpected);
|
||||
assertThat(statusIdActual).isEqualTo(statusIdExpected);
|
||||
assertThat(statusCodeActual).isEqualTo(statusCodeExpected);
|
||||
assertThat(clientIdActual).isEqualTo(clientIdExpected);
|
||||
assertThat(areBigDecimalValuesEqual(principalDisbursedActual, principalDisbursedExpected)).isTrue();
|
||||
assertThat(actualDisbursementDateActual).isEqualTo(actualDisbursementDateExpected);
|
||||
assertThat(currencyCodeActual).isEqualTo(currencyCodeExpected);
|
||||
assertThat(areBigDecimalValuesEqual(totalUnpaidPayableDueInterestActual, totalUnpaidPayableDueInterestExpected))
|
||||
.isTrue();
|
||||
assertThat(areBigDecimalValuesEqual(totalUnpaidPayableNotDueInterestActual, totalUnpaidPayableNotDueInterestExpected))
|
||||
.isTrue();
|
||||
assertThat(areBigDecimalValuesEqual(totalInterestPaymentWaiverActual, totalInterestPaymentWaiverExpected)).isTrue();
|
||||
assertThat(areBigDecimalValuesEqual(delinquentInterestActual, delinquentInterestExpected)).isTrue();
|
||||
assertThat(areBigDecimalValuesEqual(delinquentFeeActual, delinquentFeeExpected)).isTrue();
|
||||
assertThat(areBigDecimalValuesEqual(delinquentPenaltyActual, delinquentPenaltyExpected)).isTrue();
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private boolean areBigDecimalValuesEqual(BigDecimal actual, BigDecimal expected) {
|
||||
log.info("--- Checking BigDecimal values.... ---");
|
||||
log.info("Actual: {}", actual);
|
||||
log.info("Expected: {}", expected);
|
||||
return actual.compareTo(expected) == 0;
|
||||
}
|
||||
|
||||
public void loanDisbursalTransactionEventCheck(Response<PostLoansLoanIdResponse> loanDisburseResponse) throws IOException {
|
||||
Long disbursementTransactionId = loanDisburseResponse.body().getSubResourceId();
|
||||
|
||||
@@ -204,6 +284,7 @@ public class EventCheckHelper {
|
||||
case PAYOUT_REFUND -> LoanTransactionPayoutRefundPostEvent.class;
|
||||
case MERCHANT_ISSUED_REFUND -> LoanTransactionMerchantIssuedRefundPostEvent.class;
|
||||
case REFUND_BY_CASH -> LoanRefundPostBusinessEvent.class;
|
||||
case INTEREST_PAYMENT_WAIVER -> LoanTransactionInterestPaymentWaiverPostEvent.class;
|
||||
default -> throw new IllegalStateException(String.format("transaction type %s cannot be found", transactionType.getValue()));
|
||||
};
|
||||
|
||||
@@ -404,6 +485,6 @@ public class EventCheckHelper {
|
||||
}
|
||||
|
||||
private BigDecimal zeroConversion(BigDecimal input) {
|
||||
return input.compareTo(BigDecimal.ZERO) == 0 ? new BigDecimal(input.toEngineeringString()) : input.setScale(8);
|
||||
return input.compareTo(new BigDecimal("0.000000")) == 0 ? new BigDecimal(input.toEngineeringString()) : input.setScale(8);
|
||||
}
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.messaging.event.loan;
|
||||
|
||||
public class LoanRejectedEvent extends AbstractLoanEvent {
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "LoanRejectedBusinessEvent";
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.messaging.event.loan;
|
||||
|
||||
public class LoanUndoApprovalEvent extends AbstractLoanEvent {
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "LoanUndoApprovalBusinessEvent";
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.messaging.event.loan.transaction;
|
||||
|
||||
public class LoanTransactionAccrualActivityPostEvent extends AbstractLoanTransactionEvent {
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "LoanTransactionAccrualActivityPostBusinessEvent";
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.messaging.event.loan.transaction;
|
||||
|
||||
public class LoanTransactionInterestPaymentWaiverPostEvent extends AbstractLoanTransactionEvent {
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "LoanTransactionInterestPaymentWaiverPostBusinessEvent";
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -71,20 +71,21 @@ public class EventStore {
|
||||
void receive(byte[] message) throws Exception {
|
||||
MessageV1 msgObject = MessageV1.fromByteBuffer(ByteBuffer.wrap(message));
|
||||
String type = msgObject.getType();
|
||||
String idempotencyKey = msgObject.getIdempotencyKey();
|
||||
LocalDate businessDate = LocalDate.parse(msgObject.getBusinessDate(), DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
Object dataObject = getDataObject(msgObject);
|
||||
if (BULK_BUSINESS_EVENT_TYPE.equals(type)) {
|
||||
BulkMessagePayloadV1 bulkPayload = (BulkMessagePayloadV1) dataObject;
|
||||
List<EventMessage<Object>> bulkEvents = bulkPayload.getDatas().stream()
|
||||
.map((BulkMessageItemV1 item) -> getEventMessageFromBulkItem(item, businessDate)).toList();
|
||||
.map((BulkMessageItemV1 item) -> getEventMessageFromBulkItem(item, businessDate, idempotencyKey)).toList();
|
||||
if (log.isDebugEnabled()) {
|
||||
bulkEvents.forEach(msg -> {
|
||||
log.debug("Received event {}", new LoggedEvent(msg));
|
||||
log.debug("Received Bulk event {}", new LoggedEvent(msg));
|
||||
});
|
||||
}
|
||||
receivedEvents.addAll(bulkEvents);
|
||||
} else {
|
||||
EventMessage<Object> msg = new EventMessage<>(type, businessDate, dataObject);
|
||||
EventMessage<Object> msg = new EventMessage<>(type, businessDate, dataObject, idempotencyKey);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Received event {}", new LoggedEvent(msg));
|
||||
}
|
||||
@@ -93,12 +94,12 @@ public class EventStore {
|
||||
log.trace("Data object within event {}", dataObject);
|
||||
}
|
||||
|
||||
private EventMessage<Object> getEventMessageFromBulkItem(BulkMessageItemV1 item, LocalDate businessDate) {
|
||||
private EventMessage<Object> getEventMessageFromBulkItem(BulkMessageItemV1 item, LocalDate businessDate, String idempotencyKey) {
|
||||
try {
|
||||
String dataschema = item.getDataschema();
|
||||
ByteBuffer data = item.getData();
|
||||
Object deserialized = deserialize(dataschema, data);
|
||||
return new EventMessage<>(item.getType(), businessDate, deserialized);
|
||||
return new EventMessage<>(item.getType(), businessDate, deserialized, idempotencyKey);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
+3
-1
@@ -25,15 +25,17 @@ public class LoggedEvent {
|
||||
|
||||
private final String type;
|
||||
private final String businessDate;
|
||||
private final String idempotencyKey;
|
||||
|
||||
public LoggedEvent(EventMessage<?> message) {
|
||||
this.type = message.getType();
|
||||
this.businessDate = DateTimeFormatter.ISO_LOCAL_DATE.format(message.getBusinessDate());
|
||||
this.idempotencyKey = message.getIdempotencyKey();
|
||||
}
|
||||
|
||||
// Don't use Lombok @ToString since the class name isn't included in the msg
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + "type='" + type + '\'' + ", businessDate='" + businessDate + '\'' + '}';
|
||||
return "{" + "idempotencyKey='" + idempotencyKey + '\'' + ", type='" + type + "', businessDate='" + businessDate + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -27,7 +27,6 @@ import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@@ -75,6 +74,7 @@ import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
import org.apache.fineract.test.helper.ErrorResponse;
|
||||
import org.apache.fineract.test.helper.Utils;
|
||||
import org.apache.fineract.test.messaging.EventAssertion;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanRescheduledDueAdjustScheduleEvent;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
@@ -175,7 +175,7 @@ public class BatchApiStepDef extends AbstractStepDef {
|
||||
|
||||
// request 3 - charge Loan
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
String dateOfCharge = formatter.format(LocalDate.now(Clock.systemUTC()).minusMonths(1L).plusDays(1L));
|
||||
String dateOfCharge = formatter.format(Utils.now().minusMonths(1L).plusDays(1L));
|
||||
|
||||
PostLoansLoanIdChargesRequest loanIdChargesRequest = new PostLoansLoanIdChargesRequest();
|
||||
loanIdChargesRequest.chargeId(CHARGE_ID_NFS_FEE);
|
||||
@@ -448,11 +448,11 @@ public class BatchApiStepDef extends AbstractStepDef {
|
||||
testContext().set(TestContextKey.BATCH_API_CALL_RESPONSE, batchResponseList);
|
||||
testContext().set(TestContextKey.BATCH_API_CALL_IDEMPOTENCY_KEY, idempotencyKey);
|
||||
eventAssertion.assertEvent(LoanRescheduledDueAdjustScheduleEvent.class, loanId).extractingData(loanAccountDataV1 -> {
|
||||
Optional<LoanSchedulePeriodDataV1> period = loanAccountDataV1.getRepaymentSchedule().getPeriods().stream()
|
||||
.filter(p -> formatter.format(LocalDate.parse(p.getDueDate())).equals(toDateStr)).findFirst();
|
||||
LoanSchedulePeriodDataV1 period = loanAccountDataV1.getRepaymentSchedule().getPeriods().stream()
|
||||
.filter(p -> formatter.format(LocalDate.parse(p.getDueDate())).equals(toDateStr)).findFirst().orElse(null);
|
||||
String dueDate = "";
|
||||
if (period.isPresent()) {
|
||||
dueDate = formatter.format(LocalDate.parse(period.get().getDueDate()));
|
||||
if (period != null) {
|
||||
dueDate = formatter.format(LocalDate.parse(period.getDueDate()));
|
||||
}
|
||||
assertThat(dueDate).as(ErrorMessageHelper.wrongDataInLastPaymentAmount(dueDate, toDateStr)).isEqualTo(toDateStr);
|
||||
return null;
|
||||
|
||||
+53
-84
@@ -30,8 +30,11 @@ import org.apache.fineract.client.models.BusinessStep;
|
||||
import org.apache.fineract.client.models.GetBusinessStepConfigResponse;
|
||||
import org.apache.fineract.client.models.UpdateBusinessStepConfigRequest;
|
||||
import org.apache.fineract.client.services.BusinessStepConfigurationApi;
|
||||
import org.apache.fineract.test.data.CobBusinessStep;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContext;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import retrofit2.Response;
|
||||
|
||||
@@ -47,28 +50,20 @@ public class BusinessStepStepDef extends AbstractStepDef {
|
||||
private static final String BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES = "ADD_PERIODIC_ACCRUAL_ENTRIES";
|
||||
private static final String BUSINESS_STEP_NAME_EXTERNAL_ASSET_OWNER_TRANSFER = "EXTERNAL_ASSET_OWNER_TRANSFER";
|
||||
private static final String BUSINESS_STEP_NAME_CHECK_DUE_INSTALLMENTS = "CHECK_DUE_INSTALLMENTS";
|
||||
private static final String BUSINESS_STEP_NAME_ACCRUAL_ACTIVITY_POSTING = "ACCRUAL_ACTIVITY_POSTING";
|
||||
private static final List<BusinessStep> ORIGINAL_COB_BUSINESS_STEPS = TestContext.GLOBAL
|
||||
.get(TestContextKey.ORIGINAL_COB_WORKFLOW_JOB_BUSINESS_STEP_LIST);
|
||||
|
||||
@Autowired
|
||||
private BusinessStepConfigurationApi businessStepConfigurationApi;
|
||||
|
||||
@Given("Admin puts EXTERNAL_ASSET_OWNER_TRANSFER job into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void putExternalAssetOwnerTransferJobInCOB() throws IOException {
|
||||
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||
.order(2L);
|
||||
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||
BusinessStep externalAssetOwnerTransfer = new BusinessStep().stepName(BUSINESS_STEP_NAME_EXTERNAL_ASSET_OWNER_TRANSFER).order(7L);
|
||||
List<BusinessStep> businessSteps = new ArrayList<>(ORIGINAL_COB_BUSINESS_STEPS);
|
||||
Long lastOrder = businessSteps.get(businessSteps.size() - 1).getOrder();
|
||||
|
||||
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||
businessSteps.add(applyChargeToOverdueLoans);
|
||||
businessSteps.add(loanDelinquencyClassification);
|
||||
businessSteps.add(checkLoanRepaymentDue);
|
||||
businessSteps.add(checkLoanRepaymentOverdue);
|
||||
businessSteps.add(updateLoanArrearsAging);
|
||||
businessSteps.add(addPeriodicAccrualEntries);
|
||||
BusinessStep externalAssetOwnerTransfer = new BusinessStep().stepName(BUSINESS_STEP_NAME_EXTERNAL_ASSET_OWNER_TRANSFER)
|
||||
.order(lastOrder + 1);
|
||||
businessSteps.add(externalAssetOwnerTransfer);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
@@ -76,51 +71,22 @@ public class BusinessStepStepDef extends AbstractStepDef {
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
// --- log changes ---
|
||||
logChanges();
|
||||
}
|
||||
|
||||
@Then("Admin removes EXTERNAL_ASSET_OWNER_TRANSFER job from LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void removeExternalAssetOwnerTransferJobInCOB() throws IOException {
|
||||
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||
.order(2L);
|
||||
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||
|
||||
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||
businessSteps.add(applyChargeToOverdueLoans);
|
||||
businessSteps.add(loanDelinquencyClassification);
|
||||
businessSteps.add(checkLoanRepaymentDue);
|
||||
businessSteps.add(checkLoanRepaymentOverdue);
|
||||
businessSteps.add(updateLoanArrearsAging);
|
||||
businessSteps.add(addPeriodicAccrualEntries);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
setBackBusinessStepsToOriginal();
|
||||
}
|
||||
|
||||
@Given("Admin puts CHECK_DUE_INSTALLMENTS job into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void putCheckDueInstallmentsJobInCOB() throws IOException {
|
||||
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||
.order(2L);
|
||||
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||
BusinessStep checkDueInstallments = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_DUE_INSTALLMENTS).order(7L);
|
||||
List<BusinessStep> businessSteps = new ArrayList<>(ORIGINAL_COB_BUSINESS_STEPS);
|
||||
Long lastOrder = businessSteps.get(businessSteps.size() - 1).getOrder();
|
||||
|
||||
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||
businessSteps.add(applyChargeToOverdueLoans);
|
||||
businessSteps.add(loanDelinquencyClassification);
|
||||
businessSteps.add(checkLoanRepaymentDue);
|
||||
businessSteps.add(checkLoanRepaymentOverdue);
|
||||
businessSteps.add(updateLoanArrearsAging);
|
||||
businessSteps.add(addPeriodicAccrualEntries);
|
||||
BusinessStep checkDueInstallments = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_DUE_INSTALLMENTS).order(lastOrder + 1);
|
||||
businessSteps.add(checkDueInstallments);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
@@ -128,68 +94,71 @@ public class BusinessStepStepDef extends AbstractStepDef {
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
// --- log changes ---
|
||||
logChanges();
|
||||
}
|
||||
|
||||
@Then("Admin removes CHECK_DUE_INSTALLMENTS job from LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void removeCheckDueInstallmentsJobInCOB() throws IOException {
|
||||
BusinessStep applyChargeToOverdueLoans = new BusinessStep().stepName(BUSINESS_STEP_NAME_APPLY_CHARGE_TO_OVERDUE_LOANS).order(1L);
|
||||
BusinessStep loanDelinquencyClassification = new BusinessStep().stepName(BUSINESS_STEP_NAME_LOAN_DELINQUENCY_CLASSIFICATION)
|
||||
.order(2L);
|
||||
BusinessStep checkLoanRepaymentDue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_DUE).order(3L);
|
||||
BusinessStep checkLoanRepaymentOverdue = new BusinessStep().stepName(BUSINESS_STEP_NAME_CHECK_LOAN_REPAYMENT_OVERDUE).order(4L);
|
||||
BusinessStep updateLoanArrearsAging = new BusinessStep().stepName(BUSINESS_STEP_NAME_UPDATE_LOAN_ARREARS_AGING).order(5L);
|
||||
BusinessStep addPeriodicAccrualEntries = new BusinessStep().stepName(BUSINESS_STEP_NAME_ADD_PERIODIC_ACCRUAL_ENTRIES).order(6L);
|
||||
|
||||
List<BusinessStep> businessSteps = new ArrayList<>();
|
||||
businessSteps.add(applyChargeToOverdueLoans);
|
||||
businessSteps.add(loanDelinquencyClassification);
|
||||
businessSteps.add(checkLoanRepaymentDue);
|
||||
businessSteps.add(checkLoanRepaymentOverdue);
|
||||
businessSteps.add(updateLoanArrearsAging);
|
||||
businessSteps.add(addPeriodicAccrualEntries);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
setBackBusinessStepsToOriginal();
|
||||
}
|
||||
|
||||
@Given("Admin puts {string} business step into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void putGivenJobInCOB(String businessStepName) throws IOException {
|
||||
List<BusinessStep> businessSteps = retrieveLoanCOBJobSteps();
|
||||
if (businessSteps.stream().anyMatch(businessStep -> businessStep.getStepName().equals(businessStepName))) {
|
||||
return;
|
||||
}
|
||||
List<BusinessStep> businessSteps = new ArrayList<>(ORIGINAL_COB_BUSINESS_STEPS);
|
||||
Long lastOrder = businessSteps.get(businessSteps.size() - 1).getOrder();
|
||||
|
||||
businessSteps.add(new BusinessStep().stepName(businessStepName).order((long) (1 + businessSteps.size())));
|
||||
CobBusinessStep cobBusinessStep = CobBusinessStep.valueOf(businessStepName);
|
||||
String stepName = cobBusinessStep.getValue();
|
||||
|
||||
BusinessStep businessStepToAdd = new BusinessStep().stepName(stepName).order(lastOrder + 1);
|
||||
businessSteps.add(businessStepToAdd);
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
// --- log changes ---
|
||||
logChanges();
|
||||
}
|
||||
|
||||
@Then("Admin sets back LOAN_CLOSE_OF_BUSINESS workflow to its initial state")
|
||||
public void setBackCOBToInitialState() throws IOException {
|
||||
setBackBusinessStepsToOriginal();
|
||||
}
|
||||
|
||||
@Then("Admin removes {string} business step into LOAN_CLOSE_OF_BUSINESS workflow")
|
||||
public void removeGivenJobInCOB(String businessStepName) throws IOException {
|
||||
List<BusinessStep> businessSteps = retrieveLoanCOBJobSteps();
|
||||
businessSteps.removeIf(businessStep -> businessStep.getStepName().equals(businessStepName));
|
||||
List<BusinessStep> businessSteps = new ArrayList<>(ORIGINAL_COB_BUSINESS_STEPS);
|
||||
|
||||
CobBusinessStep cobBusinessStep = CobBusinessStep.valueOf(businessStepName);
|
||||
String stepName = cobBusinessStep.getValue();
|
||||
|
||||
businessSteps.removeIf(businessStep -> businessStep.getStepName().equals(stepName));
|
||||
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
// --- log changes ---
|
||||
logChanges();
|
||||
}
|
||||
|
||||
private List<BusinessStep> retrieveLoanCOBJobSteps() throws IOException {
|
||||
Response<GetBusinessStepConfigResponse> businessStepConfigResponse = businessStepConfigurationApi
|
||||
.retrieveAllConfiguredBusinessStep(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS).execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(businessStepConfigResponse);
|
||||
return businessStepConfigResponse.body().getBusinessSteps();
|
||||
private void setBackBusinessStepsToOriginal() throws IOException {
|
||||
log.info("Setting back Business steps to original...");
|
||||
UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(ORIGINAL_COB_BUSINESS_STEPS);
|
||||
|
||||
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request)
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
// --- log changes ---
|
||||
logChanges();
|
||||
}
|
||||
|
||||
private void logChanges() throws IOException {
|
||||
|
||||
+9
@@ -21,6 +21,7 @@ package org.apache.fineract.test.stepdef.common;
|
||||
import io.cucumber.java.en.Given;
|
||||
import io.cucumber.java.en.When;
|
||||
import java.io.IOException;
|
||||
import org.apache.fineract.client.services.DefaultApi;
|
||||
import org.apache.fineract.test.helper.GlobalConfigurationHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -28,6 +29,8 @@ public class GlobalConfigurationStepDef {
|
||||
|
||||
@Autowired
|
||||
private GlobalConfigurationHelper globalConfigurationHelper;
|
||||
@Autowired
|
||||
private DefaultApi defaultApi;
|
||||
|
||||
@Given("Global configuration {string} is disabled")
|
||||
public void disableGlobalConfiguration(String configKey) throws IOException {
|
||||
@@ -42,6 +45,12 @@ public class GlobalConfigurationStepDef {
|
||||
@When("Global config {string} value set to {string}")
|
||||
public void setGlobalConfigValueString(String configKey, String configValue) throws IOException {
|
||||
globalConfigurationHelper.setGlobalConfigValueString(configKey, configValue);
|
||||
}
|
||||
|
||||
@When("Global config {string} value set to {string} through DefaultApi")
|
||||
public void setGlobalConfigValueStringDefaultApi(String configKey, String configValue) throws IOException {
|
||||
Long configValueLong = Long.valueOf(configValue);
|
||||
defaultApi.updateGlobalConfiguration(configKey, configValueLong);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -67,7 +67,6 @@ public class JournalEntriesStepDef extends AbstractStepDef {
|
||||
String transactionTypeExpected = transactionType1.getValue();
|
||||
|
||||
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
|
||||
List<GetLoansLoanIdTransactions> transactionsMatch = transactions.stream()
|
||||
.filter(t -> transactionDate.equals(formatter.format(t.getDate()))
|
||||
&& transactionTypeExpected.equals(t.getType().getCode().substring(20)))
|
||||
|
||||
+5
@@ -56,4 +56,9 @@ public class SchedulerStepDef extends AbstractStepDef {
|
||||
public void runCOB() {
|
||||
jobService.executeAndWait(DefaultJob.LOAN_COB);
|
||||
}
|
||||
|
||||
@When("Admin runs the Accrual Activity Posting job")
|
||||
public void runAccrualActivityPosting() {
|
||||
jobService.executeAndWait(DefaultJob.ACCRUAL_ACTIVITY_POSTING);
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -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.stepdef.hook;
|
||||
|
||||
import io.cucumber.java.After;
|
||||
import io.cucumber.java.Scenario;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.test.testrail.TestRailClient;
|
||||
import org.apache.fineract.test.testrail.TestRailProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
@Slf4j
|
||||
public class TestRailLifecycleHook {
|
||||
|
||||
@Autowired
|
||||
private TestRailProperties testRailProperties;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void tearDown(Scenario scenario) {
|
||||
if (testRailProperties.isEnabled()) {
|
||||
TestRailClient testRailClient = applicationContext.getBean(TestRailClient.class);
|
||||
testRailClient.saveScenarioResult(scenario);
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-3
@@ -21,12 +21,14 @@ package org.apache.fineract.test.stepdef.loan;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.models.BusinessDateResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||
@@ -46,11 +48,14 @@ import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
import org.apache.fineract.test.helper.ErrorResponse;
|
||||
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||
import org.apache.fineract.test.messaging.store.EventStore;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import retrofit2.Response;
|
||||
|
||||
@Slf4j
|
||||
public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
|
||||
public static final String DATE_FORMAT = "dd MMMM yyyy";
|
||||
@@ -65,6 +70,10 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
private LoanTransactionsApi loanTransactionsApi;
|
||||
@Autowired
|
||||
private BusinessDateManagementApi businessDateManagementApi;
|
||||
@Autowired
|
||||
private EventCheckHelper eventCheckHelper;
|
||||
@Autowired
|
||||
private EventStore eventStore;
|
||||
|
||||
@When("Admin makes a charge adjustment for the last {string} type charge which is due on {string} with {double} EUR transaction amount and externalId {string}")
|
||||
public void makeLoanChargeAdjustment(String chargeTypeEnum, String date, Double transactionAmount, String externalId)
|
||||
@@ -79,8 +88,8 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
makeChargeAdjustmentCall(loanId, transactionId, externalId, transactionAmount);
|
||||
}
|
||||
|
||||
@When("Admin makes a charge adjustment for the last {string} type charge which is due on {string} with transaction amount higher than the available charge amount")
|
||||
public void loanChargeAdjustmentFailedOnWrongAmount(String chargeTypeEnum, String date) throws IOException {
|
||||
@Then("Charge adjustment for the last {string} type charge which is due on {string} with transaction amount {double} which is higher than the available charge amount results an ERROR")
|
||||
public void loanChargeAdjustmentFailedOnWrongAmount(String chargeTypeEnum, String date, double amount) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -88,7 +97,7 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
|
||||
Long transactionId = getTransactionIdForLastChargeMetConditions(chargeTypeEnum, date, loanDetailsResponse);
|
||||
PostLoansLoanIdChargesChargeIdRequest chargeAdjustmentRequest = LoanRequestFactory.defaultChargeAdjustmentRequest().amount(8.0)
|
||||
PostLoansLoanIdChargesChargeIdRequest chargeAdjustmentRequest = LoanRequestFactory.defaultChargeAdjustmentRequest().amount(amount)
|
||||
.externalId("");
|
||||
|
||||
Response<PostLoansLoanIdChargesChargeIdResponse> chargeAdjustmentResponseFail = loanChargesApi
|
||||
@@ -108,6 +117,9 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
assertThat(developerMessageActual)
|
||||
.as(ErrorMessageHelper.wrongErrorMessageInFailedChargeAdjustment(developerMessageActual, developerMessageExpected))
|
||||
.isEqualTo(developerMessageExpected);
|
||||
|
||||
log.info("Error code: {}", httpStatusCodeActual);
|
||||
log.info("Error message: {}", developerMessageActual);
|
||||
}
|
||||
|
||||
@When("Admin reverts the charge adjustment which was raised on {string} with {double} EUR transaction amount")
|
||||
@@ -153,6 +165,7 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
}
|
||||
|
||||
private void makeChargeAdjustmentCall(Long loanId, Long transactionId, String externalId, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
PostLoansLoanIdChargesChargeIdRequest chargeAdjustmentRequest = LoanRequestFactory.defaultChargeAdjustmentRequest()
|
||||
.amount(transactionAmount).externalId(externalId);
|
||||
|
||||
@@ -160,6 +173,7 @@ public class LoanChargeAdjustmentStepDef extends AbstractStepDef {
|
||||
.executeLoanCharge2(loanId, transactionId, chargeAdjustmentRequest, "adjustment").execute();
|
||||
testContext().set(TestContextKey.LOAN_CHARGE_ADJUSTMENT_RESPONSE, chargeAdjustmentResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(chargeAdjustmentResponse);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
private Long getTransactionIdForLastChargeMetConditions(String chargeTypeEnum, String date,
|
||||
|
||||
+10
-3
@@ -40,8 +40,9 @@ import org.apache.fineract.test.data.paymenttype.PaymentTypeResolver;
|
||||
import org.apache.fineract.test.factory.LoanRequestFactory;
|
||||
import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.messaging.EventAssertion;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent;
|
||||
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargebackTransactionEvent;
|
||||
import org.apache.fineract.test.messaging.store.EventStore;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -61,6 +62,12 @@ public class LoanChargeBackStepDef extends AbstractStepDef {
|
||||
@Autowired
|
||||
private PaymentTypeResolver paymentTypeResolver;
|
||||
|
||||
@Autowired
|
||||
private EventCheckHelper eventCheckHelper;
|
||||
|
||||
@Autowired
|
||||
EventStore eventStore;
|
||||
|
||||
@When("Admin makes {string} chargeback with {double} EUR transaction amount")
|
||||
public void makeLoanChargeback(String repaymentType, double transactionAmount) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
@@ -116,6 +123,7 @@ public class LoanChargeBackStepDef extends AbstractStepDef {
|
||||
}
|
||||
|
||||
private void makeChargebackCall(Long loanId, Long transactionId, String repaymentType, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
DefaultPaymentType paymentType = DefaultPaymentType.valueOf(repaymentType);
|
||||
Long paymentTypeValue = paymentTypeResolver.resolve(paymentType);
|
||||
|
||||
@@ -134,8 +142,7 @@ public class LoanChargeBackStepDef extends AbstractStepDef {
|
||||
PostLoansLoanIdTransactionsResponse responseBody = chargebackResponse.body();
|
||||
Long loanId = responseBody.getLoanId();
|
||||
|
||||
eventAssertion.assertEvent(LoanBalanceChangedEvent.class, loanId).extractingData(data -> data.getId()).isEqualTo(loanId);
|
||||
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
checkLoanChargebackTransactionEvent(responseBody);
|
||||
}
|
||||
|
||||
|
||||
+10
@@ -51,7 +51,9 @@ import org.apache.fineract.test.helper.ErrorHelper;
|
||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
import org.apache.fineract.test.helper.ErrorResponse;
|
||||
import org.apache.fineract.test.messaging.EventAssertion;
|
||||
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||
import org.apache.fineract.test.messaging.event.loan.charge.LoanAddChargeEvent;
|
||||
import org.apache.fineract.test.messaging.store.EventStore;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -73,6 +75,10 @@ public class LoanChargeStepDef extends AbstractStepDef {
|
||||
private LoansApi loansApi;
|
||||
@Autowired
|
||||
private EventAssertion eventAssertion;
|
||||
@Autowired
|
||||
private EventCheckHelper eventCheckHelper;
|
||||
@Autowired
|
||||
private EventStore eventStore;
|
||||
|
||||
@When("Admin adds {string} due date charge with {string} due date and {double} EUR transaction amount")
|
||||
public void addChargeDueDate(String chargeType, String transactionDate, double transactionAmount) throws IOException {
|
||||
@@ -142,6 +148,7 @@ public class LoanChargeStepDef extends AbstractStepDef {
|
||||
|
||||
@And("Admin adds a {double} % Processing charge to the loan with {string} locale on date: {string}")
|
||||
public void addProcessingFee(double chargeAmount, String locale, String date) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest()
|
||||
@@ -152,10 +159,12 @@ public class LoanChargeStepDef extends AbstractStepDef {
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||
testContext().set(TestContextKey.ADD_PROCESSING_FEE_RESPONSE, loanChargeResponse);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Admin adds an NSF fee because of payment bounce with {string} transaction date")
|
||||
public void addNSFfee(String date) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdChargesRequest loanIdChargesRequest = LoanChargeRequestFactory.defaultLoanChargeRequest()
|
||||
@@ -166,6 +175,7 @@ public class LoanChargeStepDef extends AbstractStepDef {
|
||||
.execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanChargeResponse);
|
||||
testContext().set(TestContextKey.ADD_NSF_FEE_RESPONSE, loanChargeResponse);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Admin waives charge")
|
||||
|
||||
+4
-4
@@ -21,7 +21,6 @@ package org.apache.fineract.test.stepdef.loan;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import io.cucumber.datatable.DataTable;
|
||||
import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
@@ -629,7 +628,7 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
|
||||
String expectedDelinquencyRangeValue = expectedDelinquencyRange.getValue();
|
||||
|
||||
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)//
|
||||
.extractingData(loanAccountDelinquencyRangeDataV1 -> { //
|
||||
.extractingData(loanAccountDelinquencyRangeDataV1 -> {
|
||||
String actualDelinquencyRangeValue = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getClassification();//
|
||||
assertThat(actualDelinquencyRangeValue)//
|
||||
.as(ErrorMessageHelper.delinquencyRangeError(actualDelinquencyRangeValue, expectedDelinquencyRangeValue))//
|
||||
@@ -648,7 +647,8 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
|
||||
GetLoansLoanIdDelinquencySummary delinquent = loanDetails.body().getDelinquent();
|
||||
|
||||
eventAssertion.assertEvent(LoanDelinquencyRangeChangeEvent.class, loanId)//
|
||||
.extractingData(loanAccountDelinquencyRangeDataV1 -> { //
|
||||
.extractingData(loanAccountDelinquencyRangeDataV1 -> {
|
||||
|
||||
Long loanLevelDelinquencyRangeId = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getId();
|
||||
String loanLevelDelinquencyRange = loanAccountDelinquencyRangeDataV1.getDelinquencyRange().getClassification();
|
||||
String loanLevelDelinquentDate = loanAccountDelinquencyRangeDataV1.getDelinquentDate();
|
||||
@@ -732,7 +732,6 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
|
||||
log.info("loanDetails.delinquent.lastRepaymentDate: {}", actualLastRepaymentDate);
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
|
||||
private List<String> fetchValuesOfDelinquencyPausePeriods(List<String> header, GetLoansLoanIdDelinquencyPausePeriod t) {
|
||||
List<String> actualValues = new ArrayList<>();
|
||||
for (String headerName : header) {
|
||||
@@ -741,6 +740,7 @@ public class LoanDelinquencyStepDef extends AbstractStepDef {
|
||||
case "pausePeriodStart" ->
|
||||
actualValues.add(t.getPausePeriodStart() == null ? null : FORMATTER.format(t.getPausePeriodStart()));
|
||||
case "pausePeriodEnd" -> actualValues.add(t.getPausePeriodEnd() == null ? null : FORMATTER.format(t.getPausePeriodEnd()));
|
||||
default -> throw new IllegalStateException(String.format("Header name %s cannot be found", headerName));
|
||||
}
|
||||
}
|
||||
return actualValues;
|
||||
|
||||
+12
-4
@@ -57,8 +57,12 @@ public class LoanReAgingStepDef extends AbstractStepDef {
|
||||
String startDate = data.get(2);
|
||||
int numberOfInstallments = Integer.parseInt(data.get(3));
|
||||
|
||||
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory.defaultReAgingRequest().frequencyNumber(frequencyNumber)
|
||||
.frequencyType(frequencyType).startDate(startDate).numberOfInstallments(numberOfInstallments);
|
||||
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory//
|
||||
.defaultReAgingRequest()//
|
||||
.frequencyNumber(frequencyNumber)//
|
||||
.frequencyType(frequencyType)//
|
||||
.startDate(startDate)//
|
||||
.numberOfInstallments(numberOfInstallments);//
|
||||
|
||||
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi.executeLoanTransaction(loanId, reAgingRequest, "reAge")
|
||||
.execute();
|
||||
@@ -77,8 +81,12 @@ public class LoanReAgingStepDef extends AbstractStepDef {
|
||||
String startDate = data.get(2);
|
||||
int numberOfInstallments = Integer.parseInt(data.get(3));
|
||||
|
||||
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory.defaultReAgingRequest().frequencyNumber(frequencyNumber)
|
||||
.frequencyType(frequencyType).startDate(startDate).numberOfInstallments(numberOfInstallments);
|
||||
PostLoansLoanIdTransactionsRequest reAgingRequest = LoanRequestFactory//
|
||||
.defaultReAgingRequest()//
|
||||
.frequencyNumber(frequencyNumber)//
|
||||
.frequencyType(frequencyType)//
|
||||
.startDate(startDate)//
|
||||
.numberOfInstallments(numberOfInstallments);//
|
||||
|
||||
Response<PostLoansLoanIdTransactionsResponse> response = loanTransactionsApi
|
||||
.executeLoanTransaction1(loanExternalId, reAgingRequest, "reAge").execute();
|
||||
|
||||
+37
-17
@@ -61,8 +61,8 @@ import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
import org.apache.fineract.test.helper.ErrorResponse;
|
||||
import org.apache.fineract.test.messaging.EventAssertion;
|
||||
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanBalanceChangedEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanAdjustTransactionBusinessEvent;
|
||||
import org.apache.fineract.test.messaging.store.EventStore;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -77,6 +77,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
public static final String DEFAULT_CHECK_NB = "1234567890";
|
||||
public static final String DEFAULT_RECEIPT_NB = "1234567890";
|
||||
public static final String DEFAULT_BANK_NB = "1234567890";
|
||||
public static final String DEFAULT_REPAYMENT_TYPE = "AUTOPAY";
|
||||
@Autowired
|
||||
private LoanTransactionsApi loanTransactionsApi;
|
||||
|
||||
@@ -98,6 +99,9 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
@Autowired
|
||||
private EventCheckHelper eventCheckHelper;
|
||||
|
||||
@Autowired
|
||||
private EventStore eventStore;
|
||||
|
||||
@And("Customer makes {string} repayment on {string} with {double} EUR transaction amount")
|
||||
public void makeLoanRepayment(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||
makeRepayment(repaymentType, transactionDate, transactionAmount, null);
|
||||
@@ -111,6 +115,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
|
||||
private void makeRepayment(String repaymentType, String transactionDate, double transactionAmount, String transferExternalOwnerId)
|
||||
throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -132,11 +137,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
EventAssertion.EventAssertionBuilder<LoanTransactionDataV1> transactionEvent = eventCheckHelper
|
||||
.transactionEventCheck(repaymentResponse, TransactionType.REPAYMENT, transferExternalOwnerId);
|
||||
testContext().set(TestContextKey.TRANSACTION_EVENT, transactionEvent);
|
||||
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Created user makes {string} repayment on {string} with {double} EUR transaction amount")
|
||||
public void makeRepaymentWithGivenUser(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -164,11 +170,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
.executeLoanTransaction(loanId, repaymentRequest, "repayment", headerMap).execute();
|
||||
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Customer makes externalID controlled {string} repayment on {string} with {double} EUR transaction amount")
|
||||
public void makeRepaymentByExternalId(String repaymentType, String transactionDate, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
String resourceExternalId = loanResponse.body().getResourceExternalId();
|
||||
@@ -189,12 +196,13 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
|
||||
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Created user makes externalID controlled {string} repayment on {string} with {double} EUR transaction amount")
|
||||
public void makeRepaymentWithGivenUserByExternalId(String repaymentType, String transactionDate, double transactionAmount)
|
||||
throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
String resourceExternalId = loanResponse.body().getResourceExternalId();
|
||||
@@ -223,7 +231,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
.executeLoanTransaction1(resourceExternalId, repaymentRequest, "repayment", headerMap).execute();
|
||||
testContext().set(TestContextKey.LOAN_REPAYMENT_RESPONSE, repaymentResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(repaymentResponse);
|
||||
eventAssertion.assertEventRaised(LoanBalanceChangedEvent.class, loanId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@And("Customer not able to make {string} repayment on {string} with {double} EUR transaction amount")
|
||||
@@ -282,6 +290,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
|
||||
@When("Refund happens on {string} with {double} EUR transaction amount")
|
||||
public void makeRefund(String transactionDate, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdTransactionsRequest refundRequest = LoanRequestFactory.defaultRefundRequest().transactionDate(transactionDate)
|
||||
@@ -293,10 +302,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
.executeLoanTransaction(loanId, refundRequest, "payoutRefund").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(refundResponse);
|
||||
testContext().set(TestContextKey.LOAN_REFUND_RESPONSE, refundResponse);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Refund undo happens on {string}")
|
||||
public void makeRefundUndo(String transactionDate) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
Response<PostLoansLoanIdTransactionsResponse> refundResponse = testContext().get(TestContextKey.LOAN_REFUND_RESPONSE);
|
||||
@@ -318,10 +329,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||
.isEqualTo(Boolean.TRUE);
|
||||
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Customer makes a repayment undo on {string}")
|
||||
public void makeLoanRepaymentUndo(String transactionDate) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
Response<PostLoansLoanIdTransactionsResponse> repaymentResponse = testContext().get(TestContextKey.LOAN_REPAYMENT_RESPONSE);
|
||||
@@ -343,6 +356,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||
.isEqualTo(Boolean.TRUE);
|
||||
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@Then("Loan {string} transaction adjust amount {double} must return {int} code")
|
||||
@@ -361,6 +375,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
|
||||
@When("Customer undo {string}th repayment on {string}")
|
||||
public void undoNthRepayment(String nthItemStr, String transactionDate) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
|
||||
@@ -387,10 +402,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||
.isEqualTo(Boolean.TRUE);
|
||||
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Customer undo {string}th transaction made on {string}")
|
||||
public void undoNthTransaction(String nthItemStr, String transactionDate) throws IOException {
|
||||
eventStore.reset();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
@@ -418,10 +435,12 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||
.isEqualTo(Boolean.TRUE);
|
||||
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Customer undo {string}th {string} transaction made on {string}")
|
||||
public void undoNthTransactionType(String nthItemStr, String transactionType, String transactionDate) throws IOException {
|
||||
eventStore.reset();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
@@ -452,6 +471,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
|
||||
.isEqualTo(Boolean.TRUE);
|
||||
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@Then("Repayment transaction is created with {double} amount and {string} type")
|
||||
@@ -516,6 +536,18 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
adjustNthRepaymentWithExternalOwnerCheck(nthItemStr, transactionDate, amount, null);
|
||||
}
|
||||
|
||||
@When("Loan Pay-off is made on {string}")
|
||||
public void makeLoanPayOff(String transactionDate) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId1 = loanResponse.body().getLoanId();
|
||||
Response<GetLoansLoanIdTransactionsTemplateResponse> response = loanTransactionsApi
|
||||
.retrieveTransactionTemplate(loanId1, "prepayLoan", DATE_FORMAT, transactionDate, DEFAULT_LOCALE).execute();
|
||||
Double transactionAmount = response.body().getAmount();
|
||||
|
||||
log.info("%n--- Loan Pay-off with amount: {} ---", transactionAmount);
|
||||
makeRepayment(DEFAULT_REPAYMENT_TYPE, transactionDate, transactionAmount, null);
|
||||
}
|
||||
|
||||
private void adjustNthRepaymentWithExternalOwnerCheck(String nthItemStr, String transactionDate, String amount, String externalOwnerId)
|
||||
throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
@@ -564,16 +596,4 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@When("Loan Pay-off is made on {string}")
|
||||
public void makeLoanPayOff(String transactionDate) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId1 = loanResponse.body().getLoanId();
|
||||
Response<GetLoansLoanIdTransactionsTemplateResponse> response = loanTransactionsApi
|
||||
.retrieveTransactionTemplate(loanId1, "prepayLoan", DATE_FORMAT, transactionDate, DEFAULT_LOCALE).execute();
|
||||
Double transactionAmount = response.body().getAmount();
|
||||
|
||||
log.info("--- Loan Pay-off with amount: {} ---", transactionAmount);
|
||||
makeRepayment("AUTOPAY", transactionDate, transactionAmount, null);
|
||||
}
|
||||
}
|
||||
|
||||
+34
-9
@@ -26,6 +26,8 @@ import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
|
||||
@@ -48,6 +50,10 @@ import retrofit2.Response;
|
||||
public class LoanRescheduleStepDef extends AbstractStepDef {
|
||||
|
||||
private static final Gson GSON = new JSON().getGson();
|
||||
public static final String DATE_FORMAT_HU = "yyyy-MM-dd";
|
||||
public static final String DATE_FORMAT_EN = "dd MMMM yyyy";
|
||||
public static final DateTimeFormatter FORMATTER_HU = DateTimeFormatter.ofPattern(DATE_FORMAT_HU);
|
||||
public static final DateTimeFormatter FORMATTER_EN = DateTimeFormatter.ofPattern(DATE_FORMAT_EN);
|
||||
|
||||
@Autowired
|
||||
private RescheduleLoansApi rescheduleLoansApi;
|
||||
@@ -59,13 +65,18 @@ public class LoanRescheduleStepDef extends AbstractStepDef {
|
||||
|
||||
List<List<String>> data = table.asLists();
|
||||
List<String> rescheduleData = data.get(1);
|
||||
|
||||
String rescheduleFromDate = rescheduleData.get(0);
|
||||
String submittedOnDate = rescheduleData.get(1);
|
||||
String adjustedDueDate = rescheduleData.get(2);
|
||||
Integer graceOfPrincipal = rescheduleData.get(3) != null ? Integer.parseInt(rescheduleData.get(3)) : null;
|
||||
Integer graceOnInterest = rescheduleData.get(4) != null ? Integer.parseInt(rescheduleData.get(4)) : null;
|
||||
Integer extraTerms = rescheduleData.get(5) != null ? Integer.parseInt(rescheduleData.get(5)) : null;
|
||||
BigDecimal newInterestRate = rescheduleData.get(6) != null ? new BigDecimal(rescheduleData.get(6)) : null;
|
||||
Integer graceOfPrincipal = (rescheduleData.get(3) == null || "0".equals(rescheduleData.get(3))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(3));
|
||||
Integer graceOnInterest = (rescheduleData.get(4) == null || "0".equals(rescheduleData.get(4))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(4));
|
||||
Integer extraTerms = (rescheduleData.get(5) == null || "0".equals(rescheduleData.get(5))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(5));
|
||||
BigDecimal newInterestRate = (rescheduleData.get(6) == null || "0".equals(rescheduleData.get(6))) ? null
|
||||
: new BigDecimal(rescheduleData.get(6));
|
||||
|
||||
PostCreateRescheduleLoansRequest request = new PostCreateRescheduleLoansRequest()//
|
||||
.loanId(loanId)//
|
||||
@@ -105,10 +116,13 @@ public class LoanRescheduleStepDef extends AbstractStepDef {
|
||||
String rescheduleFromDate = rescheduleData.get(0);
|
||||
String submittedOnDate = rescheduleData.get(1);
|
||||
String adjustedDueDate = rescheduleData.get(2);
|
||||
Integer graceOfPrincipal = rescheduleData.get(3) != null ? Integer.parseInt(rescheduleData.get(3)) : null;
|
||||
Integer graceOnInterest = rescheduleData.get(4) != null ? Integer.parseInt(rescheduleData.get(4)) : null;
|
||||
Integer extraTerms = rescheduleData.get(5) != null ? Integer.parseInt(rescheduleData.get(5)) : null;
|
||||
BigDecimal newInterestRate = rescheduleData.get(6) != null ? new BigDecimal(rescheduleData.get(6)) : null;
|
||||
Integer graceOfPrincipal = (rescheduleData.get(3) == null || "0".equals(rescheduleData.get(3))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(3));
|
||||
Integer graceOnInterest = (rescheduleData.get(4) == null || "0".equals(rescheduleData.get(4))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(4));
|
||||
Integer extraTerms = (rescheduleData.get(5) == null || "0".equals(rescheduleData.get(5))) ? null
|
||||
: Integer.valueOf(rescheduleData.get(5));
|
||||
BigDecimal newInterestRate = rescheduleData.get(6) == null ? null : new BigDecimal(rescheduleData.get(6));
|
||||
|
||||
PostCreateRescheduleLoansRequest request = new PostCreateRescheduleLoansRequest()//
|
||||
.loanId(loanId)//
|
||||
@@ -127,7 +141,18 @@ public class LoanRescheduleStepDef extends AbstractStepDef {
|
||||
Response<PostCreateRescheduleLoansResponse> createResponse = rescheduleLoansApi.createLoanRescheduleRequest(request).execute();
|
||||
|
||||
LoanRescheduleErrorMessage loanRescheduleErrorMessage = LoanRescheduleErrorMessage.valueOf(errorMessageType);
|
||||
String errorMessageExpected = loanRescheduleErrorMessage.getValue(loanId);
|
||||
|
||||
LocalDate localDate = LocalDate.parse(rescheduleFromDate, FORMATTER_EN);
|
||||
String rescheduleFromDateFormatted = localDate.format(FORMATTER_HU);
|
||||
String errorMessageExpected = "";
|
||||
int expectedParameterCount = loanRescheduleErrorMessage.getExpectedParameterCount();
|
||||
if (expectedParameterCount == 1) {
|
||||
errorMessageExpected = loanRescheduleErrorMessage.getValue(loanId);
|
||||
} else if (expectedParameterCount == 2) {
|
||||
errorMessageExpected = loanRescheduleErrorMessage.getValue(rescheduleFromDateFormatted, loanId);
|
||||
} else {
|
||||
throw new IllegalStateException("Parameter count in Error message does not met the criteria");
|
||||
}
|
||||
|
||||
String errorToString = createResponse.errorBody().string();
|
||||
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||
|
||||
+275
-23
@@ -21,7 +21,7 @@ package org.apache.fineract.test.stepdef.loan;
|
||||
import static org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
@@ -63,6 +63,7 @@ import org.apache.fineract.client.models.GetLoansLoanIdTimeline;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
|
||||
import org.apache.fineract.client.models.IsCatchUpRunningResponse;
|
||||
import org.apache.fineract.client.models.PaymentAllocationOrder;
|
||||
import org.apache.fineract.client.models.PostClientsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||
@@ -100,10 +101,13 @@ import org.apache.fineract.test.helper.Utils;
|
||||
import org.apache.fineract.test.initializer.global.LoanProductGlobalInitializerStep;
|
||||
import org.apache.fineract.test.messaging.EventAssertion;
|
||||
import org.apache.fineract.test.messaging.event.EventCheckHelper;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanRescheduledDueAdjustScheduleEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.LoanStatusChangedEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanAccrualTransactionCreatedBusinessEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffUndoEvent;
|
||||
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionAccrualActivityPostEvent;
|
||||
import org.apache.fineract.test.messaging.store.EventStore;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -117,6 +121,8 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
public static final String DEFAULT_LOCALE = "en";
|
||||
public static final String LOAN_STATE_SUBMITTED_AND_PENDING = "Submitted and pending approval";
|
||||
public static final String LOAN_STATE_APPROVED = "Approved";
|
||||
public static final String LOAN_STATE_REJECTED = "Rejected";
|
||||
public static final String LOAN_STATE_WITHDRAWN = "Withdrawn by applicant";
|
||||
public static final String LOAN_STATE_ACTIVE = "Active";
|
||||
private static final Gson GSON = new JSON().getGson();
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);
|
||||
@@ -149,6 +155,9 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
@Autowired
|
||||
private LoanProductsApi loanProductsApi;
|
||||
|
||||
@Autowired
|
||||
private EventStore eventStore;
|
||||
|
||||
@When("Admin creates a new Loan")
|
||||
public void createLoan() throws IOException {
|
||||
Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||
@@ -240,6 +249,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
private void createTransactionWithIdempotencyKeyAndExternalOwnerCheck(String transactionTypeInput, String transactionPaymentType,
|
||||
String transactionDate, double transactionAmount, String externalOwnerId) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -262,11 +272,13 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
|
||||
|
||||
eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, externalOwnerId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Admin makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount")
|
||||
public void createTransactionForRefund(String transactionTypeInput, String transactionPaymentType, String transactionDate,
|
||||
double transactionAmount) throws IOException, InterruptedException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -284,6 +296,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
|
||||
|
||||
eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, null);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Customer makes {string} transaction with {string} payment type on {string} with {double} EUR transaction amount and system-generated Idempotency key")
|
||||
@@ -303,6 +316,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
private void createTransactionWithAutoIdempotencyKeyAndWithExternalOwner(String transactionTypeInput, String transactionPaymentType,
|
||||
String transactionDate, double transactionAmount, String externalOwnerId) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -321,10 +335,12 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
|
||||
|
||||
eventCheckHelper.transactionEventCheck(paymentTransactionResponse, transactionType, externalOwnerId);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@When("Admin makes Credit Balance Refund transaction on {string} with {double} EUR transaction amount")
|
||||
public void createCBR(String transactionDate, double transactionAmount) throws IOException {
|
||||
eventStore.reset();
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
|
||||
@@ -337,6 +353,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
.executeLoanTransaction(loanId, paymentTransactionRequest, transactionTypeValue).execute();
|
||||
testContext().set(TestContextKey.LOAN_PAYMENT_TRANSACTION_RESPONSE, paymentTransactionResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(paymentTransactionResponse);
|
||||
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
|
||||
}
|
||||
|
||||
@Then("Credit Balance Refund transaction on future date {string} with {double} EUR transaction amount will result an error")
|
||||
@@ -444,7 +461,8 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
.expectedDisbursementDate(submitDate)//
|
||||
.graceOnPrincipalPayment(graceOnPrincipalPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
|
||||
.graceOnInterestPayment(graceOnInterestCharged)//
|
||||
.transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
|
||||
.fixedLength(fixedLength);//
|
||||
|
||||
Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
||||
@@ -454,6 +472,84 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
eventCheckHelper.createLoanEventCheck(response);
|
||||
}
|
||||
|
||||
@When("Trying to create a fully customized loan with fixed length {int} and with the following data will result a {int} ERROR:")
|
||||
public void createFullyCustomizedLoanFixedLengthError(int fixedLength, int errorCodeExpected, DataTable table) throws IOException {
|
||||
List<List<String>> data = table.asLists();
|
||||
List<String> loanData = data.get(1);
|
||||
String loanProduct = loanData.get(0);
|
||||
String submitDate = loanData.get(1);
|
||||
String principal = loanData.get(2);
|
||||
BigDecimal interestRate = new BigDecimal(loanData.get(3));
|
||||
String interestType = loanData.get(4);
|
||||
String interestCalculationPeriod = loanData.get(5);
|
||||
String amortizationType = loanData.get(6);
|
||||
Integer loanTermFrequency = Integer.valueOf(loanData.get(7));
|
||||
String loanTermFrequencyType = loanData.get(8);
|
||||
Integer repaymentFrequency = Integer.valueOf(loanData.get(9));
|
||||
String repaymentFrequencyType = loanData.get(10);
|
||||
Integer numberOfRepayments = Integer.valueOf(loanData.get(11));
|
||||
Integer graceOnPrincipalPayment = Integer.valueOf(loanData.get(12));
|
||||
Integer graceOnInterestPayment = Integer.valueOf(loanData.get(13));
|
||||
Integer graceOnInterestCharged = Integer.valueOf(loanData.get(14));
|
||||
String transactionProcessingStrategyCode = loanData.get(15);
|
||||
|
||||
Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||
Long clientId = clientResponse.body().getClientId();
|
||||
|
||||
DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProduct);
|
||||
Long loanProductId = loanProductResolver.resolve(product);
|
||||
|
||||
LoanTermFrequencyType termFrequencyType = LoanTermFrequencyType.valueOf(loanTermFrequencyType);
|
||||
Integer loanTermFrequencyTypeValue = termFrequencyType.getValue();
|
||||
|
||||
RepaymentFrequencyType repaymentFrequencyType1 = RepaymentFrequencyType.valueOf(repaymentFrequencyType);
|
||||
Integer repaymentFrequencyTypeValue = repaymentFrequencyType1.getValue();
|
||||
|
||||
InterestType interestType1 = InterestType.valueOf(interestType);
|
||||
Integer interestTypeValue = interestType1.getValue();
|
||||
|
||||
InterestCalculationPeriodTime interestCalculationPeriod1 = InterestCalculationPeriodTime.valueOf(interestCalculationPeriod);
|
||||
Integer interestCalculationPeriodValue = interestCalculationPeriod1.getValue();
|
||||
|
||||
AmortizationType amortizationType1 = AmortizationType.valueOf(amortizationType);
|
||||
Integer amortizationTypeValue = amortizationType1.getValue();
|
||||
|
||||
TransactionProcessingStrategyCode processingStrategyCode = TransactionProcessingStrategyCode
|
||||
.valueOf(transactionProcessingStrategyCode);
|
||||
String transactionProcessingStrategyCodeValue = processingStrategyCode.getValue();
|
||||
|
||||
PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
|
||||
.productId(loanProductId)//
|
||||
.principal(new BigDecimal(principal))//
|
||||
.interestRatePerPeriod(interestRate)//
|
||||
.interestType(interestTypeValue)//
|
||||
.interestCalculationPeriodType(interestCalculationPeriodValue)//
|
||||
.amortizationType(amortizationTypeValue)//
|
||||
.loanTermFrequency(loanTermFrequency)//
|
||||
.loanTermFrequencyType(loanTermFrequencyTypeValue)//
|
||||
.numberOfRepayments(numberOfRepayments)//
|
||||
.repaymentEvery(repaymentFrequency)//
|
||||
.repaymentFrequencyType(repaymentFrequencyTypeValue)//
|
||||
.submittedOnDate(submitDate)//
|
||||
.expectedDisbursementDate(submitDate)//
|
||||
.graceOnPrincipalPayment(graceOnPrincipalPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestCharged)//
|
||||
.transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
|
||||
.fixedLength(fixedLength);//
|
||||
|
||||
Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
||||
String errorToString = response.errorBody().string();
|
||||
ErrorResponse errorResponse = GSON.fromJson(errorToString, ErrorResponse.class);
|
||||
String errorMessageActual = errorResponse.getErrors().get(0).getDeveloperMessage();
|
||||
int errorCodeActual = response.code();
|
||||
|
||||
assertThat(errorCodeActual).as(ErrorMessageHelper.wrongErrorCode(errorCodeActual, errorCodeExpected)).isEqualTo(errorCodeExpected);
|
||||
|
||||
log.info("ERROR CODE: {}", errorCodeActual);
|
||||
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||
}
|
||||
|
||||
@When("Admin creates a fully customized loan with Advanced payment allocation and with product no Advanced payment allocation set results an error:")
|
||||
public void createFullyCustomizedLoanNoAdvancedPaymentError(DataTable table) throws IOException {
|
||||
int errorCodeExpected = 403;
|
||||
@@ -519,7 +615,8 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
.expectedDisbursementDate(submitDate)//
|
||||
.graceOnPrincipalPayment(graceOnPrincipalPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue);//
|
||||
.graceOnInterestPayment(graceOnInterestCharged)//
|
||||
.transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue);//
|
||||
|
||||
Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
||||
int errorCodeActual = response.code();
|
||||
@@ -535,6 +632,79 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
log.info("ERROR MESSAGE: {}", errorMessageActual);
|
||||
}
|
||||
|
||||
@When("Admin creates a fully customized loan with installment level delinquency and with the following data:")
|
||||
public void createFullyCustomizedLoanWithInstallmentLvlDelinquency(DataTable table) throws IOException {
|
||||
List<List<String>> data = table.asLists();
|
||||
List<String> loanData = data.get(1);
|
||||
String loanProduct = loanData.get(0);
|
||||
String submitDate = loanData.get(1);
|
||||
String principal = loanData.get(2);
|
||||
BigDecimal interestRate = new BigDecimal(loanData.get(3));
|
||||
String interestType = loanData.get(4);
|
||||
String interestCalculationPeriod = loanData.get(5);
|
||||
String amortizationType = loanData.get(6);
|
||||
Integer loanTermFrequency = Integer.valueOf(loanData.get(7));
|
||||
String loanTermFrequencyType = loanData.get(8);
|
||||
Integer repaymentFrequency = Integer.valueOf(loanData.get(9));
|
||||
String repaymentFrequencyType = loanData.get(10);
|
||||
Integer numberOfRepayments = Integer.valueOf(loanData.get(11));
|
||||
Integer graceOnPrincipalPayment = Integer.valueOf(loanData.get(12));
|
||||
Integer graceOnInterestPayment = Integer.valueOf(loanData.get(13));
|
||||
Integer graceOnInterestCharged = Integer.valueOf(loanData.get(14));
|
||||
String transactionProcessingStrategyCode = loanData.get(15);
|
||||
|
||||
Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||
Long clientId = clientResponse.body().getClientId();
|
||||
|
||||
DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProduct);
|
||||
Long loanProductId = loanProductResolver.resolve(product);
|
||||
|
||||
LoanTermFrequencyType termFrequencyType = LoanTermFrequencyType.valueOf(loanTermFrequencyType);
|
||||
Integer loanTermFrequencyTypeValue = termFrequencyType.getValue();
|
||||
|
||||
RepaymentFrequencyType repaymentFrequencyType1 = RepaymentFrequencyType.valueOf(repaymentFrequencyType);
|
||||
Integer repaymentFrequencyTypeValue = repaymentFrequencyType1.getValue();
|
||||
|
||||
InterestType interestType1 = InterestType.valueOf(interestType);
|
||||
Integer interestTypeValue = interestType1.getValue();
|
||||
|
||||
InterestCalculationPeriodTime interestCalculationPeriod1 = InterestCalculationPeriodTime.valueOf(interestCalculationPeriod);
|
||||
Integer interestCalculationPeriodValue = interestCalculationPeriod1.getValue();
|
||||
|
||||
AmortizationType amortizationType1 = AmortizationType.valueOf(amortizationType);
|
||||
Integer amortizationTypeValue = amortizationType1.getValue();
|
||||
|
||||
TransactionProcessingStrategyCode processingStrategyCode = TransactionProcessingStrategyCode
|
||||
.valueOf(transactionProcessingStrategyCode);
|
||||
String transactionProcessingStrategyCodeValue = processingStrategyCode.getValue();
|
||||
|
||||
PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId)//
|
||||
.productId(loanProductId)//
|
||||
.principal(new BigDecimal(principal))//
|
||||
.interestRatePerPeriod(interestRate)//
|
||||
.interestType(interestTypeValue)//
|
||||
.interestCalculationPeriodType(interestCalculationPeriodValue)//
|
||||
.amortizationType(amortizationTypeValue)//
|
||||
.loanTermFrequency(loanTermFrequency)//
|
||||
.loanTermFrequencyType(loanTermFrequencyTypeValue)//
|
||||
.numberOfRepayments(numberOfRepayments)//
|
||||
.repaymentEvery(repaymentFrequency)//
|
||||
.repaymentFrequencyType(repaymentFrequencyTypeValue)//
|
||||
.submittedOnDate(submitDate)//
|
||||
.expectedDisbursementDate(submitDate)//
|
||||
.graceOnPrincipalPayment(graceOnPrincipalPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestPayment)//
|
||||
.graceOnInterestPayment(graceOnInterestCharged)//
|
||||
.transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
|
||||
.enableInstallmentLevelDelinquency(true);//
|
||||
|
||||
Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
|
||||
testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
|
||||
ErrorHelper.checkSuccessfulApiCall(response);
|
||||
|
||||
eventCheckHelper.createLoanEventCheck(response);
|
||||
}
|
||||
|
||||
@Then("Loan details has the following last payment related data:")
|
||||
public void checkLastPaymentData(DataTable table) throws IOException {
|
||||
List<List<String>> data = table.asLists();
|
||||
@@ -730,6 +900,37 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
eventCheckHelper.approveLoanEventCheck(loanApproveResponse);
|
||||
}
|
||||
|
||||
@And("Admin successfully rejects the loan on {string}")
|
||||
public void rejectLoan(String rejectDate) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdRequest rejectRequest = LoanRequestFactory.defaultLoanRejectRequest().rejectedOnDate(rejectDate);
|
||||
|
||||
Response<PostLoansLoanIdResponse> loanRejectResponse = loansApi.stateTransitions(loanId, rejectRequest, "reject").execute();
|
||||
testContext().set(TestContextKey.LOAN_REJECT_RESPONSE, loanRejectResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(loanRejectResponse);
|
||||
assertThat(loanRejectResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_REJECTED);
|
||||
assertThat(loanRejectResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_REJECTED);
|
||||
|
||||
eventCheckHelper.loanRejectedEventCheck(loanRejectResponse);
|
||||
}
|
||||
|
||||
@And("Admin successfully withdrawn the loan on {string}")
|
||||
public void withdrawnLoan(String withdrawnDate) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdRequest withdawnRequest = LoanRequestFactory.defaultLoanWithdrawnRequest().withdrawnOnDate(withdrawnDate);
|
||||
|
||||
Response<PostLoansLoanIdResponse> loanWithdrawnResponse = loansApi.stateTransitions(loanId, withdawnRequest, "withdrawnByApplicant")
|
||||
.execute();
|
||||
testContext().set(TestContextKey.LOAN_WITHDRAWN_RESPONSE, loanWithdrawnResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(loanWithdrawnResponse);
|
||||
assertThat(loanWithdrawnResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_WITHDRAWN);
|
||||
assertThat(loanWithdrawnResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_WITHDRAWN);
|
||||
|
||||
eventCheckHelper.undoApproveLoanEventCheck(loanWithdrawnResponse);
|
||||
}
|
||||
|
||||
@And("Admin successfully approves the second loan on {string} with {string} amount and expected disbursement date on {string}")
|
||||
public void approveSecondLoan(String approveDate, String approvedAmount, String expectedDisbursementDate) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_SECOND_LOAN_RESPONSE);
|
||||
@@ -785,10 +986,31 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
@And("Admin successfully disburse the loan on {string} with {string} EUR transaction amount")
|
||||
public void disburseLoan(String actualDisbursementDate, String transactionAmount) throws IOException {
|
||||
final Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
assertNotNull(loanResponse.body());
|
||||
final long loanId = loanResponse.body().getLoanId();
|
||||
final PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
|
||||
.actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));
|
||||
|
||||
Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse").execute();
|
||||
testContext().set(TestContextKey.LOAN_DISBURSE_RESPONSE, loanDisburseResponse);
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDisburseResponse);
|
||||
Long statusActual = loanDisburseResponse.body().getChanges().getStatus().getId();
|
||||
|
||||
Response<GetLoansLoanIdResponse> loanDetails = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||
Long statusExpected = Long.valueOf(loanDetails.body().getStatus().getId());
|
||||
|
||||
assertThat(statusActual)//
|
||||
.as(ErrorMessageHelper.wrongLoanStatus(Math.toIntExact(statusActual), Math.toIntExact(statusExpected)))//
|
||||
.isEqualTo(statusExpected);//
|
||||
eventCheckHelper.disburseLoanEventCheck(loanId);
|
||||
eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse);
|
||||
}
|
||||
|
||||
@And("Admin successfully disburse the loan without auto downpayment on {string} with {string} EUR transaction amount")
|
||||
public void disburseLoanWithoutAutoDownpayment(String actualDisbursementDate, String transactionAmount) throws IOException {
|
||||
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.body().getLoanId();
|
||||
PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
|
||||
.actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));
|
||||
performLoanDisbursementAndVerifyStatus(loanId, disburseRequest);
|
||||
}
|
||||
@@ -829,7 +1051,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDisburseResponse);
|
||||
assertThat(loanDisburseResponse.body().getChanges().getStatus().getValue()).isEqualTo(LOAN_STATE_ACTIVE);
|
||||
|
||||
eventCheckHelper.disburseLoanEventCheck(loanDisburseResponse);
|
||||
eventCheckHelper.disburseLoanEventCheck(loanId);
|
||||
eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse);
|
||||
}
|
||||
|
||||
@@ -1141,10 +1363,13 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
List<List<String>> data = table.asLists();
|
||||
for (int i = 1; i < data.size(); i++) {
|
||||
List<String> expectedValues = data.get(i);
|
||||
String transactionDateExpected = expectedValues.get(0);
|
||||
List<List<String>> actualValuesList = transactions.stream()//
|
||||
.filter(t -> transactionDateExpected.equals(FORMATTER.format(t.getDate())))//
|
||||
.map(t -> fetchValuesOfTransaction(table.row(0), t))//
|
||||
.collect(Collectors.toList());//
|
||||
boolean containsExpectedValues = actualValuesList.get(i - 1).equals(expectedValues);//
|
||||
boolean containsExpectedValues = actualValuesList.stream()//
|
||||
.anyMatch(actualValues -> actualValues.equals(expectedValues));//
|
||||
assertThat(containsExpectedValues).as(ErrorMessageHelper.wrongValueInLineInTransactionsTab(i, actualValuesList, expectedValues))
|
||||
.isTrue();
|
||||
}
|
||||
@@ -1319,7 +1544,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
assertThat(allInstallmentsObligationsMet).isTrue();
|
||||
}
|
||||
|
||||
@Then("Loan closedon_date is {}")
|
||||
@Then("Loan closedon_date is {string}")
|
||||
public void loanClosedonDate(String date) throws IOException {
|
||||
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanCreateResponse.body().getLoanId();
|
||||
@@ -1327,10 +1552,10 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "", "", "").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
testContext().set(TestContextKey.LOAN_RESPONSE, loanDetailsResponse);
|
||||
if (date == null || "null".equals(date)) {
|
||||
if ("null".equals(date)) {
|
||||
assertThat(loanDetailsResponse.body().getTimeline().getClosedOnDate()).isNull();
|
||||
} else {
|
||||
assertThat(loanDetailsResponse.body().getTimeline().getClosedOnDate()).isEqualTo(date);
|
||||
assertThat(FORMATTER.format(loanDetailsResponse.body().getTimeline().getClosedOnDate())).isEqualTo(date);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1555,7 +1780,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
IsCatchUpRunningResponse isCatchUpRunning = isCatchUpRunningResponse.body();
|
||||
return isCatchUpRunning.getIsCatchUpRunning();
|
||||
});
|
||||
await().pollInterval(2, TimeUnit.SECONDS).atMost(Duration.ofSeconds(240)).until(() -> {
|
||||
await().pollInterval(2, TimeUnit.SECONDS).atMost(Duration.ofMinutes(4)).until(() -> {
|
||||
Response<IsCatchUpRunningResponse> isCatchUpRunningResponse = loanCobCatchUpApi.isCatchUpRunning().execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(isCatchUpRunningResponse);
|
||||
IsCatchUpRunningResponse isCatchUpRunning = isCatchUpRunningResponse.body();
|
||||
@@ -1596,6 +1821,31 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
eventAssertion.assertEventRaised(LoanAccrualTransactionCreatedBusinessEvent.class, accrualTransactionId);
|
||||
}
|
||||
|
||||
@Then("LoanTransactionAccrualActivityPostBusinessEvent is raised on {string}")
|
||||
public void checkLoanTransactionAccrualActivityPostBusinessEvent(String date) throws IOException {
|
||||
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanCreateResponse.body().getLoanId();
|
||||
|
||||
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
|
||||
|
||||
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
|
||||
GetLoansLoanIdTransactions accrualTransaction = transactions.stream()
|
||||
.filter(t -> date.equals(FORMATTER.format(t.getDate())) && "Accrual Activity".equals(t.getType().getValue())).findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException(String.format("No Accrual activity transaction found on %s", date)));
|
||||
Long accrualTransactionId = accrualTransaction.getId();
|
||||
|
||||
eventAssertion.assertEventRaised(LoanTransactionAccrualActivityPostEvent.class, accrualTransactionId);
|
||||
}
|
||||
|
||||
@Then("LoanRescheduledDueAdjustScheduleBusinessEvent is raised on {string}")
|
||||
public void checkLoanRescheduledDueAdjustScheduleBusinessEvent(String date) throws IOException {
|
||||
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanCreateResponse.body().getLoanId();
|
||||
|
||||
eventAssertion.assertEventRaised(LoanRescheduledDueAdjustScheduleEvent.class, loanId);
|
||||
}
|
||||
|
||||
@Then("Loan details and event has the following last repayment related data:")
|
||||
public void checkLastRepaymentData(DataTable table) throws IOException {
|
||||
List<List<String>> data = table.asLists();
|
||||
@@ -1649,7 +1899,6 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@And("Admin does a charge-off undo the loan with reversal external Id")
|
||||
@@ -1741,7 +1990,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
String futureInstallmentAllocationRuleNew) throws IOException {
|
||||
DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProductName);
|
||||
Long loanProductId = loanProductResolver.resolve(product);
|
||||
log.info("loanProductId {}", loanProductId);
|
||||
log.info("loanProductId: {}", loanProductId);
|
||||
|
||||
Response<GetLoanProductsProductIdResponse> loanProductDetails = loanProductsApi.retrieveLoanProductDetails(loanProductId).execute();
|
||||
ErrorHelper.checkSuccessfulApiCall(loanProductDetails);
|
||||
@@ -1751,11 +2000,12 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
paymentAllocation.forEach(e -> {
|
||||
String transactionTypeOriginal = e.getTransactionType();
|
||||
String futureInstallmentAllocationRule = e.getFutureInstallmentAllocationRule();
|
||||
List<PaymentAllocationOrder> paymentAllocationOrder = e.getPaymentAllocationOrder();
|
||||
if (transactionTypeToChange.equals(transactionTypeOriginal)) {
|
||||
futureInstallmentAllocationRule = futureInstallmentAllocationRuleNew;
|
||||
}
|
||||
newPaymentAllocation.add(
|
||||
LoanProductGlobalInitializerStep.createPaymentAllocation(transactionTypeOriginal, futureInstallmentAllocationRule));
|
||||
newPaymentAllocation.add(LoanProductGlobalInitializerStep.editPaymentAllocationFutureInstallment(transactionTypeOriginal,
|
||||
futureInstallmentAllocationRule, paymentAllocationOrder));
|
||||
});
|
||||
|
||||
PutLoanProductsProductIdRequest putLoanProductsProductIdRequest = new PutLoanProductsProductIdRequest()
|
||||
@@ -1770,7 +2020,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
public void editRepaymentStartDateType(String loanProductName, String repaymentStartDateType) throws IOException {
|
||||
DefaultLoanProduct product = DefaultLoanProduct.valueOf(loanProductName);
|
||||
Long loanProductId = loanProductResolver.resolve(product);
|
||||
log.info("loanProductId {}", loanProductId);
|
||||
log.info("loanProductId: {}", loanProductId);
|
||||
|
||||
Map<String, Integer> repaymentStartDateTypeMap = Map.of("DISBURSEMENT_DATE", 1, "SUBMITTED_ON_DATE", 2);
|
||||
|
||||
@@ -1822,7 +2072,6 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
|
||||
ErrorResponse errorDetails = ErrorResponse.from(transactionUndoResponse);
|
||||
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(503);
|
||||
|
||||
}
|
||||
|
||||
@Then("Loan {string} repayment transaction on {string} with {double} EUR transaction amount results in error")
|
||||
@@ -1843,7 +2092,6 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
ErrorResponse errorDetails = ErrorResponse.from(repaymentResponse);
|
||||
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.dateFailureErrorCodeMsg()).isEqualTo(400);
|
||||
|
||||
}
|
||||
|
||||
@Then("Loan details has the downpayment amount {string} in summary.totalRepaymentTransaction")
|
||||
@@ -2036,7 +2284,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
assertThat(statusActual).as(ErrorMessageHelper.wrongLoanStatus(Math.toIntExact(statusActual), Math.toIntExact(statusExpected)))
|
||||
.isEqualTo(statusExpected);
|
||||
eventCheckHelper.disburseLoanEventCheck(loanDisburseResponse);
|
||||
eventCheckHelper.disburseLoanEventCheck(loanId);
|
||||
eventCheckHelper.loanDisbursalTransactionEventCheck(loanDisburseResponse);
|
||||
}
|
||||
|
||||
@@ -2114,7 +2362,6 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
|
||||
private List<String> fetchValuesOfTransaction(List<String> header, GetLoansLoanIdTransactions t) {
|
||||
List<String> actualValues = new ArrayList<>();
|
||||
for (String headerName : header) {
|
||||
@@ -2132,12 +2379,16 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
case "Overpayment" ->
|
||||
actualValues.add(t.getOverpaymentPortion() == null ? null : String.valueOf(t.getOverpaymentPortion()));
|
||||
case "Reverted" -> actualValues.add(t.getManuallyReversed() == null ? null : String.valueOf(t.getManuallyReversed()));
|
||||
case "Replayed" -> {
|
||||
boolean hasReplayed = t.getTransactionRelations().stream().anyMatch(e -> "REPLAYED".equals(e.getRelationType()));
|
||||
actualValues.add(hasReplayed ? "true" : "false");
|
||||
}
|
||||
default -> throw new IllegalStateException(String.format("Header name %s cannot be found", headerName));
|
||||
}
|
||||
}
|
||||
return actualValues;
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("SF_SWITCH_NO_DEFAULT")
|
||||
private List<String> fetchValuesOfRepaymentSchedule(List<String> header, GetLoansLoanIdRepaymentPeriod repaymentPeriod) {
|
||||
List<String> actualValues = new ArrayList<>();
|
||||
for (String headerName : header) {
|
||||
@@ -2171,6 +2422,7 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
: String.valueOf(repaymentPeriod.getTotalWaivedForPeriod()));
|
||||
case "Outstanding" -> actualValues.add(repaymentPeriod.getTotalOutstandingForPeriod() == null ? null
|
||||
: String.valueOf(repaymentPeriod.getTotalOutstandingForPeriod()));
|
||||
default -> throw new IllegalStateException(String.format("Header name %s cannot be found", headerName));
|
||||
}
|
||||
}
|
||||
return actualValues;
|
||||
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.stepdef.saving;
|
||||
|
||||
import io.cucumber.java.en.And;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.fineract.client.models.PostClientsResponse;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountTransactionsResponse;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsAccountIdRequest;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsAccountIdResponse;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsRequest;
|
||||
import org.apache.fineract.client.models.PostSavingsAccountsResponse;
|
||||
import org.apache.fineract.client.services.SavingsAccountApi;
|
||||
import org.apache.fineract.client.services.SavingsAccountTransactionsApi;
|
||||
import org.apache.fineract.test.factory.SavingsAccountRequestFactory;
|
||||
import org.apache.fineract.test.stepdef.AbstractStepDef;
|
||||
import org.apache.fineract.test.support.TestContextKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class SavingsAccountStepDef extends AbstractStepDef {
|
||||
|
||||
@Autowired
|
||||
private SavingsAccountTransactionsApi savingsAccountTransactionsApi;
|
||||
|
||||
@Autowired
|
||||
private SavingsAccountApi savingsAccountApi;
|
||||
|
||||
@And("Client creates a new EUR savings account with {string} submitted on date")
|
||||
public void createSavingsAccountEUR(String submittedOnDate) throws IOException {
|
||||
Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||
long clientId = clientResponse.body().getClientId();
|
||||
|
||||
PostSavingsAccountsRequest createSavingsAccountRequest = SavingsAccountRequestFactory.defaultEURSavingsAccountRequest()
|
||||
.clientId((int) clientId).submittedOnDate(submittedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsResponse> createSavingsAccountResponse = savingsAccountApi
|
||||
.submitApplication2(createSavingsAccountRequest).execute();
|
||||
testContext().set(TestContextKey.EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE, createSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Client creates a new USD savings account with {string} submitted on date")
|
||||
public void createSavingsAccountUSD(String submittedOnDate) throws IOException {
|
||||
Response<PostClientsResponse> clientResponse = testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
|
||||
long clientId = clientResponse.body().getClientId();
|
||||
|
||||
PostSavingsAccountsRequest createSavingsAccountRequest = SavingsAccountRequestFactory.defaultUSDSavingsAccountRequest()
|
||||
.clientId((int) clientId).submittedOnDate(submittedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsResponse> createSavingsAccountResponse = savingsAccountApi
|
||||
.submitApplication2(createSavingsAccountRequest).execute();
|
||||
testContext().set(TestContextKey.USD_SAVINGS_ACCOUNT_CREATE_RESPONSE, createSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Approve EUR savings account on {string} date")
|
||||
public void approveEurSavingsAccount(String approvedOnDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountsAccountIdRequest approveSavingsAccountRequest = SavingsAccountRequestFactory.defaultApproveRequest()
|
||||
.approvedOnDate(approvedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsAccountIdResponse> approveSavingsAccountResponse = savingsAccountApi
|
||||
.handleCommands6(savingsAccountID, approveSavingsAccountRequest, "approve").execute();
|
||||
testContext().set(TestContextKey.EUR_SAVINGS_ACCOUNT_APPROVE_RESPONSE, approveSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Approve USD savings account on {string} date")
|
||||
public void approveUsdSavingsAccount(String approvedOnDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.USD_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountsAccountIdRequest approveSavingsAccountRequest = SavingsAccountRequestFactory.defaultApproveRequest()
|
||||
.approvedOnDate(approvedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsAccountIdResponse> approveSavingsAccountResponse = savingsAccountApi
|
||||
.handleCommands6(savingsAccountID, approveSavingsAccountRequest, "approve").execute();
|
||||
testContext().set(TestContextKey.USD_SAVINGS_ACCOUNT_APPROVE_RESPONSE, approveSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Activate EUR savings account on {string} date")
|
||||
public void activateSavingsAccount(String activatedOnDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountsAccountIdRequest activateSavingsAccountRequest = SavingsAccountRequestFactory.defaultActivateRequest()
|
||||
.activatedOnDate(activatedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsAccountIdResponse> activateSavingsAccountResponse = savingsAccountApi
|
||||
.handleCommands6(savingsAccountID, activateSavingsAccountRequest, "activate").execute();
|
||||
testContext().set(TestContextKey.EUR_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE, activateSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Activate USD savings account on {string} date")
|
||||
public void activateUsdSavingsAccount(String activatedOnDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.USD_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountsAccountIdRequest activateSavingsAccountRequest = SavingsAccountRequestFactory.defaultActivateRequest()
|
||||
.activatedOnDate(activatedOnDate);
|
||||
|
||||
Response<PostSavingsAccountsAccountIdResponse> activateSavingsAccountResponse = savingsAccountApi
|
||||
.handleCommands6(savingsAccountID, activateSavingsAccountRequest, "activate").execute();
|
||||
testContext().set(TestContextKey.USD_SAVINGS_ACCOUNT_ACTIVATED_RESPONSE, activateSavingsAccountResponse);
|
||||
}
|
||||
|
||||
@And("Client successfully deposits {double} EUR to the savings account on {string} date")
|
||||
public void createEurDeposit(double depositAmount, String depositDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountTransactionsRequest depositRequest = SavingsAccountRequestFactory.defaultDepositRequest()
|
||||
.transactionDate(depositDate).transactionAmount(BigDecimal.valueOf(depositAmount));
|
||||
|
||||
Response<PostSavingsAccountTransactionsResponse> depositResponse = savingsAccountTransactionsApi
|
||||
.transaction2(savingsAccountID, depositRequest, "deposit").execute();
|
||||
testContext().set(TestContextKey.EUR_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE, depositResponse);
|
||||
}
|
||||
|
||||
@And("Client successfully deposits {double} USD to the savings account on {string} date")
|
||||
public void createUsdDeposit(double depositAmount, String depositDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.USD_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountTransactionsRequest depositRequest = SavingsAccountRequestFactory.defaultDepositRequest()
|
||||
.transactionDate(depositDate).transactionAmount(BigDecimal.valueOf(depositAmount));
|
||||
|
||||
Response<PostSavingsAccountTransactionsResponse> depositResponse = savingsAccountTransactionsApi
|
||||
.transaction2(savingsAccountID, depositRequest, "deposit").execute();
|
||||
testContext().set(TestContextKey.USD_SAVINGS_ACCOUNT_DEPOSIT_RESPONSE, depositResponse);
|
||||
}
|
||||
|
||||
@And("Client successfully withdraw {double} EUR from the savings account on {string} date")
|
||||
public void createEurWithdraw(double withdrawAmount, String transcationDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.EUR_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountTransactionsRequest withdrawRequest = SavingsAccountRequestFactory.defaultWithdrawRequest()
|
||||
.transactionDate(transcationDate).transactionAmount(BigDecimal.valueOf(withdrawAmount));
|
||||
|
||||
Response<PostSavingsAccountTransactionsResponse> withdrawalResponse = savingsAccountTransactionsApi
|
||||
.transaction2(savingsAccountID, withdrawRequest, "withdrawal").execute();
|
||||
testContext().set(TestContextKey.EUR_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE, withdrawalResponse);
|
||||
}
|
||||
|
||||
@And("Client successfully withdraw {double} USD from the savings account on {string} date")
|
||||
public void createUsdWithdraw(double withdrawAmount, String transcationDate) throws IOException {
|
||||
Response<PostSavingsAccountsResponse> savingsAccountResponse = testContext()
|
||||
.get(TestContextKey.USD_SAVINGS_ACCOUNT_CREATE_RESPONSE);
|
||||
long savingsAccountID = savingsAccountResponse.body().getSavingsId();
|
||||
|
||||
PostSavingsAccountTransactionsRequest withdrawRequest = SavingsAccountRequestFactory.defaultWithdrawRequest()
|
||||
.transactionDate(transcationDate).transactionAmount(BigDecimal.valueOf(withdrawAmount));
|
||||
|
||||
Response<PostSavingsAccountTransactionsResponse> withdrawalResponse = savingsAccountTransactionsApi
|
||||
.transaction2(savingsAccountID, withdrawRequest, "withdrawal").execute();
|
||||
testContext().set(TestContextKey.USD_SAVINGS_ACCOUNT_WITHDRAW_RESPONSE, withdrawalResponse);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -25,7 +25,8 @@ import java.util.Map;
|
||||
|
||||
public enum TestContext {
|
||||
|
||||
INSTANCE;
|
||||
INSTANCE, //
|
||||
GLOBAL;//
|
||||
|
||||
@SuppressWarnings("ImmutableEnumChecker")
|
||||
private final ThreadLocal<Map<String, Object>> testContexts = withInitial(HashMap::new);
|
||||
|
||||
+25
-6
@@ -24,6 +24,7 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public abstract class TestContextKey {
|
||||
|
||||
public static final String ORIGINAL_COB_WORKFLOW_JOB_BUSINESS_STEP_LIST = "originalCOBWorkflowJobBusinessStepList";
|
||||
public static final String CLIENT_CREATE_RESPONSE = "clientCreateResponse";
|
||||
public static final String CLIENT_CREATE_SECOND_CLIENT_RESPONSE = "clientCreateSecondClientResponse";
|
||||
public static final String LOAN_CREATE_RESPONSE = "loanCreateResponse";
|
||||
@@ -35,6 +36,8 @@ public abstract class TestContextKey {
|
||||
public static final String WAIVE_CHARGE_RESPONSE = "waiveChargeResponse";
|
||||
public static final String UNDO_WAIVE_RESPONSE = "waiveNsfFeeResponse";
|
||||
public static final String LOAN_APPROVAL_RESPONSE = "loanApprovalResponse";
|
||||
public static final String LOAN_REJECT_RESPONSE = "loanRejectResponse";
|
||||
public static final String LOAN_WITHDRAWN_RESPONSE = "loanWithdrawnResponse";
|
||||
public static final String LOAN_APPROVAL_SECOND_LOAN_RESPONSE = "loanApprovalSecondLoanResponse";
|
||||
public static final String LOAN_UNDO_APPROVAL_RESPONSE = "loanUndoApprovalResponse";
|
||||
public static final String LOAN_DISBURSE_RESPONSE = "loanDisburseResponse";
|
||||
@@ -61,27 +64,44 @@ public abstract class TestContextKey {
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_PERIOD_SAME_AS_PAYMENT = "loanProductCreateResponseLP1InterestDecliningPeriodSameAsPayment";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_1MONTH_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_MONTHLY = "loanProductCreateResponseLP1InterestDecliningPeriodSameAsPaymentRecalculation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE = "loanProductCreateResponseLP1InterestDecliningBalanceDailyRecalculationCompoundingNone";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleCustomPaymentAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE = "loanProductCreateResponseLP1InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNone";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTI_DISBURSEMENT = "loanProductCreateResponseLP1InterestDecliningBalanceDailyRecalculationSameAsRepaymentCompoundingNoneMultiDisbursement";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_REDUCE_NR_INSTALLMENTS = "loanProductCreateResponseLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleReduceNrInstallments";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_RESCHEDULE_NEXT_REPAYMENTS = "loanProductCreateResponseLP1InterestDecliningBalanceDailyRecalculationCompoundingNoneRescheduleNextRepayments";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_PERIOD_DAILY = "loanProductCreateResponseLP1InterestDecliningPeriodDaily";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_PERIOD_DAILY_ACCRUAL_ACTIVITY = "loanProductCreateResponseLP1InterestDecliningPeriodDailyAccrualActivity";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_INTEREST_DECLINING_BALANCE_DAILY_RECALCULATION_COMPOUNDING_NONE_ACCRUAL_ACTIVITY = "loanProductCreateResponseLP1InterestDecliningBalanceRecalculationCompoundingNoneAccrualActivity";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION = "loanProductCreateResponseLP2DownPaymentAutoAdvancedPaymentAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_AUTO_ADVANCED_REPAYMENT_ALLOCATION_PAYMENT_START_SUBMITTED = "loanProductCreateResponseLP2DownPaymentAutoAdvancedPaymentAllocationPaymentStartSubmitted";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION = "loanProductCreateResponseLP2DownPaymentAdvancedPaymentAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT = "loanProductCreateResponseLP2DownPayment";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST = "loanProductCreateResponseLP2DownPaymentInterest";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST_AUTO = "loanProductCreateResponseLP2DownPaymentInterestAuto";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_AUTO = "loanProductCreateResponseLP2DownPaymentAuto";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2DownPaymentProgressiveLoanSchedule";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE = "loanProductCreateResponseLP2ProgressiveLoanScheduleCustomPaymentAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_VERTICAL = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleVertical";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_INSTALLMENT_LEVEL_DELINQUENCY = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleInstallmentLevelDelinquency";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleHorizontalInstallmentLevelDelinquencyCreditAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleFixedLength";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationTillPreClose";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationTillRestFrequency";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL = "loanProductCreateResponseLP2ProgressiveLoanScheduleHorizontal";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL_LAST = "loanProductCreateResponseLP2ProgressiveLoanScheduleHorizontal";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC = "loanProductCreateResponseLP2DownPaymentInterestFlatAdvancedPaymentAllocation";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActual";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualAccrualActivity";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30 = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyTillPreClose";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyTillPreCloseLastInstallment";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_PMT_ALLOC_1 = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyTillPreClosePmtAlloc1";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SAME_AS_REP_TILL_PRECLOSE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreClose";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationDailyTillRestFrequencyDate";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_SAME_AS_REP_TILL_REST_FREQUENCY_DATE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillRestFrequencyDate";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_FULL = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefundFull";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030MultiDisburse";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030MultiDisburseDownPayment";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_365_ACTUAL = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi365Actual";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_DOWNPAYMENT = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030DownPayment";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefund";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL = "loanProductCreateResponseLP1ProgressiveLoanScheduleHorizontal";
|
||||
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreCloseWholeTerm";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = "ChargeForLoanPercentLateCreateResponse";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
|
||||
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
||||
@@ -132,5 +152,4 @@ public abstract class TestContextKey {
|
||||
public static final String TRANSACTION_EVENT = "transactionEvent";
|
||||
public static final String LOAN_WRITE_OFF_RESPONSE = "loanWriteOffResponse";
|
||||
public static final String LOAN_DELINQUENCY_ACTION_RESPONSE = "loanDelinquencyActionResponse";
|
||||
|
||||
}
|
||||
|
||||
+37
@@ -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.testrail;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
class AddResultForCaseRequest {
|
||||
|
||||
@SerializedName("status_id")
|
||||
private TestRailStatus statusId;
|
||||
|
||||
private String comment;
|
||||
}
|
||||
+32
@@ -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.testrail;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
|
||||
interface TestRailApiClient {
|
||||
|
||||
@Headers({ "Content-Type:application/json" })
|
||||
@POST("/api/v2/add_result_for_case/{runId}/{caseId}")
|
||||
Call<Void> addResultForCase(@Path("runId") int runId, @Path("caseId") int caseId, @Body AddResultForCaseRequest request);
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT 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.testrail;
|
||||
|
||||
import io.cucumber.java.Scenario;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.ResponseBody;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.junit.runner.Result;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.stereotype.Component;
|
||||
import retrofit2.Response;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Conditional(TestRailEnabledCondition.class)
|
||||
public class TestRailClient implements InitializingBean {
|
||||
|
||||
public static final Pattern TESTRAIL_TAG_PATTERN = Pattern.compile("@TestRailId:C([0-9]+)");
|
||||
private static final String SUCCESS_COMMENT = "Test passed";
|
||||
private static final String FAILED_COMMENT = "Test failed";
|
||||
|
||||
private final TestRailProperties testRailProperties;
|
||||
private final TestRailApiClient apiClient;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
log.warn("Configured TestRail Run ID: '{}'", testRailProperties.getRunId());
|
||||
}
|
||||
|
||||
public void saveScenarioResult(Scenario scenario) {
|
||||
Integer caseId = getScenarioCaseId(scenario);
|
||||
|
||||
AddResultForCaseRequest request;
|
||||
if (scenario.isFailed()) {
|
||||
request = createFailedRequest(scenario);
|
||||
} else {
|
||||
request = createSuccessRequest(scenario);
|
||||
}
|
||||
|
||||
if (caseId != null) {
|
||||
try {
|
||||
Response<Void> response = apiClient.addResultForCase(testRailProperties.getRunId(), caseId, request).execute();
|
||||
if (response.code() != HttpStatus.SC_OK) {
|
||||
handleApiError(response);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error while reporting to TestRail", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Integer getScenarioCaseId(Scenario scenario) {
|
||||
Integer caseId = null;
|
||||
for (String s : scenario.getSourceTagNames()) {
|
||||
if (s.contains("TestRail")) {
|
||||
Matcher matcher = TESTRAIL_TAG_PATTERN.matcher(s);
|
||||
if (matcher.matches()) {
|
||||
caseId = Integer.parseInt(matcher.group(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return caseId;
|
||||
}
|
||||
|
||||
private void handleApiError(Response<Void> response) throws IOException {
|
||||
String exceptionMsg = "Error while reporting to TestRail";
|
||||
ResponseBody errorBody = response.errorBody();
|
||||
if (errorBody != null) {
|
||||
exceptionMsg += " " + errorBody.string();
|
||||
}
|
||||
throw new RuntimeException(exceptionMsg);
|
||||
}
|
||||
|
||||
private AddResultForCaseRequest createFailedRequest(Scenario scenario) {
|
||||
return new AddResultForCaseRequest.AddResultForCaseRequestBuilder().statusId(TestRailStatus.FAILED)
|
||||
.comment(createFailedComment(scenario)).build();
|
||||
}
|
||||
|
||||
private AddResultForCaseRequest createSuccessRequest(Scenario scenario) {
|
||||
return new AddResultForCaseRequest.AddResultForCaseRequestBuilder().statusId(TestRailStatus.PASSED)
|
||||
.comment(createSuccessComment(scenario)).build();
|
||||
}
|
||||
|
||||
private String createSuccessComment(Scenario scenario) {
|
||||
return SUCCESS_COMMENT;
|
||||
}
|
||||
|
||||
private String createFailedComment(Scenario scenario) {
|
||||
try {
|
||||
Class c = ClassUtils.getClass("cucumber.runtime.java.JavaHookDefinition$ScenarioAdaptor");
|
||||
Field fieldScenario = FieldUtils.getField(c, "scenario", true);
|
||||
if (fieldScenario != null) {
|
||||
|
||||
fieldScenario.setAccessible(true);
|
||||
Object objectScenario = fieldScenario.get(scenario);
|
||||
|
||||
Field fieldStepResults = objectScenario.getClass().getDeclaredField("stepResults");
|
||||
fieldStepResults.setAccessible(true);
|
||||
|
||||
ArrayList<Result> results = (ArrayList<Result>) fieldStepResults.get(objectScenario);
|
||||
for (Result result : results) {
|
||||
if (result.getFailures() != null) {
|
||||
return FAILED_COMMENT + "%n" + result.getFailures();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FAILED_COMMENT;
|
||||
|
||||
} catch (IllegalAccessException | NoSuchFieldException | ClassNotFoundException e) {
|
||||
return FAILED_COMMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.testrail;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.apache.fineract.client.auth.HttpBasicAuth;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
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 retrofit2.Retrofit;
|
||||
|
||||
@Configuration
|
||||
@Conditional(TestRailEnabledCondition.class)
|
||||
public class TestRailConfiguration {
|
||||
|
||||
@Autowired
|
||||
private TestRailProperties testRailProperties;
|
||||
|
||||
@Bean
|
||||
public TestRailApiClient testRailApiClient() {
|
||||
String testRailBaseUrl = testRailProperties.getBaseUrl();
|
||||
String testRailUsername = testRailProperties.getUsername();
|
||||
String testRailPassword = testRailProperties.getPassword();
|
||||
|
||||
if (isBlank(testRailBaseUrl)) {
|
||||
throw new IllegalStateException("TestRail base URL has not been set");
|
||||
}
|
||||
if (isBlank(testRailUsername)) {
|
||||
throw new IllegalStateException("TestRail username has not been set");
|
||||
}
|
||||
if (isBlank(testRailPassword)) {
|
||||
throw new IllegalStateException("TestRail password has not been set");
|
||||
}
|
||||
|
||||
HttpBasicAuth httpBasicAuth = new HttpBasicAuth();
|
||||
httpBasicAuth.setCredentials(testRailUsername, testRailPassword);
|
||||
OkHttpClient httpClient = new OkHttpClient.Builder().addInterceptor(httpBasicAuth).addInterceptor(new TestRailIndexPhpInterceptor())
|
||||
.build();
|
||||
|
||||
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(JSON.GsonCustomConverterFactory.create(new JSON().getGson()))
|
||||
.client(httpClient).baseUrl(testRailBaseUrl).build();
|
||||
|
||||
return retrofit.create(TestRailApiClient.class);
|
||||
}
|
||||
|
||||
// Needed otherwise Retrofit 2 will be mad on the URL query/path parameters
|
||||
private static final class TestRailIndexPhpInterceptor implements Interceptor {
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request request = chain.request();
|
||||
String finalUrl = request.url().toString().replace("api/v2", "index.php?/api/v2");
|
||||
return chain.proceed(request.newBuilder().url(finalUrl).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -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.testrail;
|
||||
|
||||
import org.apache.fineract.test.support.PropertiesCondition;
|
||||
|
||||
public class TestRailEnabledCondition extends PropertiesCondition<TestRailProperties> {
|
||||
|
||||
@Override
|
||||
protected Class<TestRailProperties> getPropertiesClass() {
|
||||
return TestRailProperties.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(TestRailProperties properties) {
|
||||
return properties.isEnabled();
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.test.testrail;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Getter
|
||||
public class TestRailProperties {
|
||||
|
||||
@Value("${fineract-test.testrail.enabled}")
|
||||
private boolean enabled;
|
||||
@Value("${fineract-test.testrail.base-url}")
|
||||
private String baseUrl;
|
||||
@Value("${fineract-test.testrail.username}")
|
||||
private String username;
|
||||
@Value("${fineract-test.testrail.password}")
|
||||
private String password;
|
||||
@Value("${fineract-test.testrail.run-id}")
|
||||
private int runId;
|
||||
}
|
||||
+34
@@ -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.testrail;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
enum TestRailStatus {
|
||||
@SerializedName("1") //
|
||||
PASSED, //
|
||||
@SerializedName("2") //
|
||||
BLOCKED, //
|
||||
@SerializedName("3") //
|
||||
UNTESTED, //
|
||||
@SerializedName("4") //
|
||||
RETEST, //
|
||||
@SerializedName("5") //
|
||||
FAILED//
|
||||
}
|
||||
@@ -1257,7 +1257,7 @@ Feature: Loan
|
||||
When Admin sets the business date to "20 June 2023"
|
||||
When Customer undo "1"th "Repayment" transaction made on "20 June 2023"
|
||||
Then Loan status will be "ACTIVE"
|
||||
Then Loan closedon_date is null
|
||||
Then Loan closedon_date is "null"
|
||||
|
||||
Scenario: As an admin I would like to delete a loan using external id
|
||||
When Admin sets the business date to the actual date
|
||||
@@ -5541,7 +5541,7 @@ Feature: Loan
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
|
||||
When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
|
||||
Then Loan Repayment schedule has 6 periods, with the following data for periods:
|
||||
@@ -5598,10 +5598,10 @@ Feature: Loan
|
||||
Scenario: Early pay-off loan with interest, TILL_REST_FREQUENCY_DATE product
|
||||
When Admin sets the business date to "01 January 2024"
|
||||
When Admin creates a client with random data
|
||||
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE | 01 January 2024 | 100 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
|
||||
When Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
|
||||
Then Loan Repayment schedule has 6 periods, with the following data for periods:
|
||||
@@ -5654,7 +5654,7 @@ Feature: Loan
|
||||
| 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false |
|
||||
| 15 February 2024 | Repayment | 84.06 | 83.57 | 0.49 | 0.0 | 0.0 | 0.0 | false |
|
||||
Then Loan's all installments have obligations met
|
||||
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY" loan product "DEFAULT" transaction type to "LAST_INSTALLMENT" future installment allocation rule
|
||||
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_REST_FREQUENCY_DATE" loan product "DEFAULT" transaction type to "LAST_INSTALLMENT" future installment allocation rule
|
||||
|
||||
Scenario: Interest recalculation - S1 daily for overdue loan
|
||||
Given Global configuration "enable-business-date" is enabled
|
||||
@@ -5662,7 +5662,7 @@ Feature: Loan
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
|
||||
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
|
||||
When Admin sets the business date to "15 July 2024"
|
||||
@@ -5685,7 +5685,7 @@ Feature: Loan
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
|
||||
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
|
||||
When Admin sets the business date to "10 March 2024"
|
||||
@@ -5708,7 +5708,7 @@ Feature: Loan
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 01 January 2024 | 100 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
|
||||
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
|
||||
When Admin sets the business date to "1 February 2024"
|
||||
@@ -5736,7 +5736,7 @@ Feature: Loan
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP1_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTIDISB | 01 January 2023 | 10000 | 12 | DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||
And Admin successfully approves the loan on "1 January 2023" with "100" amount and expected disbursement date on "1 January 2023"
|
||||
When Admin successfully disburse the loan on "1 January 2023" with "100" EUR transaction amount and "50" fixed emi amount
|
||||
And Admin successfully disburse the loan on "1 January 2023" with "100" EUR transaction amount and "50" fixed emi amount
|
||||
Then Loan emi amount variations has 1 variation, with the following data:
|
||||
| Term Type Id | Term Type Code | Term Type Value | Applicable From | Decimal Value | Date Value | Is Specific To Installment | Is Processed |
|
||||
| 1 | loanTermType.emiAmount | emiAmount | 01 January 2023 | 50.0 | | false | |
|
||||
@@ -5750,7 +5750,7 @@ Feature: Loan
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP1_INTEREST_DECLINING_BALANCE_SAR_RECALCULATION_SAME_AS_REPAYMENT_COMPOUNDING_NONE_MULTIDISB | 01 January 2023 | 10000 | 12 | DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | PENALTIES_FEES_INTEREST_PRINCIPAL_ORDER |
|
||||
And Admin successfully approves the loan on "1 January 2023" with "100" amount and expected disbursement date on "1 January 2023"
|
||||
When Admin successfully disburse the loan on "1 January 2023" with "100" EUR transaction amount, "50" EUR fixed emi amount and adjust repayment date on "15 January 2023"
|
||||
And Admin successfully disburse the loan on "1 January 2023" with "100" EUR transaction amount, "50" EUR fixed emi amount and adjust repayment date on "15 January 2023"
|
||||
Then Loan term variations has 2 variation, with the following data:
|
||||
| Term Type Id | Term Type Code | Term Type Value | Applicable From | Decimal Value | Date Value | Is Specific To Installment | Is Processed |
|
||||
| 1 | loanTermType.emiAmount | emiAmount | 01 January 2023 | 50.0 | | false | |
|
||||
@@ -5838,4 +5838,4 @@ Feature: Loan
|
||||
| 15 January 2024 | Repayment | 1.5 | 1.5 | 0.0 | 0.0 | 0.0 | 83.5 |
|
||||
| 15 January 2024 | Repayment | 83.76 | 83.5 | 0.26 | 0.0 | 0.0 | 0.0 |
|
||||
| 15 January 2024 | Accrual | 0.26 | 0.0 | 0.26 | 0.0 | 0.0 | 0.0 |
|
||||
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
|
||||
|
||||
@@ -173,8 +173,7 @@ Feature: LoanCharge
|
||||
| NSF fee | true | Specified due date | 23 October 2022 | Flat | 10.0 | 10.0 | 0.0 | 0.0 |
|
||||
#
|
||||
## charge adjustment with 8 will fail
|
||||
When Admin makes a charge adjustment for the last "LOAN_NSF_FEE" type charge which is due on "23 October 2022" with transaction amount higher than the available charge amount
|
||||
|
||||
When Charge adjustment for the last "LOAN_NSF_FEE" type charge which is due on "23 October 2022" with transaction amount 8 which is higher than the available charge amount results an ERROR
|
||||
## revert last charge adjustment (was amount 3)
|
||||
When Admin reverts the charge adjustment which was raised on "04 November 2022" with 3 EUR transaction amount
|
||||
Then Loan has 1002 outstanding amount
|
||||
@@ -1678,7 +1677,7 @@ Feature: LoanCharge
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_CUST_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 27 Sep 2024 | 100 | 9.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 1 | MONTHS | 1 | MONTHS | 1 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 27 Sep 2024 | 100 | 9.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 1 | MONTHS | 1 | MONTHS | 1 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "27 September 2024" with "40" amount and expected disbursement date on "27 September 2024"
|
||||
When Admin successfully disburse the loan on "27 September 2024" with "40" EUR transaction amount
|
||||
Then Loan Repayment schedule has 1 periods, with the following data for periods:
|
||||
@@ -1691,7 +1690,6 @@ Feature: LoanCharge
|
||||
Then Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||
| 27 September 2024 | Disbursement | 40.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 |
|
||||
| 27 September 2024 | Accrual | 0.33 | 0.0 | 0.33 | 0.0 | 0.0 | 0.0 |
|
||||
When Admin adds "LOAN_NSF_FEE" due date charge with "27 September 2024" due date and 1 EUR transaction amount
|
||||
When Admin makes a charge adjustment for the last "LOAN_NSF_FEE" type charge which is due on "27 September 2024" with 1 EUR transaction amount and externalId ""
|
||||
Then Loan has 40.32 outstanding amount
|
||||
@@ -1705,6 +1703,4 @@ Feature: LoanCharge
|
||||
Then Loan Transactions tab has the following data:
|
||||
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
|
||||
| 27 September 2024 | Disbursement | 40.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 |
|
||||
| 27 September 2024 | Accrual | 0.33 | 0.0 | 0.33 | 0.0 | 0.0 | 0.0 |
|
||||
| 27 September 2024 | Accrual | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
|
||||
| 27 September 2024 | Charge Adjustment | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 39.0 |
|
||||
| 27 September 2024 | Charge Adjustment | 1.0 | 1.0 | 0.0 | 0.0 | 0.0 | 39.0 |
|
||||
|
||||
@@ -3250,7 +3250,7 @@ Feature: LoanRepayment
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 23 July 2024 | 150 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 1 | MONTHS | 1 | MONTHS | 1 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LP1_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 23 July 2024 | 150 | 0 | FLAT | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 1 | MONTHS | 1 | MONTHS | 1 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
# --- 7/23 - Disbursement for 111.92 EUR ---
|
||||
And Admin successfully approves the loan on "23 July 2024" with "111.92" amount and expected disbursement date on "23 July 2024"
|
||||
When Admin successfully disburse the loan on "23 July 2024" with "111.92" EUR transaction amount
|
||||
@@ -3386,8 +3386,8 @@ Feature: LoanRepayment
|
||||
When Admin sets the business date to "23 June 2024"
|
||||
When Admin creates a client with random data
|
||||
When Admin creates a fully customized loan with the following data:
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 23 June 2024 | 400 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
|
||||
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE | 23 June 2024 | 400 | 7.0 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
|
||||
And Admin successfully approves the loan on "23 June 2024" with "400" amount and expected disbursement date on "23 June 2024"
|
||||
When Admin successfully disburse the loan on "23 June 2024" with "400" EUR transaction amount
|
||||
When Admin sets the business date to "24 June 2024"
|
||||
|
||||
Reference in New Issue
Block a user