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