chinmaya samantara created FINERACT-2952:
--------------------------------------------

             Summary: Undoing or adjusting a savings withdrawal does not always 
reverse its withdrawal feef
                 Key: FINERACT-2952
                 URL: https://issues.apache.org/jira/browse/FINERACT-2952
             Project: Apache Fineract
          Issue Type: Bug
          Components: Savings
            Reporter: chinmaya samantara
            Assignee: chinmaya samantara


When a savings withdrawal that triggered a withdrawal fee is undone or 
adjusted, the fee is often not reversed. The customer keeps paying a fee for a 
withdrawal that no longer exists (undo), or pays the old fee plus the new one 
(adjust). The API returns 200, so nothing tells the user that the balance is 
wrong.

*Steps to reproduce* (develop ddb1ca0, PostgreSQL)

Savings account with an active 1% withdrawal fee charge, balance 1000. Withdraw 
100: the account gets a Withdrawal of 100 and a Withdrawal fee of 1.00, balance 
899.

A) Undo the withdrawal:
{code}
POST 
/fineract-provider/api/v1/savingsaccounts/{savingsId}/transactions/{withdrawalId}?command=undo
{code}
Actual result: balance 999.00. The withdrawal is reversed, the 1.00 fee is not.
Expected result: balance 1000.00, fee reversed.

B) Adjust the withdrawal to 50:
{code}
POST 
/fineract-provider/api/v1/savingsaccounts/{savingsId}/transactions/{withdrawalId}?command=modify
{ "transactionDate": "02 August 2026", "transactionAmount": 50, 
"paymentTypeId": 4, "locale": "en", "dateFormat": "dd MMMM yyyy" }
{code}
Actual result: balance 948.50. The old 1.00 fee stays and a new 0.50 fee is 
added.
Expected result: balance 949.50 (only the 0.50 fee).

It does not happen every time. In 5 runs on fresh accounts, undo kept the fee 3 
times and adjust 1 time. It depends on which of the two new rows gets the lower 
id:
{code}
#13 Withdrawal fee     1.0      <- the fee got the lower id
#14 Withdrawal       100.0  REVERSED
#15 Withdrawal        50.0
#16 Withdrawal fee     0.5
{code}

*Cause*

SavingsAccountWritePlatformServiceJpaRepositoryImpl.undoTransaction() and 
adjustSavingsTransaction() find the fee by id:
{code:java}
findOneByIdAndSavingsAccountId(transactionId + 1, savingsId)
{code}
SavingsAccount.withdraw() pays the withdrawal fee before it creates the 
withdrawal transaction, and the order in which the two rows get their ids is 
not guaranteed. When the fee gets the lower id, transactionId + 1 is a 
different row (or none) and the fee stays.

The withdrawal and its fee already share the same ref_no (one UUID per 
withdrawal, set in SavingsAccountDomainServiceJpa.handleWithdrawal), and 
SavingsAccountTransactionRepository.findByRefNo() exists (it is used by the 
bulk reverse command).

*Possible fix:* look the fee up by the withdrawal's ref_no instead of 
transactionId + 1 (same savings account, withdrawal fee, not reversed), and 
keep the id + 1 lookup only for old rows without a ref_no. Add an integration 
test with a withdrawal fee for undo and adjust; ClientSavingsIntegrationTest 
undoes and modifies a withdrawal, but its product has no withdrawal fee.




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

Reply via email to