Farooq Ayoade created FINERACT-2778:
---------------------------------------
Summary: Financial activity account update rejects cashAtTeller
and cashAtMainVault, which create accepts
Key: FINERACT-2778
URL: https://issues.apache.org/jira/browse/FINERACT-2778
Project: Apache Fineract
Issue Type: Bug
Components: Accounting
Reporter: Farooq Ayoade
h3. Summary
{{FinancialActivityAccountDataValidator}} validates the same parameter against
two different lists.
{{validateForCreate}} accepts all seven members of the {{FinancialActivity}}
enum, {{CASH_AT_MAINVAULT}}
(101) and {{CASH_AT_TELLER}} (102) among them. {{validateForUpdate}} omits
exactly those two and accepts
only {{[100, 200, 300, 103, 201]}}.
So the platform will happily create a teller or main-vault mapping and then
refuse every attempt to change
it:
{code}
PUT /financialactivityaccounts/{id}
{"financialActivityId":102,"glAccountId":805}
400
validation.msg.financialactivityaccount.financialActivityId.is.not.one.of.expected.enumerations
The parameter `financialActivityId` must be one of [ 100, 200, 300, 103,
201 ] .
{code}
The two halves write the same column and the mapping is read back the same way
whichever route created it
({{TellerWritePlatformServiceJpaImpl}} resolves both through
{{findByFinancialActivityTypeWithNotFoundDetection}}). There is no stated
reason for them to disagree, and
no note in the code suggesting the omission is deliberate.
h3. Impact
These two activities are not decorative: they are the GL accounts the
teller/cashier module posts cash
against. A deployment that maps them to the wrong account — easy to do, since
the mapping is set once at
configuration time — has every cashier and vault movement landing on the wrong
GL account, and no supported
way to correct it.
The remaining options are both bad:
* delete the mapping and create a replacement, which discards the row and its
identity, or
* {{UPDATE}} {{acc_gl_financial_activity_account}} directly in the database,
bypassing the platform's
validation and its audit trail.
On the tenant where this was found, {{cashAtTeller}} resolved to an account
named "Sms Unpaid" and
{{cashAtMainVault}} to "LOAN - PROVIDER'S ADVANCE - UNPAID INTEREST". Neither
could be repointed through the
API.
h3. Steps to reproduce
# {{POST /financialactivityaccounts}} with {{{}"financialActivityId": 102{}}}
(cashAtTeller) and any asset
GL account id. It succeeds — create accepts 102.
# {{PUT /financialactivityaccounts/{id\}}} with {{{}"financialActivityId":
102{}}} and a different asset GL
account id.
# The request fails with HTTP 400 and
{{validation.msg.financialactivityaccount.financialActivityId.is.not.one.of.expected.enumerations}},
naming
an expected set that does not contain the value the resource was created with.
The same holds for 101 (cashAtMainVault).
h3. Root cause
{{fineract-accounting/src/main/java/org/apache/fineract/accounting/financialactivityaccount/serialization/FinancialActivityAccountDataValidator.java}}
{{validateForCreate}} lists seven constants:
{code}
FinancialActivity.ASSET_TRANSFER, FinancialActivity.LIABILITY_TRANSFER,
FinancialActivity.CASH_AT_MAINVAULT, FinancialActivity.CASH_AT_TELLER,
FinancialActivity.OPENING_BALANCES_TRANSFER_CONTRA,
FinancialActivity.ASSET_FUND_SOURCE,
FinancialActivity.PAYABLE_DIVIDENDS
{code}
{{validateForUpdate}} lists five — the same set with {{CASH_AT_MAINVAULT}} and
{{CASH_AT_TELLER}} dropped.
Both lists are written out by hand rather than derived from the enum, which is
how they came to differ.
h3. Why it was not caught
{{FinancialActivityAccountsTest}} exercises the update path only with
{{LIABILITY_TRANSFER}}, and its
negative case uses activity id {{232}} — a value that is not in the enum at
all. A value that is in the
enum, is accepted by create, and is rejected by update is precisely the case
the test never covers.
h3. Proposed fix
Add the two missing constants to {{validateForUpdate}} so both halves accept
the same set, and extend
{{FinancialActivityAccountsTest}} to create a {{CASH_AT_TELLER}} mapping and
update it, which fails before
the change and passes after.
Deriving both lists from {{FinancialActivity.values()}} would prevent a
recurrence and is the tidier change,
but it widens the diff beyond the defect; happy to do it that way if reviewers
prefer.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)