Skip to content

FINERACT-2240: migrate Charges to CommandDispatcher - #6167

Draft
aditinikam wants to merge 3 commits into
apache:developfrom
aditinikam:FINERACT-2240
Draft

FINERACT-2240: migrate Charges to CommandDispatcher#6167
aditinikam wants to merge 3 commits into
apache:developfrom
aditinikam:FINERACT-2240

Conversation

@aditinikam

Copy link
Copy Markdown

Migrate the charge definition module (/v1/charges) to the typed command-processing infrastructure, removing the legacy JsonCommand write path entirely (CQRS-only), following the conventions established by the Staff and Floating Rate modules.

Write path

  • ChargesApiResource POST/PUT/DELETE build typed Charge{Create,Update, Delete}Command and dispatch through CommandDispatcher, returning typed responses; the update response still carries the changes map
  • add ChargeWriteService(+Impl), typed command handlers and request / response DTOs under portfolio.charge.data
  • applyChanges() lives in the write service rather than on the entity, so the entity no longer consumes DTOs; Charge.fromJson and Charge.update(JsonCommand) are gone
  • delete ChargeWritePlatformService(+Impl), the @CommandType handlers, the JSON deserializer and the CommandWrapperBuilder charge methods

Validation

  • the programmatic deserializer is replaced by declarative Jakarta Bean Validation: field constraints on the request DTOs plus the class-level @ValidChargeCreate / @ValidChargeUpdate constraints for the cross-field and chargeAppliesTo-driven rules
  • ChargeUpdateValidator is repository-backed because the legacy path validated the charge state after the update had been applied; it now validates the merged (post-update) values instead
  • messages live in fineract-validation ValidationMessages.properties

Read path

  • ChargeReadPlatformService is renamed to ChargeReadService, the inline permission checks are dropped and read authorization moves to SecurityConfig matchers alongside the write ones

The generated client models follow the typed signatures, so the charge operations in the integration and end-to-end tests are updated to ChargeCreateRequest / ChargeCreateResponse / ChargeUpdateRequest / ChargeUpdateResponse / ChargeDeleteResponse / ChargeData. The previously undocumented template query parameter of GET /charges/{chargeId} is now part of the API contract.

Description

Describe the changes made and why they were made. (Ignore if these details are present on the associated Apache Fineract JIRA ticket.)

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per our guidelines
  • Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
  • Create/update unit or integration tests for verifying the changes made.
  • Follow our coding conventions.
  • Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
  • This PR must not be a "code dump". Large changes can be made in a branch, with assistance. Ask for help on the developer mailing list.
  • If merging this PR resolves a JIRA issue, I will mark that issue as resolved and set "Fix Version/s" appropriately.

Your assigned reviewer(s) will follow our guidelines for code reviews.

Migrate the charge definition module (/v1/charges) to the typed
command-processing infrastructure, removing the legacy JsonCommand write
path entirely (CQRS-only), following the conventions established by the
Staff and Floating Rate modules.

Write path
- ChargesApiResource POST/PUT/DELETE build typed Charge{Create,Update,
  Delete}Command and dispatch through CommandDispatcher, returning typed
  responses; the update response still carries the `changes` map
- add ChargeWriteService(+Impl), typed command handlers and request /
  response DTOs under portfolio.charge.data
- applyChanges() lives in the write service rather than on the entity, so
  the entity no longer consumes DTOs; Charge.fromJson and
  Charge.update(JsonCommand) are gone
- delete ChargeWritePlatformService(+Impl), the @CommandType handlers, the
  JSON deserializer and the CommandWrapperBuilder charge methods

Validation
- the programmatic deserializer is replaced by declarative Jakarta Bean
  Validation: field constraints on the request DTOs plus the class-level
  @ValidChargeCreate / @ValidChargeUpdate constraints for the cross-field
  and chargeAppliesTo-driven rules
- ChargeUpdateValidator is repository-backed because the legacy path
  validated the charge state after the update had been applied; it now
  validates the merged (post-update) values instead
- messages live in fineract-validation ValidationMessages.properties

Read path
- ChargeReadPlatformService is renamed to ChargeReadService, the inline
  permission checks are dropped and read authorization moves to
  SecurityConfig matchers alongside the write ones

The generated client models follow the typed signatures, so the charge
operations in the integration and end-to-end tests are updated to
ChargeCreateRequest / ChargeCreateResponse / ChargeUpdateRequest /
ChargeUpdateResponse / ChargeDeleteResponse / ChargeData. The previously
undocumented `template` query parameter of GET /charges/{chargeId} is now
part of the API contract.
@vidakovic
vidakovic self-requested a review July 27, 2026 17:30
Restore the documented schemas that the CommandDispatcher migration
dropped, fixing the R010 and R014 findings of the API backward
compatibility check:

- Reinstate ChargesApiResourceSwagger (GetChargesResponse,
  PutChargesChargeIdRequest/Response) and reference it from the GET
  and PUT @apiresponse annotations so the enum description fields and
  the typed changes map stay in the spec (R014).
- Document feeInterval/feeFrequency as string in the create/update
  request DTOs, matching the legacy ChargeRequest contract; the Java
  fields remain Integer and Jackson coerces both forms (R010).
- Align integration test helpers with the restored client model names
  (GetChargesResponse, PutChargesChargeIdResponse).
…hema

The CommandDispatcher migration pointed the GET /v1/charges/{chargeId}
@apiresponse at ChargeData, and the e2e step definitions were updated to
match. Restoring the published contract to
ChargesApiResourceSwagger.GetChargesResponse moved the generated client
back to GetChargesResponse, but WorkingCapitalChargeStepDef was left on
the old type, breaking :fineract-e2e-tests-core:compileTestJava.

Switch the retrieveOneCharge call sites back to GetChargesResponse. The
template endpoint still returns ChargeData, so those usages are
unchanged.
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.

2 participants