Aman-Mittal opened a new pull request, #847:
URL: https://github.com/apache/fineract-backoffice-ui/pull/847
Four things, in five commits. The module's API surface was already fully
reached by numeric id, so none of this is a wrapper for its own sake — each
piece is a capability that had no way in.
## 1. The book at portfolio level
Every working-capital screen was one loan or one piece of reference data;
nothing said what the book looks like. The overview reports outstanding,
delinquency and its aging, the status mix, and the flags the platform sets,
with a link through to the loans list.
**It states figures Fineract states per loan and adds them up.** Nothing is
inferred beyond addition and banding day counts. In particular it does **not**
claim which loans are "in breach": `breach` is the definition attached to the
loan, `breachStartDate` is a date this project has never had to pin down, and
every existing screen reads breach as per-loan *actions* instead. A derived
breach flag would put a risk judgement the module does not make onto a screen
that reads as authoritative. The one breach figure the platform names,
`balance.breachPastDueAmount`, is reported under that name.
The arithmetic is a pure `summarisePortfolio` in the adapter port, not a
template expression, because these totals are the screen's whole claim. The
aging bands are tested at every boundary, and the band totals are asserted to
**sum back to the portfolio total** — the one thing a reader checks.
New code cannot import the generated client (ADR 0006), so this comes with a
narrow port: two reads, a snapshot model whose numbers are non-optional, and a
mapper that resolves every absent figure to zero. The generated type marks all
80-odd fields optional; one `undefined` in a column of money renders as `NaN`,
so absence is decided once in a tested mapper rather than at each `+`.
## 2. Charts for the aging bands and the status mix
The aging bands are an **ordinal** ramp — one blue hue, light to dark — so
"older" reads as "darker" without asking anyone to learn five hues. The
statuses are **categorical** and take the fixed slot order; a sixth status is
not a sixth hue, it folds into one deliberately neutral "Other", so a slice
keeps its colour as long as it keeps its rank.
Both charts plot loan **counts**. The amounts stay in the tables: charting
one of them here would put two scales in one picture.
Every step was validated against its own surface — ordinal mode for the ramp
(monotone lightness, visible step gaps, light end clearing the surface) and
categorical mode for the statuses (lightness band, chroma floor, colour-vision
separation). Dark steps are **selected** per theme rather than flipped, which
`ThemeService.isDarkMode` already makes possible. The light categorical steps
sit below 3:1 on the light surface, which obliges a non-colour reading of the
same data: hence a table under each chart and a label on every slice.
Worth raising separately: **the palette the dashboard's existing donuts use
does not pass** — one of its four steps falls below the chroma floor and reads
as grey, and three fall under 3:1. It is deliberately not extended here and is
left for its own change rather than quietly reused.
No charting dependency: this reuses the app-owned SVG chart components, and
the screen uses plain semantic markup rather than Ionic cards, because ADR 0005
closes the vendor boundary to new files and `app/ui` has no card primitive —
the gap #684 describes.
## 3. Opening a loan by its external id
Fineract addresses every working-capital resource twice, by its own numeric
id and by the external id the institution set, and this application only ever
used the numeric half. An operator holding their own reference had to scroll
the list.
A lookup on the loans list resolves the reference through `GET
/working-capital-loans/external-id/{loanExternalId}` and hands over to the
ordinary loan view, replacing the URL so the back button returns where the
operator came from. `/working-capital/loans/external/<ref>` is then a shareable
address for a loan nobody has the numeric id for. The route is declared ahead
of every `loans/:id/...` pattern so an external id is never read as a numeric
one.
A reference matching nothing answers `null`, not an error — that is the
lookup working, and the screen names the reference back. A real failure keeps
its own path with a retry, because "no such loan" and "the server broke" are
different answers.
## 4. The internal commands, behind developer tools
The three `/v1/internal/**` working-capital commands — activate a loan,
regenerate its amortization schedule, step it into the next delinquency period
— had no way in.
They are **not** offered as product operations. Fineract serves
`/v1/internal/**` only under its `test` Spring profile, which upstream says
must not be enabled in production, so on any other deployment they answer 404.
The route is matched only where `developerToolsEnabled` is set, the nav entry
is a `developerTool`, and the screen states the constraint before offering
anything. They live in their own port so a product contract cannot grow a
dependency on a test-only endpoint by accident, and
`check-internal-endpoints.mjs` has one file to pin rather than a screen each.
**This is the one part I could not exercise end to end.** The optional date
parameters are left to the platform's default rather than guessed, the success
message says the platform *accepted* the command rather than claiming an
outcome, and the tests pin the shape rather than the behaviour of a live
instance. Worth a look from anyone with a test-profile instance.
## Tests
56 unit tests across the port arithmetic, the mapper, both screens and the
lookup, plus a mocked e2e covering the overview's totals and the not-found
reference. Written as invariants where possible: the band totals must sum to
the portfolio total, and a mapper that let an `undefined` through would fail on
the `NaN` assertion.
## Checks
- unit suite 326 files / 2803 tests; `lint` silent with
`eslint-suppressions.json` unchanged; `tsc` app + e2e clean
- `i18n:check` consistent with `fr` at 100% and `hi` carrying all 30 new
keys; `format:check` clean
- `api:surface` records the four newly used operations (644 → 648);
`ga:check` 10/11 with 0 blocking
- `check:internal-endpoints`, `check:nav-ids`, `check:route-permissions`,
`check:a11y-names`, `check:template-text`, `check:ui-primitives`,
`check:responsive`, `check:theme-contrast`, `check:icons` all pass
- mocked e2e 2/2
--
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]