bvanelli / actualpy

Python API implementation for Actual server - reference https://actualbudget.org/
20 stars 4 forks source link

get_accounts does not return a balance #21

Closed JaxOfDiamonds closed 3 months ago

JaxOfDiamonds commented 3 months ago

The get_accounts function does not appear to be populating the balances. I have balances in Actual.

Code snippet:

    accounts = get_accounts(actual.session, 'Bank...6877')
    for account in accounts:
        print(account.name)
        print(account)

Output:

Bank...6877
account_id='ACT-23432-adsfa-40asdf6c-asdf-asdf' balance_current=None balance_available=None mask=None subtype=None offbudget=0 sort_order=None type=None id='234fefas-32423asd-dsfa23-sdf-asdf2' name='Bank...6877' balance_limit=None official_name='COSTLY BLACK' bank='sadfads-asdfa-2dsf-8928adsfasd-2332423' closed=0 tombstone=0
bvanelli commented 3 months ago

Hello,

I checked the official API, and it was a bit confusing to me because:

https://github.com/actualbudget/actual/blob/b803731bc52dbf3628b2129c7881cebabd24488e/packages/loot-core/src/server/accounts/sync.ts#L672

https://github.com/actualbudget/actual/blob/b803731bc52dbf3628b2129c7881cebabd24488e/packages/loot-core/src/server/main.ts#L582-L590

I created a patch for now on https://github.com/bvanelli/actualpy/pull/23 that uses an sqlalchemy property. I used the beta token from https://beta-bridge.simplefin.org/info/developers to create an account with lots of entries:

image

The result of the property:

from actual import Actual
from actual.queries import get_accounts

with Actual("http://localhost:5006", password="mypass", file="My Finances") as actual:
    accounts = get_accounts(actual.session)
    for acct in accounts:
        print(f"Balance for {acct.name} is {acct.balance}")
Balance for SimpleFIN Savings is 115524.49
Balance for SimpleFIN Checking is 26134.41

In the general case, I think it would be nice to include the balance on categories, payees and group of transactions. The general query is:

def get_balance(transactions: list[Transactions]) -> decimal.Decimal:
    running_balance = decimal.Decimal(0)
    for t in transactions:
        if t.is_parent == 0 and t.tombstone == 0:  # skip the splits, as they already get counted
            amount = t.get_amount()
            running_balance = running_balance + amount
    return running_balance

Let me know what you think of the PR, you will be able to install it from git or by cloning and checking out the PR.

JaxOfDiamonds commented 3 months ago

The PR worked for me except for an edge case of accounts with zero transactions. I added a comment and a workaround in the PR - though there may be a more elegant solution.

bvanelli commented 3 months ago

The PR worked for me except for an edge case of accounts with zero transactions. I added a comment and a workaround in the PR - though there may be a more elegant solution.

Solved the issue, thanks for the correction!