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

   ## Description
   
   Moves the write side of `GroupsApiResource` and `CentersApiResource` to the 
typed `CommandDispatcher` (same pattern as FINERACT-2288 Staff and the 
Meetings/Notes migrations): one request DTO, `Command` and `CommandHandler` per 
action, typed services (`GroupingTypesWriteService`, `GroupRolesWriteService`), 
programmatic Jakarta validation, and per-command authorization in 
`SecurityConfig` through a query-parameter-aware request matcher for the 
`?command=` endpoints (existing `ACTIVATE_GROUP`, `ASSOCIATECLIENTS_GROUP`, … 
authorities). The bulk-import handlers dispatch typed requests; the 
client-transfer and collection-sheet services each gain one typed adapter 
method (`transferClientsBetweenGroups(request)`, 
`saveGroupCollectionSheet(request)`), other callers untouched. The legacy path 
— the 22 `@CommandType` handlers (including 
`TransferClientsBetweenGroupsCommandHandler`) plus the unreferenced 
`UnassignStaffFromCenterCommandHandler`, the Gson validators, 
`GroupingTypesWritePlat
 formService`, `GroupRolesWritePlatformService`, the `CommandWrapperBuilder` 
group/center builders and the hand-written `GroupsApiResourceSwagger` / 
`CentersApiResourceSwagger` stubs — is removed.
   
   Request and write-response schemas are now generated from the real classes, 
and the read schemas reference the real DTOs (`GroupGeneralData`, `CenterData`, 
`GroupsPageResponse`, `CentersPageResponse`, `AccountSummaryCollectionData`) 
instead of the stubs — this closes the gaps reported in FINERACT-2832 
(`accountNo` on the list items; `staffId`, `centerId`, `clientMembers`, 
`datatables` on the create request) by construction. The read endpoints 
themselves are unchanged: they keep the existing JSON serializer, `?fields=` 
support and date format; their `READ_GROUP` / `READ_CENTER` check moves from 
the resource into `SecurityConfig`, scoped to the routes these two resources 
serve.
   
   Wire contract: same URLs, methods, query parameters and `?command=` values, 
same field names, dates, validation rules and error-body shape. Verified with 
the existing integration suites (GroupTest, CenterIntegrationTest, 
LoanReschedulingWithinCenterTest, GroupSavingsIntegrationTest, 
GroupLoanIntegrationTest, MakercheckerTest, AccountNumberPreferencesTest) and 
by exercising every write endpoint and `?command=` value over HTTP, including 
the roles, client-transfer, collection-sheet and bulk-import paths, which have 
no integration suite.
   
   Deliberate differences, consistent with the other CommandDispatcher 
migrations:
   - maker-checker no longer applies to `*_GROUP` / `*_CENTER` tasks, and the 
legacy webhook events for `GROUP` / `CENTER` no longer fire;
   - audit is written to `m_command` instead of `m_portfolio_command_source`;
   - unknown keys in a request body are ignored instead of rejected with 400;
   - validation errors keep the `{"errors":[{parameterName,…}]}` shape but 
carry the constraint's `org.apache.fineract.portfolio.group.<parameter>.<rule>` 
globalisation codes instead of `validation.msg.group.<parameter>.…`; the 
unsupported-`?command=` error lists the real command values (the legacy list 
was incomplete and contained the typo `updateassignRole`);
   - `PUT /groups/{id}` and `PUT /centers/{id}` with an explicit `"staffId": 
null` / `"centerId": null` no longer unassign — use `?command=unassignStaff` / 
`disassociateGroups` as before;
   - `DELETE /groups/{id}` and `?command=unassignStaff` previously returned 
`officeId` and `groupId` swapped; they now carry the correct values;
   - `POST /groups` accepts `centerId` without `officeId` (the office is taken 
from the centre), matching what the service always did;
   - `?command=transferClients` rejects an empty `clients` list with 400 
(legacy silently did nothing);
   - `?command=generateCollectionSheet` now requires `READ_GROUP` / 
`READ_CENTER` (legacy checked authentication only);
   - OpenAPI schema names change (`PostGroupsRequest` → `GroupCreateRequest`, 
`GetGroupsGroupIdResponse` → `GroupGeneralData`, …), so the api-compatibility 
check reports renames.
   
   Authorization hardening for these two resources: the matchers accept a 
`?command=` value with surrounding whitespace and a trailing slash on the path, 
exactly as the resource and Jersey do, so a request cannot reach the handler 
without passing the matcher. Note for follow-up: the matchers of the 
already-migrated Staff/Meetings/Notes resources do not tolerate a trailing 
slash while Jersey does; that is outside this ticket.
   
   Also worth knowing: a `?command=` request with no body now gets a 400 (the 
typed request must be present; send `{}` for `unassignRole` / `unassignStaff`), 
where the legacy resource tolerated an empty body; and a missing `roleId` on 
`updateRole` / `unassignRole` still 500s exactly as on develop.
   
   Observed while testing, not changed here: `?command=generateCollectionSheet` 
on both `/groups/{id}` and `/centers/{id}` fails on PostgreSQL with `operator 
does not exist: boolean = integer` (`CollectionSheetReadPlatformServiceImpl`), 
on develop as well.
   
   ## Checklist
   
   - [x] Write the commit message as described in 
https://github.com/apache/fineract/#pull-requests
   - [x] Acknowledge that we will not review PRs that are not passing the build
   - [x] Create/update unit or integration tests
   - [x] Follow coding conventions
   - [x] Add required Swagger annotation and update API documentation
   - [x] Submission is not a "code dump"
   - [x] Run the full CI locally
   


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