Python Create Investment Transaction

john.vogtle+infinitekind's Avatar

john.vogtle+infinitekind

23 Oct, 2024 06:19 PM

Following Stuart Beesley's fine example here: https://infinitekind.tenderapp.com/discussions/moneydance-developme..., I am trying to create a dividend Transaction.

I'm currently running Moneydance 2024.2 (5172)

Code

from com.infinitekind.moneydance.model import ParentTxn, InvestFields, AbstractTxn, InvestTxnType, CurrencyUtil
from com.infinitekind.util import DateUtil
from com.infinitekind.util import StringUtils
from com.infinitekind.moneydance.model import Account, AccountUtil, AcctFilter
from java.lang import Math


RJ_DIVIDEND_ACCOUNT_NAME = "Raymond James Bank Deposit Program"


MD_REF = moneydance # Entry point into the Moneydance API book = MD_REF.getCurrentAccountBook() # Entry point into your dataset ra = MD_REF.getRootAccount()


investment_account_name = "RJF John Roth" investment_acct = ra.getAccountByName(investment_account_name)


security_acct_name = investment_account_name + ":" + RJ_DIVIDEND_ACCOUNT_NAME security_acct = ra.getAccountByName(security_acct_name)


print investment_acct print security_acct, security_acct.getUUID()


date = DateUtil.getStrippedDateInt() print date


niceCheckNum = "" desc = "this_is_description" memo = "this_is_memo"


#-- Create Parent Transaction pTxn = ParentTxn.makeParentTxn( book, date, date, DateUtil.getUniqueCurrentTimeMillis(), niceCheckNum, investment_acct, desc, memo, -1L, AbstractTxn.ClearedStatus.UNRECONCILED.legacyValue())


txnType = InvestTxnType.DIVIDEND totalAmount = long(.99)


fields = InvestFields() fields.setFieldStatus(txnType, pTxn) fields.date = date fields.taxDate = date fields.checkNum = niceCheckNum fields.payee = desc fields.memo = memo fields.amount = totalAmount fields.shares = 0 fields.price = 1 # fields.xfrAcct = AccountUtil.getDefaultTransferAcct(investAcct); # fields.fee = 0 # fields.feeAcct = AccountUtil.getDefaultCategoryForAcct(investAcct) # fields.category = AccountUtil.getDefaultCategoryForAcct(investAcct) fields.security = security_acct fields.storeFields(pTxn) print("stored fields ", fields, " as txn ", pTxn) pTxn.syncItem()

Running the code generates this error:

20241023-14:03:51.607 Error running script: Traceback (most recent call last):
  File "/Users/JohnnyV/repo/Moneydance/scripts/create_rj_txn_test.py", line 76, in <module>
    fields.storeFields(pTxn)
    at com.infinitekind.moneydance.model.InvestFields.storeFields(InvestFields.kt:433)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
