[
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)