Aman-Mittal opened a new pull request, #508: URL: https://github.com/apache/fineract-backoffice-ui/pull/508
## What and why `refundByCash` is a command the platform accepts and no screen ever sent. It is the counter-side of taking a repayment — handing back money a borrower paid ahead of schedule, in cash, with no card or wallet rail behind it. The shared transaction form already carries the whole request: it is driven by the route's `:type` segment and posts `postLoansLoanIdTransactions(loanId, transaction, type)` with `transactionDate`, `dateFormat`, `locale`, `transactionAmount` and `paymentTypeId` — exactly the body this command takes. So the change is a menu entry, a title key and `AMOUNT_VISIBLE_TYPES` membership, not a new form. Addresses #506. **Charge refund, the other half of that issue, is not included** — it additionally needs a `loanChargeId` picker listing the loan's charges, which is a genuinely new field on the shared form and belongs in its own change. #506 stays open for it. ## Offered conditionally, and the window is narrower than it looks Per the rule #268 established for undo-last-disbursal, an action that can only fail should not be offered. Both edges were probed against a running `apache/fineract` rather than inferred: | Loan state | Platform response | |---|---| | Active, nothing paid ahead | `403` `error.msg.loan.refund.amount.invalid` — "loan is not paid in advance" | | Overpaid, therefore closed | `400` `error.msg.loan.refund.account.is.not.active` | So the action needs the loan to be active **and** carrying an advance balance — not merely one or the other. That is what `hasAdvanceBalance()` checks, alongside the existing `isLoanActive` block it sits in. `paidInAdvance` is absent from the generated `GetLoansLoanIdResponse` (#448), so it is read defensively rather than through the typed model — the same shape `isOverpaid` already uses for `status` a few lines above. ## Screenshots The action on a loan deliberately paid ahead of schedule:  The shared transaction form under the new type:  ## Verification Driven end to end through the UI against a local `apache/fineract` (`deploy/docker-compose-e2e.yml`), on a loan seeded with the repository's own `e2e/utils/seed-api.ts` helpers and then paid ahead of schedule. What the app actually sent: ``` POST /fineract-provider/api/v1/loans/23/transactions?command=refundByCash {"transactionAmount":500,"transactionDate":"2026-09-06","dateFormat":"yyyy-MM-dd","locale":"en"} ``` and what the platform then reported for that loan: ``` transaction types = ["Disbursement","Accrual","Repayment","Refund"] ``` The Refund is real, not just a route that resolved — a menu entry that navigates correctly but posts something the platform rejects would look identical in a screenshot, which is why this was checked against the API rather than the UI. Also run: - `npm run test:unit --include='**/loan-view.component.test.ts'` — 22 passed, including the two new gate cases - `npm run lint` — clean - `npm run check:icons` — 117 registered, `cash-outline` already among them - `npm run i18n:check` — 1610 referenced keys resolved, none missing - `npx prettier --check` on all four changed files — clean - Commit is signed ## Checklist - [x] I did not hand-edit generated files under `src/app/api/`. - [x] No new browser globals or imperative third-party APIs; the adapter boundary is unchanged. - [x] User-facing strings use translation keys (`LOANS.ACTIONS.REFUND_BY_CASH` added). - [x] Unit coverage for the command name and for both sides of the advance-balance gate. - [x] Verified end to end against a real backend; the request and the resulting transaction are quoted above. - [x] Commits are signed. -- 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]
