Aman-Mittal opened a new pull request, #253:
URL: https://github.com/apache/fineract-backoffice-ui/pull/253

   Closes part of #180.
   
   ## What this is
   
   Groups had a list and a create form and nothing else. A group could be made 
and then never looked at again: no screen showed who was in one, and the group 
lifecycle — activate, close, staff, membership, committee — had no 
representation in the UI at all. Group lending is the product this application 
gates behind the `mfis` institution type, so enabling that mode revealed a 
feature that could not be used.
   
   This adds `/groups/view/:id` with four tabs (general, members, committee, 
notes) and the commands the platform exposes for a group: activate, close, 
assign and unassign staff, add and remove members, assign and unassign 
committee roles, and notes CRUD.
   
   ## Things the API demanded that are not visible from the generated client
   
   These cost real time to find, so they are recorded in the code as well as 
here.
   
   - **`GET /groups/{id}` answers with the summary alone.** `clientMembers` and 
`groupRoles` arrive only with `associations=all`, which the generated method 
cannot send — it takes `staffInSelectedOfficeOnly` and `roleId` and nothing 
else. The fetch therefore goes through `HttpClient` and `BASE_PATH`, the same 
escape hatch `loan-documents-tab` uses. Without it both tabs render empty for 
every group that has members.
   - **`assignRole` takes `role` (a code-value id); `unassignRole` takes the id 
of the *assignment*, as a query parameter.** Crossing the two answers 404 
naming a group role that plainly exists, which reads like the feature is broken 
rather than misaddressed. Both e2e specs pin this down.
   - **Closing needs a `closureReasonId` from the `GroupClosureReason` code, 
which ships empty.** The dialog says so rather than offering an empty dropdown 
behind a confirm button that cannot succeed.
   - **`unassignStaff` requires `staffId` in the body**; an empty body is a 400.
   
   ## Response typing
   
   Nine of the fields this screen reads — `status`, `active`, `activationDate`, 
`staffId`, `staffName`, `groupLevel`, `clientMembers`, `activeClientMembers`, 
`groupRoles` — are absent from the upstream OpenAPI document, so the generated 
`GetGroupsGroupIdResponse` describes seven fields and the endpoint returns 
sixteen.
   
   Rather than reach through the generated type with `as unknown as { … }` at 
each read, the shape is declared once in `group-detail.model.ts`. That keeps 
the guesswork in one reviewable place, and makes it a visible deletion if the 
weekly spec sync (ADR-0002) ever picks these up.
   
   ## Behaviour worth a second look in review
   
   - **The members tab lists `clientMembers`, not `activeClientMembers`.** Both 
come back. Hiding a pending member from the screen an officer would use to 
chase them also makes the member count disagree with what the platform will let 
you disassociate.
   - **The candidate search is not filtered by client status.** It was, until 
probing showed `associateClients` accepts a pending client — a group that forms 
before its members are activated is the ordinary case in group lending. The 
filter was hiding exactly the people an officer forms a group with.
   - **Command handlers raise no error toast.** `errorInterceptor` already 
toasts the platform's own `defaultUserMessage` for every failed request, and 
that message is the useful one: closing a group that still has members answers 
*"Group cannot be closed because of active clients associated with it"*, which 
a generic "the group could not be updated" would replace with nothing. The 
handlers clear pending state and otherwise get out of the way.
   
   ## Tests
   
   Two e2e specs, because they answer different questions.
   
   - `e2e/group-detail.spec.ts` (mocked, 6 tests) asserts on the *request* the 
screen makes — which command, which body, which query parameter — including the 
two cases a real backend cannot cheaply be steered into: a failed load, and a 
tenant whose closure-reason code is empty.
   - `e2e/group-membership.spec.ts` (real backend, 2 tests) answers what mocks 
cannot: whether the platform accepts what the screen sends. Everything is 
driven through the UI — the client, the staff member and the group are all 
created on screen — because those prerequisites are part of what an operator 
does, and seeding them through the API would not show the feature is reachable.
   
   Plus 17 unit specs across the view and the members dialog. Local runs: unit 
800/800, mocked group specs 6/6, backend group specs 2/2, `npm run build` and 
`npm run lint` clean.
   
   **The mocked e2e caught a real bug the unit spec had blessed.** `BASE_PATH` 
stops short of the version segment — `app.config.ts` strips a trailing `/v1` 
because the generated services prepend their own — and the detail fetch was 
missing it, so every group 404'd. The unit spec had asserted the same wrong 
URL; it now binds `BASE_PATH` the way the app actually computes it, so a call 
site that forgets `/v1` cannot pass.
   
   ## Also in here
   
   The groups list moves off `TranslateModule` onto the translation adapter 
while gaining the link into the new view, which clears one entry from the lint 
suppression baseline. Its create-button label is translated too — one of the 
hardcoded English strings tracked in #251.
   
   ## Deferred
   
   Out of scope here, and called out so #180 is not closed by this: transfer 
clients, the meeting schedule and attendance, the entity datatables tab, and 
GSIM/GLIM group accounts.
   


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