Foo Developer created FINERACT-2867:
---------------------------------------

             Summary: Submitting a savings account application with a FLAT 
charge fails with HTTP 500 (NullPointerException on the account currency)
                 Key: FINERACT-2867
                 URL: https://issues.apache.org/jira/browse/FINERACT-2867
             Project: Apache Fineract
          Issue Type: Bug
          Components: Savings
            Reporter: Foo Developer
            Assignee: Foo Developer


h3. Steps to reproduce
# Create a savings charge with calculation type FLAT, for example charge time 
"Savings Activation":

{code:json}POST /fineract-provider/api/v1/charges
{
  "name": "Flat activation fee", "chargeAppliesTo": 2, "currencyCode": "USD",
  "chargeTimeType": 3, "chargeCalculationType": 1, "chargePaymentMode": 0,
  "amount": 10, "active": true, "locale": "en"
}
{code}
# Submit a new savings account application that carries that charge:

{code:json}POST /fineract-provider/api/v1/savingsaccounts
{
  "clientId": 1, "productId": 1, "submittedOnDate": "01 January 2024",
  "locale": "en", "dateFormat": "dd MMMM yyyy",
  "charges": [ { "chargeId": <charge id>, "amount": 10 } ]
}
{code}

The same failure is reachable from 
{{SavingsAccountAssembler.assembleFrom(client, group, productId, ...)}}, which 
copies a product's charges onto a new account through 
{{SavingsAccountChargeAssembler.fromSavingsProduct}}, when the product has a 
FLAT charge.

h3. Expected

The savings account application is created with the FLAT charge, its amount 
rounded to the account currency.

h3. Actual

The request fails with HTTP 500. {{SavingsAccountCharge.populateDerivedFields}} 
throws {{NullPointerException: Cannot invoke "SavingsAccount.getCurrency()" 
because the return value of "SavingsAccountCharge.savingsAccount()" is null}}.

h3. Root cause

{{SavingsAccountChargeAssembler.fromParsedJson}} and {{fromSavingsProduct}} 
build the charges of a new application with 
{{SavingsAccountCharge.createNewWithoutSavingsAccount(...)}}, i.e. with 
{{savingsAccount = null}}; the charge is attached to its account only 
afterwards, through {{SavingsAccountCharge.update(SavingsAccount)}}. The 
constructor always calls {{populateDerivedFields}}, and since FINERACT-2284 its 
{{FLAT}} branch does {{Money.of(this.savingsAccount().getCurrency(), 
chargeAmount)}} to apply the currency rounding. With no account yet, that 
dereferences null. Charges added to an existing account ({{createNewFromJson}}) 
are not affected, because they are built with the account.

h3. Proposed fix

In {{populateDerivedFields}}, round the FLAT amount only when the account is 
known and keep the raw amount otherwise. In {{update(SavingsAccount)}}, when a 
FLAT charge is attached to its account for the first time, apply the currency 
rounding to {{amount}} and {{amountOutstanding}} then, so a charge submitted 
with a new application is rounded the same way as one added to an existing 
account.

h3. Tests

A unit test in {{fineract-savings}} for {{SavingsAccountCharge}}: building a 
FLAT charge with {{createNewWithoutSavingsAccount}} no longer throws, and 
attaching it to an account rounds its amount and outstanding amount to the 
account currency.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to