Skip to content

Commit 7f3d40d

Browse files
authored
Merge pull request #5727
FINERACT-2305: Add a feature flag with global configuration for accru…
2 parents a804849 + 1a15618 commit 7f3d40d

24 files changed

Lines changed: 569 additions & 406 deletions

File tree

fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/api/GlobalConfigurationConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public final class GlobalConfigurationConstants {
8585
public static final String FORCE_WITHDRAWAL_ON_SAVINGS_ACCOUNT = "allow-force-withdrawal-on-savings-account";
8686
public static final String FORCE_WITHDRAWAL_ON_SAVINGS_ACCOUNT_LIMIT = "force-withdrawal-on-savings-account-limit";
8787
public static final String FORCE_PASSWORD_RESET_ON_FIRST_LOGIN = "force-password-reset-on-first-login";
88+
public static final String ALLOW_CASH_AND_NON_CASH_ACCRUAL = "allow-cash-and-non-cash-accrual";
8889

8990
private GlobalConfigurationConstants() {}
9091
}

fineract-core/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,6 @@ public interface ConfigurationDomainService {
163163
boolean isMaxLoginRetriesEnabled();
164164

165165
Integer retrieveMaxLoginRetries();
166+
167+
boolean isAllowCashAndNonCashAccrual();
166168
}

fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/GlobalConfigurationGlobalInitializerStep.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class GlobalConfigurationGlobalInitializerStep implements FineractGlobalI
3636
public static final String CONFIG_KEY_DAYS_BEFORE_REPAYMENT_IS_DUE = "days-before-repayment-is-due";
3737
public static final String CONFIG_KEY_DAYS_AFTER_REPAYMENT_IS_OVERDUE = "days-after-repayment-is-overdue";
3838
public static final String CONFIG_KEY_ENABLE_AUTO_GENERATED_EXTERNAL_ID = "enable-auto-generated-external-id";
39+
public static final String CONFIG_KEY_ALLOW_CASH_AND_NON_CASH_ACCRUAL = "allow-cash-and-non-cash-accrual";
3940

4041
private final GlobalConfigurationHelper globalConfigurationHelper;
4142

@@ -48,5 +49,6 @@ public void initialize() throws Exception {
4849
globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_DAYS_BEFORE_REPAYMENT_IS_DUE, 1L);
4950
globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_DAYS_AFTER_REPAYMENT_IS_OVERDUE, 2L);
5051
globalConfigurationHelper.enableGlobalConfiguration(CONFIG_KEY_ENABLE_AUTO_GENERATED_EXTERNAL_ID, 0L);
52+
globalConfigurationHelper.disableGlobalConfiguration(CONFIG_KEY_ALLOW_CASH_AND_NON_CASH_ACCRUAL, 0L);
5153
}
5254
}

fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff-Part3.feature

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,9 +1868,7 @@ Feature: Charge-off - Part3
18681868
And Loan Transactions tab has the following data:
18691869
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
18701870
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
1871-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
18721871
| 15 January 2024 | Repayment | 17.01 | 16.75 | 0.26 | 0.0 | 0.0 | 83.25 | false | false |
1873-
| 01 March 2024 | Accrual Adjustment | 1.03 | 0.0 | 1.03 | 0.0 | 0.0 | 0.0 | false | false |
18741872
| 01 March 2024 | Charge-off | 84.99 | 83.25 | 1.74 | 0.0 | 0.0 | 0.0 | false | false |
18751873

18761874
@TestRailId:C3513