java.lang.NullPointerException: java.lang.NullPointerException
I'm going to guess that I need to initialize one of the fields but there's no information to let me know what's missing. I'd appreciate any help that could be provided. Thanks
  1. 1 Posted by Stuart Beesley ... on 23 Oct, 2024 07:31 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    Hmm... There's nothing fundamentally wrong with your script... Other than long(0.99) needs to be long(99) - MD does NOT store decimal places..

    BUT it did have an incorrect variable which causes it to error on my system. Here is a corrected version.. I suggest you shut down the dev console and try again.

    from com.infinitekind.moneydance.model import ParentTxn, InvestFields, AbstractTxn, InvestTxnType, CurrencyUtil
    from com.infinitekind.util import DateUtil
    from com.infinitekind.util import StringUtils
    from com.infinitekind.moneydance.model import Account, AccountUtil, AcctFilter
    from java.lang import Math
    
    RJ_DIVIDEND_ACCOUNT_NAME = "Raymond James Bank Deposit Program"
    
    MD_REF = moneydance                         # Entry point into the Moneydance API
    book = MD_REF.getCurrentAccountBook()   # Entry point into your dataset
    ra = MD_REF.getRootAccount()
    
    investment_account_name = "RJF John Roth"
    investment_acct = ra.getAccountByName(investment_account_name)
    
    security_acct_name = investment_account_name + ":" + RJ_DIVIDEND_ACCOUNT_NAME
    security_acct = ra.getAccountByName(security_acct_name)
    
    assert investment_acct is not None and security_acct is not None
    
    print investment_acct
    print security_acct, "uuid", security_acct.getUUID()
    
    ta = AccountUtil.getDefaultTransferAcct(investment_acct)
    fa = AccountUtil.getDefaultCategoryForAcct(investment_acct)
    dc = AccountUtil.getDefaultCategoryForAcct(investment_acct)
    
    assert ta is not None and fa is not None and dc is not None
    print "TA:", ta
    print "FA:", fa
    print "DC:", dc
    
    date = DateUtil.getStrippedDateInt()
    print date
    
    
    
    niceCheckNum = ""
    desc = "this_is_description"
    memo = "this_is_memo"
    
    
    
    #-- Create Parent Transaction
    pTxn = ParentTxn.makeParentTxn(
        book,
        date,
        date,
        DateUtil.getUniqueCurrentTimeMillis(),
        niceCheckNum,
        investment_acct,
        desc,
        memo,
        -1L,
        AbstractTxn.ClearedStatus.UNRECONCILED.legacyValue())
    
    
    txnType = InvestTxnType.DIVIDEND
    totalAmount = long(99)
    
    fields = InvestFields()
    fields.setFieldStatus(txnType, pTxn)
    fields.date = date
    fields.taxDate = date
    fields.checkNum = niceCheckNum
    fields.payee = desc
    fields.memo = memo
    fields.amount = totalAmount
    fields.shares = 0
    fields.price = 1
    
    fields.xfrAcct = ta
    
    fields.fee = 0
    
    fields.feeAcct = fa
    fields.category = dc
    
    fields.security = security_acct
    fields.storeFields(pTxn)
    print("stored fields ", fields, " as txn ", pTxn)
    pTxn.syncItem()
    

    Attached is the result....

    I think you should improve the method of getting the account(s), but that can be done later....

    Let me know how you get on?

  2. 2 Posted by Stuart Beesley ... on 23 Oct, 2024 08:02 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    FYI. For future use, as a suggestion, I would probably find the various accounts’ UUIDs and use these to lookup the objects. Using:
    https://infinitekind.com/dev/apidoc/com/infinitekind/moneydance/mod...

    E.g.

    id = “c7c08012-1685-441e-a69d-1878b7b52d97”
    investAcct=book.getAccountByUUID​(id)
    

    you can do this for both the accounts and the categories.

  3. Support Staff 3 Posted by Sean Reilly on 23 Oct, 2024 08:07 PM

    Sean Reilly's Avatar

    Hi John,

    The problem in this case is that the fields.category property needs to be set to a non-null category Account. You're right that we should have a more useful error in that situation!

    Thanks,
    Sean

    --
    Sean Reilly
    Developer, The Infinite Kind
    https://infinitekind.com

  4. 4 Posted by john.vogtle+inf... on 23 Oct, 2024 09:56 PM

    john.vogtle+infinitekind's Avatar

    Thanks Stuart and Sean!

    It now works like a champ.

    Stuart - while I agree that grabbing things by UUID is going to guarantee uniqueness, the only way that was apparent to me to get the UUID was to look it up by name.
    The script itself is a small part of a larger script where I can get the investment account UUID from the transaction but I still need to obtain the Security Account based on the name.

    If there's a better way of getting the UUIDs, I'm open to improving things.

    Sean - thanks for considering the logging improvement. It's hard when you don't have access to the source! :)

  5. 5 Posted by Stuart Beesley ... on 23 Oct, 2024 10:15 PM

    Stuart Beesley (Mr Toolbox)'s Avatar

    If you already have transaction object then you don’t of course need the uuid, you can just use the txn’s getAccount() method and pass that.

    My comments were about when hardcoding account lookups by name. There’s nothing wrong with this, but prone to error if the lookup fails or names change, that’s all. I guess if you are doing account lookups you should always check the result is not None.

    FYI. To get an account’s uuid, open console to enable MD debug mode. Then tools/accounts. Then right click and show raw details.

  6. 6 Posted by john.vogtle+inf... on 23 Oct, 2024 11:51 PM

    john.vogtle+infinitekind's Avatar

    Awesome hint! Thank you!

  7. john.vogtle+infinitekind closed this discussion on 24 Oct, 2024 11:16 AM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac