FINERACT-1668: Adding Configuration for reversal transaction (#2454)

Co-authored-by: Dhaval Maniyar <dhavalmaniyar@Dhavals-MacBook-Pro.local>
This commit is contained in:
logoutdhaval
2022-08-05 16:36:40 +05:30
committed by GitHub
co-authored by Dhaval Maniyar
parent e15459c659
commit 4685e96c81
12 changed files with 162 additions and 44 deletions
@@ -116,4 +116,6 @@ public interface ConfigurationDomainService {
boolean isBusinessDateEnabled();
boolean isCOBDateAdjustmentEnabled();
boolean isReversalTransactionAllowed();
}
@@ -444,4 +444,11 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
public boolean isCOBDateAdjustmentEnabled() {
return getGlobalConfigurationPropertyData(ENABLE_AUTOMATIC_COB_DATE_ADJUSTMENT).isEnabled();
}
@Override
public boolean isReversalTransactionAllowed() {
final String propertyName = "enable-post-reversal-txns-for-reverse-transactions";
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(propertyName);
return property.isEnabled();
}
}
@@ -140,7 +140,6 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
boolean isAccountTransfer = false;
final boolean isPreMatureClosure = false;
final MathContext mc = MathContext.DECIMAL64;
@@ -348,7 +347,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final boolean postReversals = false;
boolean isRegularTransaction = false;
boolean isAccountTransfer = false;
final boolean isPreMatureClosure = false;
@@ -364,7 +363,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName);
Long savingsTransactionId = null;
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, closedDate);
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, closedDate, postReversals);
final BigDecimal transactionAmount = account.getAccountBalance();
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
@@ -385,7 +384,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence());
frequency = frequency == -1 ? 1 : frequency;
reinvestedDeposit.generateSchedule(frequencyType, frequency, calendar);
reinvestedDeposit.processAccountUponActivation(fmt, user);
reinvestedDeposit.processAccountUponActivation(fmt, user, postReversals);
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
this.savingsAccountRepository.save(reinvestedDeposit);
@@ -520,7 +519,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final boolean postReversals = false;
boolean isAccountTransfer = false;
final boolean isPreMatureClosure = true;
boolean isRegularTransaction = false;
@@ -537,7 +536,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
Long savingsTransactionId = null;
// post interest
account.postPreMaturityInterest(closedDate, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
financialYearBeginningMonth, postReversals);
final Integer closureTypeValue = command.integerValueOfParameterNamed(DepositsApiConstants.onAccountClosureIdParamName);
DepositAccountOnClosureType closureType = DepositAccountOnClosureType.fromInt(closureTypeValue);
@@ -39,6 +39,7 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
@@ -77,6 +78,8 @@ public class FixedDepositAccount extends SavingsAccount {
@Transient
protected InterestRateChartAssembler chartAssembler;
@Transient
private ConfigurationDomainService configurationDomainService;
protected FixedDepositAccount() {
//
@@ -270,11 +270,11 @@ public class RecurringDepositAccount extends SavingsAccount {
}
}
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth,
final boolean postReversals) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.updateMaturityDetailsAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.active.state");
@@ -287,7 +287,7 @@ public class RecurringDepositAccount extends SavingsAccount {
if (!this.maturityDate().isAfter(todayDate)) {
// update account status
this.status = SavingsAccountStatusType.MATURED.getValue();
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, todayDate);
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, todayDate, postReversals);
}
}
@@ -537,7 +537,7 @@ public class RecurringDepositAccount extends SavingsAccount {
return Money.of(this.currency, this.minRequiredOpeningBalance);
}
protected void processAccountUponActivation(final DateTimeFormatter fmt, final AppUser user) {
protected void processAccountUponActivation(final DateTimeFormatter fmt, final AppUser user, final boolean postReversals) {
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance);
final boolean backdatedTxnsAllowedTill = false;
String refNo = null;
@@ -549,7 +549,6 @@ public class RecurringDepositAccount extends SavingsAccount {
// update existing transactions so derived balance fields are
// correct.
boolean postReversals = false;
recalculateDailyBalances(Money.zero(this.currency), DateUtils.getBusinessLocalDate(), backdatedTxnsAllowedTill, postReversals);
}
}
@@ -635,7 +634,7 @@ public class RecurringDepositAccount extends SavingsAccount {
}
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth,
final LocalDate closeDate) {
final LocalDate closeDate, final boolean postReversals) {
LocalDate interestPostingUpToDate = maturityDate();
if (interestPostingUpToDate == null) {
interestPostingUpToDate = closeDate;
@@ -645,7 +644,6 @@ public class RecurringDepositAccount extends SavingsAccount {
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
final boolean backdatedTxnsAllowedTill = false;
boolean postReversals = false;
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate.minusDays(1), isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill,
postReversals);
@@ -690,7 +688,7 @@ public class RecurringDepositAccount extends SavingsAccount {
}
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth, boolean postReversals) {
final Money interestPostedToDate = totalInterestPosted();
// calculate interest before one day of closure date
@@ -713,7 +711,6 @@ public class RecurringDepositAccount extends SavingsAccount {
}
applyWithholdTaxForDepositAccounts(accountCloseDate, recalucateDailyBalance, backdatedTxnsAllowedTill);
boolean postReversals = false;
if (recalucateDailyBalance) {
// update existing transactions so derived balance fields are
// correct.
@@ -755,11 +752,11 @@ public class RecurringDepositAccount extends SavingsAccount {
return interestOnMaturity;
}
@Override
public void postInterest(final MathContext mc, final LocalDate postingDate, final boolean isInterestTransfer,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth,
final LocalDate postInterestAson, final boolean backdatedTxnsAllowedTill) {
final LocalDate postInterestAson, final boolean backdatedTxnsAllowedTill, final boolean postReversals) {
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
boolean postReversals = false;
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestAson, backdatedTxnsAllowedTill, postReversals);
}
@@ -977,7 +977,6 @@ public class SavingsAccount extends AbstractPersistableCustom {
protected void recalculateDailyBalances(final Money openingAccountBalance, final LocalDate interestPostingUpToDate,
final boolean backdatedTxnsAllowedTill, boolean postReversals) {
Money runningBalance = openingAccountBalance.copy();
List<SavingsAccountTransaction> accountTransactionsSorted = null;
@@ -2775,6 +2774,7 @@ public class SavingsAccount extends AbstractPersistableCustom {
private void payActivationCharges(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth,
final AppUser user, final boolean backdatedTxnsAllowedTill) {
boolean isSavingsChargeApplied = false;
boolean postReversals = false;
UUID refNo = UUID.randomUUID();
for (SavingsAccountCharge savingsAccountCharge : this.charges()) {
if (savingsAccountCharge.isSavingsActivation()) {
@@ -2788,7 +2788,6 @@ public class SavingsAccount extends AbstractPersistableCustom {
final MathContext mc = MathContext.DECIMAL64;
boolean isInterestTransfer = false;
LocalDate postInterestAsOnDate = null;
boolean postReversals = false;
if (this.isBeforeLastPostingPeriod(getActivationLocalDate(), backdatedTxnsAllowedTill)) {
final LocalDate today = DateUtils.getBusinessLocalDate();
this.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
@@ -3551,12 +3550,12 @@ public class SavingsAccount extends AbstractPersistableCustom {
this.closedOnDate = DateUtils.getBusinessLocalDate();
this.closedBy = appUser;
boolean postInterestAsOnDate = false;
boolean postReversals = false;
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
if (this.getSummary().getAccountBalance(this.getCurrency()).isGreaterThanZero()) {
SavingsAccountTransaction transaction = SavingsAccountTransaction.escheat(this, transactionDate, appUser, postInterestAsOnDate);
this.transactions.add(transaction);
}
boolean postReversals = false;
recalculateDailyBalances(Money.zero(this.currency), transactionDate, false, postReversals);
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
}
@@ -92,6 +92,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Long relaxingDaysConfigForPivotDate = this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
final boolean postReversals = this.configurationDomainService.isReversalTransactionAllowed();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
if (transactionBooleanValues.isRegularTransaction() && !account.allowWithdrawal()) {
throw new DepositAccountTransactionNotAllowedException(account.getId(), "withdraw", account.depositAccountType());
@@ -115,7 +116,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final MathContext mc = MathContext.DECIMAL64;
final LocalDate today = DateUtils.getBusinessLocalDate();
boolean postReversals = false;
if (account.isBeforeLastPostingPeriod(transactionDate, backdatedTxnsAllowedTill)) {
account.postInterest(mc, today, transactionBooleanValues.isInterestTransfer(), isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate, backdatedTxnsAllowedTill, postReversals);
@@ -202,7 +203,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final MathContext mc = MathContext.DECIMAL64;
final LocalDate today = DateUtils.getBusinessLocalDate();
boolean postReversals = false;
boolean postReversals = this.configurationDomainService.isReversalTransactionAllowed();
if (account.isBeforeLastPostingPeriod(transactionDate, backdatedTxnsAllowedTill)) {
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, backdatedTxnsAllowedTill, postReversals);
@@ -297,6 +298,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final Long relaxingDaysConfigForPivotDate = this.configurationDomainService.retrieveRelaxingDaysConfigForPivotDate();
final boolean postReversals = true;
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
@@ -314,7 +316,9 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
chargePaidBySet = savingsAccountTransaction.getSavingsAccountChargesPaid();
reversal.getSavingsAccountChargesPaid().addAll(chargePaidBySet);
account.undoTransaction(savingsAccountTransaction);
newTransactions.add(reversal);
if (postReversals) {
newTransactions.add(reversal);
}
}
boolean isInterestTransfer = false;
@@ -322,7 +326,6 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final LocalDate today = DateUtils.getBusinessLocalDate();
final MathContext mc = new MathContext(15, MoneyHelper.getRoundingMode());
for (SavingsAccountTransaction savingsAccountTransaction : savingsAccountTransactions) {
boolean postReversals = true;
if (savingsAccountTransaction.isPostInterestCalculationRequired()
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), backdatedTxnsAllowedTill)) {
@@ -151,7 +151,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final boolean postReversals = false;
this.depositAccountTransactionDataValidator.validateActivation(command);
final MathContext mc = MathContext.DECIMAL64;
final FixedDepositAccount account = (FixedDepositAccount) this.depositAccountAssembler.assembleFrom(savingsId,
@@ -189,7 +189,6 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
}
final boolean isInterestTransfer = false;
final LocalDate postInterestOnDate = null;
final boolean postReversals = false;
if (activationChargeAmount.isGreaterThanZero()) {
payActivationCharge(account, user);
}
@@ -259,7 +258,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final boolean postReversals = false;
this.depositAccountTransactionDataValidator.validateActivation(command);
final RecurringDepositAccount account = (RecurringDepositAccount) this.depositAccountAssembler.assembleFrom(savingsId,
@@ -317,11 +316,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
account.updateOverduePayments(overdueUptoDate);
final boolean isInterestTransfer = false;
final LocalDate postInterestOnDate = null;
boolean postReversals = false;
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate(), false)) {
final LocalDate today = DateUtils.getBusinessLocalDate();
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, false);
postInterestOnDate, false, postReversals);
} else {
final LocalDate today = DateUtils.getBusinessLocalDate();
account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
@@ -473,7 +471,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
checkClientOrGroupActive(account);
final LocalDate today = DateUtils.getBusinessLocalDate();
boolean postReversals = false;
final boolean postReversals = false;
final MathContext mc = new MathContext(15, MoneyHelper.getRoundingMode());
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
@@ -521,7 +519,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final MathContext mc = new MathContext(10, MoneyHelper.getRoundingMode());
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
boolean postReversals = false;
final boolean postReversals = false;
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, false, postReversals);
this.savingAccountRepositoryWrapper.saveAndFlush(account);
@@ -573,11 +571,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
checkClientOrGroupActive(account);
boolean postReversals = false;
final boolean postReversals = false;
if (savingsAccountTransaction.isPostInterestCalculationRequired()
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) {
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, false);
postInterestOnDate, false, postReversals);
} else {
account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate, false, postReversals);
@@ -686,11 +684,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final Long newtransactionId = saveTransactionToGenerateTransactionId(transaction);
boolean isInterestTransfer = false;
final LocalDate postInterestOnDate = null;
boolean postReversals = false;
final boolean postReversals = false;
if (account.isBeforeLastPostingPeriod(transactionDate, false)
|| account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate(), false)) {
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
postInterestOnDate, false);
postInterestOnDate, false, postReversals);
} else {
account.calculateInterestUsing(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate, false, postReversals);
@@ -915,7 +913,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
final MathContext mc = MathContext.DECIMAL64;
boolean isInterestTransfer = false;
boolean postReversals = false;
final boolean postReversals = false;
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth, postInterestOnDate, false, postReversals);
@@ -947,7 +945,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
savingsAccount.office(), transferDate, user);
savingsAccount.addTransaction(withdrawtransferTransaction);
savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
boolean postReversals = false;
final boolean postReversals = false;
final MathContext mc = MathContext.DECIMAL64;
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
@@ -993,7 +991,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
savingsAccount.reassignSavingsOfficer(fieldOfficer, transferDate);
}
boolean isInterestTransfer = false;
boolean postReversals = false;
final boolean postReversals = false;
LocalDate postInterestOnDate = null;
final MathContext mc = MathContext.DECIMAL64;
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
@@ -1150,7 +1148,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
final MathContext mc = MathContext.DECIMAL64;
boolean postReversals = false;
final boolean postReversals = false;
if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate(), false)) {
final LocalDate today = DateUtils.getBusinessLocalDate();
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
@@ -1290,7 +1288,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
boolean isInterestTransfer = false;
LocalDate postInterestOnDate = null;
final MathContext mc = MathContext.DECIMAL64;
boolean postReversals = false;
final boolean postReversals = false;
if (account.isBeforeLastPostingPeriod(transactionDate, false)) {
final LocalDate today = DateUtils.getBusinessLocalDate();
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth,
@@ -1321,7 +1319,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
final boolean postReversals = false;
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(depositAccountId, depositAccountType);
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
@@ -1356,7 +1354,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
}
} else if (depositAccountType.isRecurringDeposit()) {
((RecurringDepositAccount) account).updateMaturityStatus(isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
financialYearBeginningMonth, postReversals);
}
this.savingAccountRepositoryWrapper.saveAndFlush(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
@@ -45,4 +45,5 @@
<include file="parts/0023_use_the_proper_date_or_datetime_type.xml" relativeToChangelogFile="true"/>
<include file="parts/0024_add_audit_entries.xml" relativeToChangelogFile="true"/>
<include file="parts/0025_add_audit_entries_to_journal_entry.xml" relativeToChangelogFile="true"/>
<include file="parts/0026_reversals_for_reversed_transactions.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet author="fineract" id="1">
<insert tableName="c_configuration">
<column name="id" valueNumeric="46"/>
<column name="name" value="enable-post-reversal-txns-for-reverse-transactions"/>
<column name="value"/>
<column name="date_value"/>
<column name="string_value"/>
<column name="enabled" valueBoolean="false"/>
<column name="is_trap_door" valueBoolean="false"/>
<column name="description"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -2990,6 +2990,70 @@ public class ClientSavingsIntegrationTest {
assertEquals("error.msg.savings.transaction.is.not.allowed", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
}
@Test
public void testReversalEntriesAfterSystemReversingTransactionWithReversalConfigOn() {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.savingsProductHelper = new SavingsProductHelper();
this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "46", true);
LocalDate transactionDate = LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
LocalDate nextTransactionDate = transactionDate.plusDays(2);
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy");
String startDate = formatter.format(transactionDate);
String nxtTransaction = formatter.format(nextTransactionDate);
final String jobName = "Post Interest For Savings";
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDate);
Assertions.assertNotNull(clientID);
final Integer savingsId = createSavingsAccountDailyPostingOverdraft(clientID, startDate);
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
this.scheduleJobHelper.executeAndAwaitJob(jobName);
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", nxtTransaction, CommonConstants.RESPONSE_RESOURCE_ID);
List<HashMap> transactions = this.savingsAccountHelper.getSavingsTransactions(savingsId);
boolean reversalFlag = false;
for (int i = 0; i < transactions.size(); i++) {
boolean isReversal = (boolean) transactions.get(i).get("isReversal");
if (isReversal) {
reversalFlag = true;
break;
}
}
Assertions.assertTrue(reversalFlag);
}
@Test
public void testReversalEntriesAfterSystemReversingTransactionWithReversalConfigOff() {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.savingsProductHelper = new SavingsProductHelper();
this.scheduleJobHelper = new SchedulerJobHelper(requestSpec);
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "46", false);
LocalDate transactionDate = LocalDate.now(Utils.getZoneIdOfTenant()).minusDays(5);
LocalDate nextTransactionDate = transactionDate.plusDays(2);
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy");
String startDate = formatter.format(transactionDate);
String nxtTransaction = formatter.format(nextTransactionDate);
final String jobName = "Post Interest For Savings";
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDate);
Assertions.assertNotNull(clientID);
final Integer savingsId = createSavingsAccountDailyPostingOverdraft(clientID, startDate);
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", startDate, CommonConstants.RESPONSE_RESOURCE_ID);
this.scheduleJobHelper.executeAndAwaitJob(jobName);
this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "100", nxtTransaction, CommonConstants.RESPONSE_RESOURCE_ID);
List<HashMap> transactions = this.savingsAccountHelper.getSavingsTransactions(savingsId);
boolean reversalFlag = false;
for (int i = 0; i < transactions.size(); i++) {
boolean isReversal = (boolean) transactions.get(i).get("isReversal");
if (isReversal) {
reversalFlag = true;
break;
}
}
Assertions.assertFalse(reversalFlag);
}
private Integer createSavingsAccountDailyPostingOverdraft(final Integer clientID, final String startDate) {
final Integer savingsProductID = createSavingsProductDailyPostingOverdraft();
Assertions.assertNotNull(savingsProductID);
@@ -99,8 +99,8 @@ public class GlobalConfigurationHelper {
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
// There are currently 37 global configurations.
Assertions.assertEquals(40, expectedGlobalConfigurations.size());
Assertions.assertEquals(40, actualGlobalConfigurations.size());
Assertions.assertEquals(41, expectedGlobalConfigurations.size());
Assertions.assertEquals(41, actualGlobalConfigurations.size());
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
@@ -456,6 +456,14 @@ public class GlobalConfigurationHelper {
isAutomaticCOBDateAdjustmentEnabled.put("trapDoor", false);
defaults.add(isAutomaticCOBDateAdjustmentEnabled);
HashMap<String, Object> isReversalTransactionAllowed = new HashMap<>();
isReversalTransactionAllowed.put("id", 46);
isReversalTransactionAllowed.put("name", "enable-post-reversal-txns-for-reverse-transactions");
isReversalTransactionAllowed.put("value", 0);
isReversalTransactionAllowed.put("enabled", false);
isReversalTransactionAllowed.put("trapDoor", false);
defaults.add(isReversalTransactionAllowed);
return defaults;
}