Aman-Mittal opened a new issue, #284:
URL: https://github.com/apache/fineract-backoffice-ui/issues/284

   ## Business value
   
   Two platform operations that revise the money on an approved loan have no UI 
at all. Both are in the generated client and neither is called anywhere:
   
   ```
   putLoansLoanIdApprovedAmount(loanId, { amount, locale })
   putLoansLoanIdAvailableDisbursementAmount(loanId, { amount, locale })
   ```
   
   ```
   grep -rn 
"putLoansLoanIdApprovedAmount\|putLoansLoanIdAvailableDisbursementAmount" 
src/app --include=*.ts | grep -v '/app/api/'
   # no results
   ```
   
   **Approved amount** is what a credit committee sanctioned. It changes for 
ordinary reasons: the committee approves less than was applied for, a valuation 
comes back low, a borrower asks for less, a partial disbursement happens and 
the remainder is cut. Today the only way to reflect any of that is to cancel 
the approval and start again — which loses the approval record, the checker's 
sign-off, and the original application date. On a loan that has already been 
partly disbursed, it is not possible at all.
   
   **Available disbursement amount** governs how much of a multi-tranche loan 
may still be drawn. Without it, a branch cannot close off the undrawn balance 
of a facility, and cannot extend a tranche limit without rebuilding the loan.
   
   The platform also keeps a change history (`LoanApprovedAmountHistoryData` — 
`oldApprovedAmount`, `newApprovedAmount`, `dateOfChange`), which exists 
precisely so a UI can show who changed a sanction and to what. Nothing reads it.
   
   ## Why this is not a beginner issue
   
   The endpoints are trivial. The **rules** are not, and getting them wrong 
produces a screen that offers actions the platform will refuse in ways the user 
cannot predict. This needs someone comfortable reading acceptance criteria and 
deciding what to enable when.
   
   ## The rules, from the platform's own acceptance tests
   
   
`fineract-e2e-tests-runner/src/test/resources/features/LoanUpdateApprovedAmount.feature`
 in `apache/fineract` (`develop`) — 11 scenarios. The constraints:
   
   ```gherkin
   Then Update loan approved amount is forbidden with amount "0" due to min 
allowed amount
   Then Update loan approved amount is forbidden with amount "1600" due to 
exceed applied amount
   ```
   
   and the interaction with disbursement (UC3):
   
   ```gherkin
   And Admin successfully disburse the loan on "1 January 2025" with "100" EUR 
transaction amount
   Then Update loan approved amount with new amount "600" value
   When Admin successfully undo disbursal
   Then Admin fails to disburse the loan on "1 January 2025" with "700" EUR 
transaction amount due to exceed approved amount
   When Admin successfully disburse the loan on "01 January 2025" with "600" 
EUR transaction amount
   ```
   
   So the approved amount can be revised **after a partial disbursement**, and 
the new figure binds subsequent disbursements. And with over-applied configured 
as a percentage (UC4):
   
   ```gherkin
   Then Loan has availableDisbursementAmountWithOverApplied field with value: 
1500
   And Admin successfully disburse the loan on "1 January 2025" with "1100" EUR 
transaction amount
   Then Loan has availableDisbursementAmountWithOverApplied field with value: 
400
   ```
   
   `LoanUpdateAvailableDisbursementAmount.feature` adds 18 more, and the ones 
that shape the UI are:
   
   ```gherkin
   Scenario: Verify update available disbursement amount to zero is forbidden 
for not approved loan
   Scenario: Verify update available disbursement amount to zero is forbidden 
for approved loan
   Scenario: Verify update available disbursement amount to zero is allowed for 
active loan after partial disbursement for single disb loan
   Scenario: Verify available disbursement amount change is forbidden with 
lower value for progressive multidisbursal loan that expects tranches
   Scenario: Verify available disbursement amount change with greater value 
above approved amount for ... that expects tranches
   ```
   
   Read together: **whether zero is permitted depends on the loan's status and 
on whether anything has been disbursed**, and **whether a decrease is permitted 
depends on whether the product expects tranches**. A menu item that is simply 
always enabled will produce refusals the user cannot anticipate.
   
   ## Describing the change
   
   Two dialogs on the loan view, each an amount field plus `locale`, posting to 
its endpoint. `src/app/features/clients/client-transfer-dialog.component.ts` is 
a recent, close model for a small dialog returning a typed result, and 
`loan-view.component.ts` already holds the actions menu and the 
`runCommand`-style reload pattern.
   
   Gate the menu items on loan status. The status constants pattern is 
`src/app/features/clients/client-servicing.model.ts` — a named `const` object 
rather than integer literals in the template. Loans should have the same; 
introducing it here is in scope and welcome.
   
   **Do not encode the full rule set in the client.** Gate on what is stable 
and knowable — status, and whether the product is multi-disbursement — and let 
the platform refuse the rest. The error interceptor already surfaces the 
platform's message. Client-side validation that disagrees with the backend is 
worse than none, because it blocks operations that would have succeeded.
   
   **Verify each payload against a live backend before writing the dialog.** 
`npm run e2e:stack` brings one up. Commands in this API are routinely 
asymmetric about `locale` and `dateFormat` — in this repo `acceptTransfer` 
refuses the very fields `proposeTransfer` requires — so confirm whether 
`locale` is needed, and what happens if `amount` is omitted. A 400 from 
Fineract usually names the offending parameter, and its `args` array often 
enumerates the accepted values.
   
   **A change-history panel reading `LoanApprovedAmountHistoryData` is a 
natural second PR**, not part of this one. Say so if you intend to do it.
   
   ## Testing
   
   - **Unit specs** asserting the exact body for each endpoint, and that the 
menu items are hidden for statuses where the operation is refused. Assert 
bodies with `toEqual`, not `objectContaining` — whether `locale` is present is 
precisely what you are pinning down.
   - **A mocked e2e** capturing method, URL and body. 
`e2e/client-servicing-gaps.spec.ts` has the `Probe` pattern to copy.
   - **A backend e2e** (add the filename to `BACKEND_SPECS` in 
`playwright.config.ts`) is the one that earns its keep here, because it is the 
only test that proves the payload is accepted. Mirror UC3 above — approve, 
disburse partially, revise the approved amount, and assert the loan reflects 
the new figure. Everything through the UI; no API seeding.
   
   One trap from an earlier backend e2e in this repo: list rows are inert. The 
`routerLink` sits on the name cell, so `row.click()` does nothing and the test 
sits on the list until it times out. Use 
`row.getByRole('link').first().click()`.
   
   ## Scope
   
   In scope: the two dialogs, the menu entries with status gating, and their 
tests.
   
   Out of scope: the approved-amount change history panel; over-applied 
configuration on the product form; anything about tranche editing.
   
   ## Getting started
   
   - Loan view: `src/app/features/loans/loan-view.component.ts`
   - Endpoints: `src/app/api/api/loans.service.ts`
   - Request models: `putLoansApprovedAmountRequest.ts`, 
`putLoansAvailableDisbursementAmountRequest.ts` (both are `{ amount?: number; 
locale?: string }`)
   - Dialog model to copy: 
`src/app/features/clients/client-transfer-dialog.component.ts`
   - `npm test`, `npm run lint:prune`, `npm run i18n:check` and `npm run build` 
must pass.
   - `loan-view.component.ts` is large and under active development. Rebase 
before opening the PR, and keep the diff tight.
   


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