[ 
https://issues.apache.org/jira/browse/FINERACT-2851?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ralph Hopman updated FINERACT-2851:
-----------------------------------
    Description: 
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.

h2. Related Issue

FINERACT-2852 covers the financial consequence of this behavior in the 
scheduled interest calculation, where the affected {{runningBalance}} can be 
used as an end-of-day balance.

  was:
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.


> 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.14.0, 1.15.0
>            Reporter: Ralph Hopman
>            Assignee: Ralph Hopman
>            Priority: Minor
>             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.
> h2. Related Issue
> FINERACT-2852 covers the financial consequence of this behavior in the 
> scheduled interest calculation, where the affected {{runningBalance}} can be 
> used as an end-of-day balance.



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

Reply via email to