Skip to content

FINERACT-2832: Migrate groups and centers to CommandDispatcher - #6487

Open
avivijay19 wants to merge 1 commit into
apache:developfrom
avivijay19:FINERACT-2832
Open

avivijay19 wants to merge 1 commit into
apache:developfrom
avivijay19:FINERACT-2832

Conversation

@avivijay19

Copy link
Copy Markdown
Contributor

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, GroupingTypesWritePlatformService, 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 (PostGroupsRequestGroupCreateRequest, GetGroupsGroupIdResponseGroupGeneralData, …), 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

  • Write the commit message as described in https://github.com/apache/fineract/#pull-requests
  • Acknowledge that we will not review PRs that are not passing the build
  • Create/update unit or integration tests
  • Follow coding conventions
  • Add required Swagger annotation and update API documentation
  • Submission is not a "code dump"
  • Run the full CI locally

Typed request DTOs, commands and handlers for every group and center write
operation, with per-command authorization in SecurityConfig and Jakarta
validation. Reads keep the existing serializer; the OpenAPI schemas are
generated from the real classes, which closes the reported gaps.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant