Abhishek6122008 opened a new pull request, #6421:
URL: https://github.com/apache/fineract/pull/6421

   ## What this does
   
   The `EXECUTE_STANDING_INSTRUCTIONS` job is all-or-nothing today. When the 
linked savings account cannot cover the amount due, `transferFunds` throws 
`InsufficientAccountBalanceException`, the run is recorded as `failed`, and 
nothing at all is collected. On a 40,000 installment with 39,900 available, the 
lender recovers zero.
   
   A standing instruction can now opt into partial collection, so the job 
transfers what is available instead of nothing. Per Bharath's comment on the 
ticket, the option sits on the standing instruction itself rather than being a 
global configuration.
   
   ## How
   
   - New `allow_partial_transfer` column on 
`m_account_transfer_standing_instructions`, exposed as `allowPartialTransfer` 
through the existing create/update endpoints. **Defaults to false**, so 
existing instructions — and the one Fineract creates automatically on 
disbursement to a linked savings account — behave exactly as before. No new 
endpoints.
   - When the flag is set *and* the from account is a savings account, the job 
limits the transfer to `SavingsAccount#getWithdrawableBalance()` and skips the 
instruction when nothing is available. That helper already accounts for the 
minimum required balance where enforced, overdraft headroom, on-hold funds and 
hold amounts, so no balance arithmetic is duplicated in the job.
   - The from account is assembled in the job and passed into the 
`AccountTransferDTO`. `transferFunds` assembles it itself only when that field 
is null, so the load moves rather than being added.
   - The from-account type is guarded because transfer types include 
`CHARGE_PAYMENT` and `INTEREST_TRANSFER`, where the from account is not 
necessarily savings.
   
   Clamping only ever lowers an amount that would otherwise have been rejected. 
Anything that still fails lands in the same `failed` history row as today, so 
this can improve on current behaviour but not regress it.
   
   ## Two things worth your view
   
   **The `'partial'` history status.** I raised this on the dev list and it did 
not get a reply, so I made a call and am flagging it. A partly covered run is 
recorded as `'partial'` instead of `'success'`, with the amount actually 
transferred. `m_account_transfer_standing_instructions_history.status` is 
`VARCHAR(20)`, written as a literal and read back as a plain `String` with no 
enum or switch anywhere in the read path, so a third value needs no migration 
and breaks no parsing. It only ever appears for instructions that opted in. If 
you would rather it stayed `'success'`, that is a small change.
   
   **Withdrawal fees.** If the account applies a withdrawal fee on transfers, 
the debit is amount + fee, so a transfer clamped to exactly the withdrawable 
balance can still fail by the fee. Computing the fee up front would mean 
duplicating `payWithdrawalFee` — flat vs percentage, free-withdrawal counts, 
payment-type conditions — so I left it. Such a run falls through to the same 
`failed` row it gets today. Happy to handle it if you think it is worth the 
duplication.
   
   ## Tests
   
   Unit tests on the tasklet cover the flag off with an insufficient balance 
(full amount still attempted, `failed` recorded — the behaviour this change 
leaves alone), the clamp to the available balance with a `partial` status, the 
skip when nothing is available, and a fully covered run still recording 
`success`.
   
   An integration scenario in `SchedulerJobsTestResults` funds a savings 
account below the instruction amount, runs the job, and asserts the available 
balance is transferred and the history row reads `partial` with the transferred 
amount.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to