+1

Sent from Gmail Mobile


On Thu, Apr 9, 2026 at 4:09 AM Ashhar Ahmad Khan <[email protected]>
wrote:

> Hi everyone,
>
> A few weeks ago while going through the client module I came across POST
> /clients/{clientId}/charges/{chargeId}?command=inactivate and noticed it
> always threw an exception. I traced it back to a missing command handler
> and a service method that was just returning null with a "functionality not
> yet supported" comment. It looked like an incomplete implementation, so I
> opened PR #5655 [1] to implement it.
>
> After I raised this on the dev list [2], Victor pointed out that charges
> should be account-associated rather than client-associated, and James asked
> that we properly validate whether this path had ever worked and whether
> anything depended on it before any removal decision.
>
> The inactivateCharge() service method has been returning null since its
> very first commit on August 17 2015 (d0fd3e4a6c, Vishwas Babu A J). A few
> weeks after that, commit 8f1eb39d5d updated the comment from "// TODO
> Auto-generated method stub" to "// functionality not yet supported" — still
> returning null.
>
> Searching the full git history:
> git log --all -S "clientCharge.inactivate" --oneline
> # zero results
>
> There has never been an implementation in MifosX or Apache Fineract. The
> savings equivalent has been working since July 2014 (MIFOSX-1408), but
> client charges were not introduced until August 2015, so the handler was
> simply never written when the feature arrived.
>
> I also verified this against apache/fineract:latest:
> POST /fineract-provider/api/v1/clients/1/charges/1?command=inactivate
> HTTP/1.1 400
> { "errors": [{ "userMessageGlobalisationCode":
> "error.msg.command.unsupported" }] }
>
> The m_portfolio_command_source entry for that call shows made_on_date as
> NULL and status 5, meaning the request was rejected before any processing
> began and nothing was written to m_client_charge. Before running this, the
> table had zero rows for action_name=INACTIVATE and
> entity_name=CLIENTCHARGE. The one entry that now exists is from this
> validation run.
>
> On the dependency question James raised, I checked the full surface area:
>
>    - No inactivateClientCharge method in the generated SDK client
>    - Swagger @Operation on that endpoint documents only paycharge and
>    waive
>    - Built fineract.yaml has no inactivate entry for client charges
>    - No frontend file in the repository references command=inactivate for
>    client charges
>    - No integration test has ever exercised this endpoint
>    - m_portfolio_command_source had zero prior attempts before this
>    validation run
>
> Based on all of this, and on the direction from Victor and James, I would
> like to proceed with a write-path-only removal. Concretely that means:
>
>    - Remove the else-if branch for command=inactivate in
>    ClientChargesApiResource
>    - Remove inactivateCharge() from the interface and its null stub in
>    the implementation
>    - Remove inactivateClientCharge() from CommandWrapperBuilder
>    - Remove CLIENT_CHARGE_ACTION_INACTIVATE and
>    CLIENT_CHARGE_COMMAND_INACTIVATE_CHARGE from ClientApiConstants
>    - Add a Liquibase changeset deleting INACTIVATE_CLIENTCHARGE and
>    INACTIVATE_CLIENTCHARGE_CHECKER from m_permission
>    - Update barebones_db.sql and load_sample_data.sql accordingly
>
> The shared ACTION_INACTIVATE constant in CommandWrapperConstants stays
> untouched as savings charge inactivation depends on it.
>
> The GET response for /clients/{clientId}/charges keeps isActive and
> inactivationDate for now since dropping those fields changes the response
> contract. That is a separate conversation if the community wants it.
>
> For any existing caller, ?command=inactivate goes from HTTP 400
> (error.msg.command.unsupported) to HTTP 400 (error.msg.unrecognized.param).
> The status code does not change.
>
> Backward compatibility will not be preserved for ?command=inactivate. This
> command has never returned a successful response in any version of Fineract.
>
> I will hold off at least 72 hours before opening the removal PR. If anyone
> sees a reason to preserve this path, or knows of downstream usage I may
> have missed, please reply on-thread.
>
> Thanks,
> Ashhar
>
> [1] https://github.com/apache/fineract/pull/5655
> [2] https://lists.apache.org/thread/lhh0hx0t2y7vzdrs98fg3qyfx1xo9d0y
> JIRA: https://issues.apache.org/jira/browse/FINERACT-2545
>

Reply via email to