fineract-e2e-tests-runner/src/test/resources/features/LoanChargesDisbursement.feature

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,6 @@ Feature: LoanChargesDisbursementCharges
354354
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
355355
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
356356
| 01 January 2024 | Repayment (at time of disbursement) | 0.02 | 0.0 | 0.0 | 0.02 | 0.0 | 100.0 | false | false |
357-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
358357
Then Loan Charges tab has the following data:
359358
| Name | isPenalty | Payment due at | Due as of | Calculation type | Due | Paid | Waived | Outstanding |
360359
| Disbursement Charge | false | Disbursement | | % Interest | 0.02 | 0.02 | 0.0 | 0.0 |
@@ -363,7 +362,6 @@ Feature: LoanChargesDisbursementCharges
363362
| Type | Account code | Account name | Debit | Credit |
364363
| INCOME | 404007 | Fee Income | | 0.02 |
365364
| LIABILITY | 145023 | Suspense/Clearing account | 0.02 | |
366-
Then Loan Transactions tab has a "ACCRUAL" transaction with date "01 January 2024" has no the Journal entries
367365
# --- 1st repayment - 1 February, 2024 ---
368366
When Admin sets the business date to "01 February 2024"
369367
And Customer makes "AUTOPAY" repayment on "01 February 2024" with 17.01 EUR transaction amount
@@ -383,7 +381,6 @@ Feature: LoanChargesDisbursementCharges
383381
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
384382
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
385383
| 01 January 2024 | Repayment (at time of disbursement) | 0.02 | 0.0 | 0.0 | 0.02 | 0.0 | 100.0 | false | false |
386-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
387384
| 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false |
388385
# --- 2nd repayment - 1 March, 2024 ---
389386
When Admin sets the business date to "01 March 2024"
@@ -404,7 +401,6 @@ Feature: LoanChargesDisbursementCharges
404401
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
405402
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
406403
| 01 January 2024 | Repayment (at time of disbursement) | 0.02 | 0.0 | 0.0 | 0.02 | 0.0 | 100.0 | false | false |
407-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
408404
| 01 February 2024 | Repayment | 17.01 | 16.43 | 0.58 | 0.0 | 0.0 | 83.57 | false | false |
409405
| 01 March 2024 | Repayment | 17.01 | 16.52 | 0.49 | 0.0 | 0.0 | 67.05 | false | false |
410406
When Loan Pay-off is made on "01 March 2024"

fineract-e2e-tests-runner/src/test/resources/features/LoanChargesProgressiveLoan.feature

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,17 +1740,13 @@ Feature: LoanChargesProgressiveLoan
17401740
And Loan Transactions tab has the following data:
17411741
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
17421742
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
1743-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
1744-
| 01 March 2024 | Accrual Adjustment | 0.89 | 0.0 | 0.89 | 0.0 | 0.0 | 0.0 | false | false |
17451743
| 01 March 2024 | Charge-off | 107.14 | 100.0 | 2.14 | 5.0 | 0.0 | 0.0 | false | false |
17461744
When Admin makes a charge adjustment for the last "LOAN_SNOOZE_FEE" type charge which is due on "01 March 2024" with 5 EUR transaction amount and externalId ""
17471745
Then Charge adjustment response has the subResourceExternalId
17481746
Then Loan has 1 "CHARGE_ADJUSTMENT" transactions on Transactions tab
17491747
And Loan Transactions tab has the following data:
17501748
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
17511749
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
1752-
| 01 January 2024 | Accrual | 2.05 | 0.0 | 2.05 | 0.0 | 0.0 | 0.0 | false | false |
1753-
| 01 March 2024 | Accrual Adjustment | 0.89 | 0.0 | 0.89 | 0.0 | 0.0 | 0.0 | false | false |
17541750
| 01 March 2024 | Charge-off | 107.14 | 100.0 | 2.14 | 5.0 | 0.0 | 0.0 | false | false |
17551751
| 01 March 2024 | Charge Adjustment | 5.0 | 5.0 | 0.0 | 0.0 | 0.0 | 95.0 | false | false |
17561752
When Loan Pay-off is made on "01 March 2024"

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.apache.commons.lang3.NotImplementedException;
6868
import org.apache.commons.lang3.ObjectUtils;
6969
import org.apache.commons.lang3.tuple.Pair;
70+
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
7071
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
7172
import org.apache.fineract.infrastructure.core.service.DateUtils;
7273
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
@@ -142,18 +143,21 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
142143
private final LoanChargeService loanChargeService;
143144
private final SingleLoanChargeRepaymentScheduleProcessingWrapper loanChargeRepaymentScheduleProcessing;
144145
private final ScheduledDateGenerator scheduledDateGenerator;
146+
private final ConfigurationDomainService configurationDomainService;
145147

146148
public AdvancedPaymentScheduleTransactionProcessor(final EMICalculator emiCalculator, final InterestRefundService interestRefundService,
147149
final ExternalIdFactory externalIdFactory, final LoanScheduleComponent loanSchedule,
148150
final LoanChargeValidator loanChargeValidator, final LoanBalanceService loanBalanceService,
149-
final LoanChargeService loanChargeService, ScheduledDateGenerator scheduledDateGenerator) {
151+
final LoanChargeService loanChargeService, ScheduledDateGenerator scheduledDateGenerator,
152+
ConfigurationDomainService configurationDomainService) {
150153
super(externalIdFactory, loanChargeValidator, loanBalanceService);
151154
this.emiCalculator = emiCalculator;
152155
this.interestRefundService = interestRefundService;
153156
this.loanSchedule = loanSchedule;
154157
this.loanChargeService = loanChargeService;
155158
this.loanChargeRepaymentScheduleProcessing = new SingleLoanChargeRepaymentScheduleProcessingWrapper();
156159
this.scheduledDateGenerator = scheduledDateGenerator;
160+
this.configurationDomainService = configurationDomainService;
157161
}
158162

