我想创建一个由电子邮件过滤器触发的脚本,该脚本在运行时会在 GnuCash 中创建两个事务。我看到GnuCash 具有 Python 绑定,但文档充其量是稀疏的……更好的术语是“不存在”。
是否可以编写一个脚本来在 GnuCash 中创建交易?如果是这样,最基本的代码会是什么样子?我只需要一个起点;一旦我有了它,我自己就可以很好地编写这个脚本。
我想创建一个由电子邮件过滤器触发的脚本,该脚本在运行时会在 GnuCash 中创建两个事务。我看到GnuCash 具有 Python 绑定,但文档充其量是稀疏的……更好的术语是“不存在”。
是否可以编写一个脚本来在 GnuCash 中创建交易?如果是这样,最基本的代码会是什么样子?我只需要一个起点;一旦我有了它,我自己就可以很好地编写这个脚本。
这是使用 piecash 的替代解决方案(https://github.com/sdementen/piecash,版本 0.10.1),这是一个现代 python 库,用于处理 gnucash 书籍(免责声明:我是作者)
from piecash import open_book, Transaction, Split
from datetime import datetime
from decimal import Decimal
# open the book
with open_book("/path/to/file.gnucash",
open_if_lock=True,
readonly=False) as mybook:
today = datetime.now()
# retrieve the currency from the book
USD = mybook.currencies(mnemonic="USD")
# define the amount as Decimal
amount = Decimal("25.35")
# retrieve accounts
to_account = mybook.accounts(fullname="Expenses:Some Expense Account")
from_account = mybook.accounts(fullname="Assets:Current Assets:Checking")
# create the transaction with its two splits
Transaction(
post_date=today,
enter_date=today,
currency=USD,
description="Transaction Description!",
splits=[
Split(account=to_account,
value=amount,
memo="Split Memo!"),
Split(account=from_account,
value=-amount,
memo="Other Split Memo!"),
]
)
# save the book
mybook.save()
这是一个模板,以及库中非常缺乏的几个帐户查找功能。您可以将所有事务代码放入一个函数中,然后提交创建两个自定义事务所需的任何数据。然后只需从您的电子邮件侦听器调用事务功能,您就应该开始工作了。
from gnucash import Session, Account, Transaction, Split, GncNumeric
import gnucash
from datetime import datetime
def lookup_account_by_path(parent, path):
acc = parent.lookup_by_name(path[0])
if acc.get_instance() == None:
raise Exception('Account path {} not found'.format(':'.join(path)))
if len(path) > 1:
return lookup_account_by_path(acc, path[1:])
return acc
def lookup_account(root, name):
path = name.split(':')
return lookup_account_by_path(root, path)
session = Session("/path/to/file.gnucash") #, ignore_lock=True)
# or use URI string: ('mysql://USER:PASSWORD@HOST/DATABASE')
today = datetime.now()
book = session.book # All actions are performed through the book object (or its children)
root = book.get_root_account() # Parent of all accounts
currency = book.get_table().lookup('ISO4217', "USD")
tx = Transaction(book)
tx.BeginEdit()
tx.SetCurrency(currency)
tx.SetDateEnteredTS(today)
tx.SetDatePostedTS(today) # or another datetime object for the transaction's "register date"
tx.SetDescription("Transaction Description!")
#tx.SetNum(int_variable) # if you need a transaction number
sp1 = Split(book) # First half of transaction
sp1.SetParent(tx)
# The lookup string needs to match your account path exactly.
sp1.SetAccount(lookup_account(root, "Expenses:Some Expense Account"))
# amount is an int (no $ or .), so $5.23 becomes amount=523
sp1.SetValue(GncNumeric(amount, 100)) # Assuming you only have one split
# For multiple splits, you need to make sure the totals all balance out.
sp1.SetAmount(GncNumeric(amount, 100))
sp1.SetMemo("Split Memo!") # optional
sp2 = Split(book) # Need a balancing split
sp2.SetParent(tx)
sp2.SetAccount(lookup_account(root, "Assets:Current Assets:Checking"))
sp2.SetValue(sp1.GetValue().neg())
sp2.SetAmount(sp1.GetValue().neg())
sp2.SetMemo("Other Split Memo!") # optional
tx.CommitEdit() # Finish editing transaction
session.save()
session.end()