Aman-Mittal opened a new issue, #278:
URL: https://github.com/apache/fineract-backoffice-ui/issues/278
## Business value
`POST /recurringdepositaccounts/{id}/transactions` dispatches on a `command`
query parameter.
`src/app/features/products/recurring-deposit-transactions/recurring-deposit-transaction-form.component.ts:205`
never sends one:
```ts
this.transactionsService
.postRecurringdepositaccountsRecurringDepositAccountIdTransactions(this.accountId,
request)
.subscribe({ ... });
```
The generated method's third parameter is `command?: string`. It is optional
in TypeScript because the OpenAPI spec marks the query parameter optional, but
the platform does not treat it as optional — it uses it to decide whether the
transaction is a deposit or a withdrawal, and refuses the request without it.
Verified against a live backend:
```
POST /v1/recurringdepositaccounts/1/transactions
{"transactionDate":"01 June 2026","transactionAmount":100,"dateFormat":"dd
MMMM yyyy","locale":"en"}
400 {"errors":[{"developerMessage":"The query parameter command has an
unsupported value of: null",
"parameterName":"command",
"args":[{},{"value":["deposit","withdrawal"]}]}]}
```
The same call with `?command=deposit` gets past validation and reaches
account lookup (`404 Savings account with identifier 1 does not exist` —
expected, that id does not exist on a fresh instance).
So **every** recurring-deposit transaction submitted through this screen
fails. A branch cannot record a member's RD instalment at all; the error toast
reports a platform message about a query parameter, which tells the teller
nothing actionable. Recurring deposits are a core savings product for
group-based lending, so this is not an edge case.
## Reproducing it
```
grep -n "postRecurringdepositaccountsRecurringDepositAccountIdTransactions" \
src/app/features/products/recurring-deposit-transactions/recurring-deposit-transaction-form.component.ts
```
One call site, two arguments where three are needed.
## Describing the change
The form already knows which operation the user picked — the route is
`recurring-deposits/:accountId/transactions/create` and the component has a
transaction-type notion. Pass it through:
```ts
this.transactionsService
.postRecurringdepositaccountsRecurringDepositAccountIdTransactions(
this.accountId,
request,
'deposit', // or 'withdrawal'
)
```
**Please do not hardcode `'deposit'` and stop there.** The platform accepts
exactly `deposit` and `withdrawal` (that list comes from the 400 above — the
`args` array enumerates the valid values, which is a useful trick generally).
The screen needs to be able to produce both. How the user chooses is your call;
the simplest faithful option is to take the command from the route the way the
savings equivalent does, rather than adding a dropdown.
Look at `src/app/features/products/savings-account-view.component.ts:735`
for the established pattern in this codebase:
```ts
onTransaction(command: string) {
this.router.navigate([`/products/savings-accounts/${this.accountId}/transactions/${command}`]);
}
```
## Testing
The platform's own acceptance tests describe the flow this screen has to
support. From
`fineract-e2e-tests-runner/src/test/resources/features/SavingsAccount.feature`
in `apache/fineract` (`develop`), scenarios C2438 and C2439:
```gherkin
Scenario: As a user I would like to Deposit to my savings account
And Client creates a new EUR savings account with "1 June 2022" submitted
on date
And Approve EUR savings account on "1 June 2022" date
And Activate EUR savings account on "1 June 2022" date
And Client successfully deposits 1000 EUR to the savings account on "1
June 2022" date
Scenario: As a user I would like to Withdraw from my savings account
...
And Client successfully withdraw 1000 EUR from the savings account on "1
June 2022" date
```
Two things to write.
**A unit spec** in `recurring-deposit-transaction-form.component.spec.ts`
asserting the third argument, because that is the whole bug:
```ts
expect(serviceSpy.postRecurringdepositaccountsRecurringDepositAccountIdTransactions)
.toHaveBeenCalledWith(ACCOUNT_ID, jasmine.objectContaining({
transactionAmount: 100 }), 'deposit');
```
Assert the command explicitly for both `deposit` and `withdrawal`. A spec
that only checks the body would have passed throughout this bug's life.
**A mocked e2e** in `e2e/`, following the `Probe` pattern in
`e2e/client-servicing-gaps.spec.ts` — intercept the POST, record `new
URL(request.url()).searchParams.get('command')`, and assert it is not null.
That is the assertion that would have caught this.
A backend e2e (against the real platform, registered in `BACKEND_SPECS` in
`playwright.config.ts`) is welcome if you want to go further: create an RD
account, approve, activate, deposit, and assert the transaction appears. Follow
the cucumber order above — approve and activate are prerequisites, a deposit to
a pending account is refused. Drive it entirely through the UI; do not seed via
the API.
## Scope
In scope: sending the command, and being able to send both values.
Out of scope: the fixed/recurring deposit action menu, which is broken
separately and has its own issue.
## Getting started
- `npm test` and `npm run lint:prune` must pass.
- To try it by hand you need a running platform — `npm run e2e:stack` brings
one up.
- The `args` array on a Fineract 400 usually enumerates the accepted values.
It is the fastest way to check a command name without reading platform source.
--
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]