159163
@Override
@@ -3585,6 +3589,13 @@ private BigDecimal getInterestTillChargeOffForPeriod(final Loan loan, final Loca
35853589
private void createMissingAccrualTransactionDuringChargeOffIfNeeded(final BigDecimal newInterest,
35863590
final LoanTransaction chargeOffTransaction, final LocalDate chargeOffDate, final TransactionCtx ctx) {
35873591
final Loan loan = chargeOffTransaction.getLoan();
3592+
final boolean accrualAllowed = configurationDomainService.isAllowCashAndNonCashAccrual()
3593+
? loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()
3594+
|| loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()
3595+
: loan.isUpfrontAccrualAccountingEnabledOnLoanProduct() || loan.isPeriodicAccrualAccountingEnabledOnLoanProduct();
3596+
if (!accrualAllowed) {
3597+
return;
3598+
}
35883599
final List<LoanRepaymentScheduleInstallment> relevantInstallments = loan.getRepaymentScheduleInstallments().stream()
35893600
.filter(i -> !i.getFromDate().isAfter(chargeOffDate)).toList();
35903601

fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import java.util.Map;
4949
import java.util.Set;
5050
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
51+
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
5152
import org.apache.fineract.infrastructure.core.domain.ActionContext;
5253
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
5354
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
@@ -121,7 +122,8 @@ public static void destruct() {
121122
public void setUp() {
122123
underTest = new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, Mockito.mock(InterestRefundService.class),
123124
Mockito.mock(ExternalIdFactory.class), Mockito.mock(LoanScheduleComponent.class), Mockito.mock(LoanChargeValidator.class),
124-
Mockito.mock(LoanBalanceService.class), Mockito.mock(LoanChargeService.class), Mockito.mock(ScheduledDateGenerator.class));
125+
Mockito.mock(LoanBalanceService.class), Mockito.mock(LoanChargeService.class), Mockito.mock(ScheduledDateGenerator.class),
126+
Mockito.mock(ConfigurationDomainService.class));
125127

126128
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
127129
ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
@@ -534,8 +536,6 @@ public void testDisbursementAfterMaturityDateWithEMICalculator() {
534536
Money disbursementMoney = Money.of(currency, postMaturityDisbursementAmount);
535537

536538
LoanProductRelatedDetail loanProductRelatedDetail = mock(LoanProductRelatedDetail.class);
537-
org.apache.fineract.portfolio.loanproduct.domain.LoanProduct loanProduct = mock(
538-
org.apache.fineract.portfolio.loanproduct.domain.LoanProduct.class);
539539
when(loanProductRelatedDetail.getInstallmentAmountInMultiplesOf()).thenReturn(null);
540540
when(loanProductRelatedDetail.isEnableDownPayment()).thenReturn(false);
541541

fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,4 +586,9 @@ public Integer retrieveMaxLoginRetries() {
586586
GlobalConfigurationConstants.MAX_LOGIN_RETRY_ATTEMPTS);
587587
return property.getValue() == null ? null : property.getValue().intValue();
588588
}
589+
590+
@Override
591+
public boolean isAllowCashAndNonCashAccrual() {
592+
return getGlobalConfigurationPropertyData(GlobalConfigurationConstants.ALLOW_CASH_AND_NON_CASH_ACCRUAL).isEnabled();
593+
}
589594
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ public void reprocessExistingAccruals(@NonNull final Loan loan, final boolean ad
209209
if (!accrualTransactions.isEmpty()) {
210210
if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
211211
reprocessPeriodicAccruals(loan, accrualTransactions, addEvent);
212-
} else if (loan.isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
212+
} else if (configurationDomainService.isAllowCashAndNonCashAccrual() ? !loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()
213+
: loan.isUpfrontAccrualAccountingEnabledOnLoanProduct()) {
213214
reprocessNonPeriodicAccruals(loan, accrualTransactions, addEvent);
214215
}
215216
}

0 commit comments

Comments
 (0)