Ralph Hopman created FINERACT-2851:
--------------------------------------

             Summary: Savings hold/release transactions incorrectly affect 
transaction running balance
                 Key: FINERACT-2851
                 URL: https://issues.apache.org/jira/browse/FINERACT-2851
             Project: Apache Fineract
          Issue Type: Bug
          Components: Savings
    Affects Versions: 1.15.0, 1.14.0
            Reporter: Ralph Hopman
            Assignee: Ralph Hopman
             Fix For: 1.16.0


h2. Description

When an amount is placed on hold on a savings account, the hold is represented 
as an {{AMOUNT_HOLD}} transaction.

A hold should reduce the *available balance* of the account, but should not 
change the account's ledger/book balance. This is also consistent with the 
existing savings account behavior: {{summary.accountBalance}} remains unchanged 
while {{summary.availableBalance}} is reduced by the held amount.

However, the {{runningBalance}} reported on savings transactions treats 
{{AMOUNT_HOLD}} as if it reduces the ledger balance, and {{AMOUNT_RELEASE}} as 
if it increases it again.

This results in the transaction-level running balance being inconsistent with 
the account-level balance.
h2. Example

Given a savings account with no initial balance:
 # Deposit 1,000
 # Hold 200

The account correctly reports:
{code:java}
accountBalance   = 1000
availableBalance = 800
{code}
However, the transactions report approximately:
{code:java}
Deposit       amount=1000   runningBalance=1000
Amount Hold   amount= 200   runningBalance= 800
{code}
The {{runningBalance}} of the hold transaction therefore does not correspond to 
the ledger/book balance after that transaction.

After the hold is released, the running balance increases again, even though 
releasing a hold also has no effect on the ledger balance.
h2. Expected Behavior

{{AMOUNT_HOLD}} and {{AMOUNT_RELEASE}} should not change the transaction 
{{runningBalance}} if that field represents the running ledger/book balance.

For the example above, the expected result is:
{code:java}
Deposit        amount=1000   runningBalance=1000
Amount Hold    amount= 200   runningBalance=1000
Amount Release amount= 200   runningBalance=1000
{code}
The effect of the hold should instead be reflected in the account's 
{{{}availableBalance{}}}.

Note: If {{runningBalance}} is intentionally intended to represent available 
balance rather than ledger balance, this should be explicitly defined and 
consistently applied across the savings APIs. Currently its semantics differ 
from the account-level {{accountBalance}} and can also affect downstream 
calculations.
h2. Relevant Implementation

In {{{}SavingsAccount.recalculateDailyBalances(){}}}, hold and release 
transactions are explicitly included in the running-balance calculation:
{code:java}
if (transaction.isCredit() || transaction.isAmountRelease()) {
    ...
    transactionAmount = 
transactionAmount.plus(transaction.getAmount(this.currency));
} else if (transaction.isDebit() || transaction.isAmountOnHold()) {
    ...
    transactionAmount = 
transactionAmount.minus(transaction.getAmount(this.currency));
}

runningBalance = runningBalance.plus(transactionAmount);
transaction.setRunningBalance(runningBalance);
{code}
This is notable because {{SavingsAccountTransactionType}} explicitly defines 
{{AMOUNT_HOLD}} and {{AMOUNT_RELEASE}} as transactions that do not change the 
account balance.

For example:
{code:java}
// AMOUNT_RELEASE is not credit, because the account balance is not changed
return isCreditEntryType() && !isAmountRelease();

// AMOUNT_HOLD ... [is] not debit, because the account balance is not changed
return isDebitEntryType() && !isAmountOnHold() && !isEscheat();
{code}
h2. Acceptance Criteria
 * Placing an amount on hold does not reduce the transaction 
{{{}runningBalance{}}}.
 * Releasing a held amount does not increase the transaction 
{{{}runningBalance{}}}.
 * {{runningBalance}} after a hold/release remains equal to the ledger/book 
balance at that point in the transaction history.
 * {{availableBalance}} continues to reflect active holds.
 * Existing rules preventing withdrawal of held funds continue to work.
 * Regression tests cover:
 ** deposit -> hold
 ** deposit -> hold -> release
 ** deposit -> hold -> withdrawal
 ** deposit -> hold -> deposit
 ** multiple simultaneous holds
 * Behavior is consistent between the entity-based and DTO-based savings 
processing paths.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to