|
|
c17846b |
# gnucash_core.py -- High level python wrapper classes for the core parts
|
|
|
c17846b |
# of GnuCash
|
|
|
c17846b |
#
|
|
|
c17846b |
# Copyright (C) 2008 ParIT Worker Co-operative <paritinfo@parit.ca>
|
|
|
c17846b |
# This program is free software; you can redistribute it and/or
|
|
|
c17846b |
# modify it under the terms of the GNU General Public License as
|
|
|
c17846b |
# published by the Free Software Foundation; either version 2 of
|
|
|
c17846b |
# the License, or (at your option) any later version.
|
|
|
c17846b |
#
|
|
|
c17846b |
# This program is distributed in the hope that it will be useful,
|
|
|
c17846b |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
c17846b |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
c17846b |
# GNU General Public License for more details.
|
|
|
c17846b |
#
|
|
|
c17846b |
# You should have received a copy of the GNU General Public License
|
|
|
c17846b |
# along with this program; if not, contact:
|
|
|
c17846b |
# Free Software Foundation Voice: +1-617-542-5942
|
|
|
c17846b |
# 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
|
|
|
c17846b |
# Boston, MA 02110-1301, USA gnu@gnu.org
|
|
|
c17846b |
#
|
|
|
c17846b |
# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
|
|
|
c17846b |
# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
|
|
|
c17846b |
|
|
|
c17846b |
# The following is for doxygen
|
|
|
c17846b |
## @file
|
|
|
c17846b |
# @brief High level python wrapper classes for the core parts of GnuCash
|
|
|
c17846b |
# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
|
|
|
c17846b |
# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca>
|
|
|
c17846b |
# @ingroup python_bindings
|
|
|
c17846b |
|
|
|
c17846b |
import gnucash_core_c
|
|
|
c17846b |
|
|
|
c17846b |
from function_class import \
|
|
|
c17846b |
ClassFromFunctions, extract_attributes_with_prefix, \
|
|
|
c17846b |
default_arguments_decorator, method_function_returns_instance, \
|
|
|
c17846b |
methods_return_instance, process_list_convert_to_instance, \
|
|
|
c17846b |
method_function_returns_instance_list, methods_return_instance_lists
|
|
|
c17846b |
|
|
|
c17846b |
from gnucash_core_c import gncInvoiceLookup, gncInvoiceGetInvoiceFromTxn, \
|
|
|
c17846b |
gncInvoiceGetInvoiceFromLot, gncEntryLookup, gncInvoiceLookup, \
|
|
|
c17846b |
gncCustomerLookup, gncVendorLookup, gncJobLookup, gncEmployeeLookup, \
|
|
|
c17846b |
gncTaxTableLookup, gncTaxTableLookupByName, gnc_search_invoice_on_id, \
|
|
|
c17846b |
gnc_search_customer_on_id, gnc_search_bill_on_id , gnc_search_vendor_on_id, \
|
|
|
c17846b |
gncInvoiceNextID, gncCustomerNextID, gncTaxTableGetTables, gncVendorNextID
|
|
|
c17846b |
|
|
|
c17846b |
class GnuCashCoreClass(ClassFromFunctions):
|
|
|
c17846b |
_module = gnucash_core_c
|
|
|
c17846b |
|
|
|
c17846b |
def do_lookup_create_oo_instance(self, lookup_function, cls, *args):
|
|
|
c17846b |
thing = lookup_function(self.get_instance(), *args)
|
|
|
c17846b |
if thing != None:
|
|
|
c17846b |
thing = cls(instance=thing)
|
|
|
c17846b |
return thing
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
class GnuCashBackendException(Exception):
|
|
|
c17846b |
def __init__(self, msg, errors):
|
|
|
c17846b |
Exception.__init__(self, msg)
|
|
|
c17846b |
self.errors = errors
|
|
|
c17846b |
|
|
|
c17846b |
class Session(GnuCashCoreClass):
|
|
|
c17846b |
"""A GnuCash book editing session
|
|
|
c17846b |
|
|
|
c17846b |
To commit changes to the session you may need to call save,
|
|
|
c17846b |
(this is always the case with the file backend).
|
|
|
c17846b |
|
|
|
c17846b |
When you're down with a session you may need to call end()
|
|
|
c17846b |
|
|
|
c17846b |
Every Session has a Book in the book attribute, which you'll definitely
|
|
|
c17846b |
be interested in, as every GnuCash entity (Transaction, Split, Vendor,
|
|
|
c17846b |
Invoice..) is associated with a particular book where it is stored.
|
|
|
c17846b |
"""
|
|
|
c17846b |
|
|
|
c17846b |
def __init__(self, book_uri=None, ignore_lock=False, is_new=False,
|
|
|
c17846b |
force_new= False):
|
|
|
c17846b |
"""A convenient constructor that allows you to specify a book URI,
|
|
|
c17846b |
begin the session, and load the book.
|
|
|
c17846b |
|
|
|
c17846b |
This can give you the power of calling
|
|
|
c17846b |
qof_session_new, qof_session_begin, and qof_session_load all in one!
|
|
|
c17846b |
|
|
|
c17846b |
book_uri can be None to skip the calls to qof_session_begin and
|
|
|
c17846b |
qof_session_load, or it can be a string like "file:/test.xac"
|
|
|
c17846b |
|
|
|
c17846b |
qof_session_load is only called if is_new is set to False
|
|
|
c17846b |
|
|
|
c17846b |
is_new is passed to qof_session_begin as the argument create,
|
|
|
c17846b |
and force_new as the argument force. Is_new will create a new
|
|
|
c17846b |
database or file; force will force creation even if it will
|
|
|
c17846b |
destroy an existing dataset.
|
|
|
c17846b |
|
|
|
c17846b |
ignore_lock is passed to qof_session_begin's argument of the
|
|
|
c17846b |
same name and is used to break an existing lock on a dataset.
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
This function can raise a GnuCashBackendException. If it does,
|
|
|
c17846b |
you don't need to cleanup and call end() and destroy(), that is handled
|
|
|
c17846b |
for you, and the exception is raised.
|
|
|
c17846b |
"""
|
|
|
c17846b |
GnuCashCoreClass.__init__(self)
|
|
|
c17846b |
if book_uri is not None:
|
|
|
c17846b |
try:
|
|
|
c17846b |
self.begin(book_uri, ignore_lock, is_new, force_new)
|
|
|
c17846b |
# Take care of backend inconsistency
|
|
|
c17846b |
# New xml file can't be loaded, new sql store
|
|
|
c17846b |
# has to be loaded before it can be altered
|
|
|
c17846b |
# Any existing store obviously has to be loaded
|
|
|
c17846b |
# More background: https://bugzilla.gnome.org/show_bug.cgi?id=726891
|
|
|
c17846b |
if book_uri[:3] != "xml" or not is_new:
|
|
|
c17846b |
self.load()
|
|
|
c17846b |
except GnuCashBackendException, backend_exception:
|
|
|
c17846b |
self.end()
|
|
|
c17846b |
self.destroy()
|
|
|
c17846b |
raise
|
|
|
c17846b |
|
|
|
c17846b |
def raise_backend_errors(self, called_function="qof_session function"):
|
|
|
c17846b |
"""Raises a GnuCashBackendException if there are outstanding
|
|
|
c17846b |
QOF_BACKEND errors.
|
|
|
c17846b |
|
|
|
c17846b |
set called_function to name the function that was last called
|
|
|
c17846b |
"""
|
|
|
c17846b |
errors = self.pop_all_errors()
|
|
|
c17846b |
if errors != ():
|
|
|
c17846b |
raise GnuCashBackendException(
|
|
|
c17846b |
"call to %s resulted in the "
|
|
|
c17846b |
"following errors, %s" % (called_function, backend_error_dict[errors[0]]),
|
|
|
c17846b |
errors )
|
|
|
c17846b |
|
|
|
c17846b |
def generate_errors(self):
|
|
|
c17846b |
"""A generator that yields any outstanding QofBackend errors
|
|
|
c17846b |
"""
|
|
|
c17846b |
while self.get_error() is not ERR_BACKEND_NO_ERR:
|
|
|
c17846b |
error = self.pop_error()
|
|
|
c17846b |
yield error
|
|
|
c17846b |
|
|
|
c17846b |
def pop_all_errors(self):
|
|
|
c17846b |
"""Returns any accumulated qof backend errors as a tuple
|
|
|
c17846b |
"""
|
|
|
c17846b |
return tuple( self.generate_errors() )
|
|
|
c17846b |
|
|
|
c17846b |
# STATIC METHODS
|
|
|
c17846b |
@staticmethod
|
|
|
c17846b |
def raise_backend_errors_after_call(function):
|
|
|
c17846b |
"""A function decorator that results in a call to
|
|
|
c17846b |
raise_backend_errors after execution.
|
|
|
c17846b |
"""
|
|
|
c17846b |
def new_function(self, *args):
|
|
|
c17846b |
return_value = function(self, *args)
|
|
|
c17846b |
self.raise_backend_errors(function.__name__)
|
|
|
c17846b |
return return_value
|
|
|
c17846b |
return new_function
|
|
|
c17846b |
|
|
|
c17846b |
class Book(GnuCashCoreClass):
|
|
|
c17846b |
"""A Book encapsulates all of the GnuCash data, it is the place where
|
|
|
c17846b |
all GnuCash entities (Transaction, Split, Vendor, Invoice...), are
|
|
|
c17846b |
stored. You'll notice that all of the constructors for those entities
|
|
|
c17846b |
need a book to be associated with.
|
|
|
c17846b |
|
|
|
c17846b |
The most common way to get a book is through the book property in the
|
|
|
c17846b |
Session class, that is, create a session that connects to some storage,
|
|
|
c17846b |
such as through 'my_session = Session('file:my_books.xac')', and access
|
|
|
c17846b |
the book via the book property, 'my_session.book'
|
|
|
c17846b |
|
|
|
c17846b |
If you would like to create a Book without any backing storage, call the
|
|
|
c17846b |
Book constructor without any parameters, 'Book()'. You can later merge
|
|
|
c17846b |
such a book into a book with actual store by using merge_init.
|
|
|
c17846b |
|
|
|
c17846b |
Methods of interest
|
|
|
c17846b |
get_root_account -- Returns the root level Account
|
|
|
c17846b |
get_table -- Returns a commodity lookup table, of type GncCommodityTable
|
|
|
c17846b |
"""
|
|
|
c17846b |
def InvoiceLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Invoice
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncInvoiceLookup, Invoice, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def EntryLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Entr
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncEntryLookup, Entry, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def CustomerLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Customer
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncCustomerLookup, Customer, guid.get_instance())
|
|
|
c17846b |
|
|
|
c17846b |
def JobLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Job
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncJobLookup, Job, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def VendorLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Vendor
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncVendorLookup, Vendor, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def EmployeeLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import Employee
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncEmployeeLookup, Employee, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def TaxTableLookup(self, guid):
|
|
|
c17846b |
from gnucash_business import TaxTable
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncTaxTableLookup, TaxTable, guid.get_instance() )
|
|
|
c17846b |
|
|
|
c17846b |
def TaxTableLookupByName(self, name):
|
|
|
c17846b |
from gnucash_business import TaxTable
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncTaxTableLookupByName, TaxTable, name)
|
|
|
c17846b |
|
|
|
c17846b |
def TaxTableGetTables(self):
|
|
|
c17846b |
from gnucash_business import TaxTable
|
|
|
c17846b |
return [ TaxTable(instance=item) for item in gncTaxTableGetTables(self.instance) ]
|
|
|
c17846b |
|
|
|
c17846b |
def BillLoookupByID(self, id):
|
|
|
c17846b |
from gnucash_business import Bill
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gnc_search_bill_on_id, Bill, id)
|
|
|
c17846b |
|
|
|
c17846b |
def InvoiceLookupByID(self, id):
|
|
|
c17846b |
from gnucash_business import Invoice
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gnc_search_invoice_on_id, Invoice, id)
|
|
|
c17846b |
|
|
|
c17846b |
def CustomerLookupByID(self, id):
|
|
|
c17846b |
from gnucash_business import Customer
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gnc_search_customer_on_id, Customer, id)
|
|
|
c17846b |
|
|
|
c17846b |
def VendorLookupByID(self, id):
|
|
|
c17846b |
from gnucash_business import Vendor
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gnc_search_vendor_on_id, Vendor, id)
|
|
|
c17846b |
|
|
|
c17846b |
def InvoiceNextID(self, customer):
|
|
|
c17846b |
''' Return the next invoice ID.
|
|
|
c17846b |
This works but I'm not entirely happy with it. FIX ME'''
|
|
|
c17846b |
from gnucash.gnucash_core_c import gncInvoiceNextID
|
|
|
c17846b |
return gncInvoiceNextID(self.get_instance(),customer.GetEndOwner().get_instance()[1])
|
|
|
c17846b |
|
|
|
c17846b |
def BillNextID(self, vendor):
|
|
|
c17846b |
''' Return the next Bill ID. '''
|
|
|
c17846b |
from gnucash.gnucash_core_c import gncInvoiceNextID
|
|
|
c17846b |
return gncInvoiceNextID(self.get_instance(),vendor.GetEndOwner().get_instance()[1])
|
|
|
c17846b |
|
|
|
c17846b |
def CustomerNextID(self):
|
|
|
c17846b |
''' Return the next Customer ID. '''
|
|
|
c17846b |
from gnucash.gnucash_core_c import gncCustomerNextID
|
|
|
c17846b |
return gncCustomerNextID(self.get_instance())
|
|
|
c17846b |
|
|
|
c17846b |
def VendorNextID(self):
|
|
|
c17846b |
''' Return the next Vendor ID. '''
|
|
|
c17846b |
from gnucash.gnucash_core_c import gncVendorNextID
|
|
|
c17846b |
return gncVendorNextID(self.get_instance())
|
|
|
c17846b |
|
|
|
c17846b |
class GncNumeric(GnuCashCoreClass):
|
|
|
c17846b |
"""Object used by GnuCash to store all numbers. Always consists of a
|
|
|
c17846b |
numerator and denominator.
|
|
|
c17846b |
|
|
|
c17846b |
The constants GNC_DENOM_AUTO,
|
|
|
c17846b |
GNC_HOW_RND_FLOOR, GNC_HOW_RND_CEIL, GNC_HOW_RND_TRUNC,
|
|
|
c17846b |
GNC_HOW_RND_PROMOTE, GNC_HOW_RND_ROUND_HALF_DOWN,
|
|
|
c17846b |
GNC_HOW_RND_ROUND_HALF_UP, GNC_HOW_RND_ROUND, GNC_HOW_RND_NEVER,
|
|
|
c17846b |
GNC_HOW_DENOM_EXACT, GNC_HOW_DENOM_REDUCE, GNC_HOW_DENOM_LCD,
|
|
|
c17846b |
and GNC_HOW_DENOM_FIXED are available for arithmetic
|
|
|
c17846b |
functions like GncNumeric.add
|
|
|
c17846b |
|
|
|
c17846b |
Look at gnc-numeric.h to see how to use these
|
|
|
c17846b |
"""
|
|
|
c17846b |
|
|
|
c17846b |
def __init__(self, num=0, denom=1, **kargs):
|
|
|
c17846b |
"""Constructor that allows you to set the numerator and denominator or
|
|
|
c17846b |
leave them blank with a default value of 0 (not a good idea since there
|
|
|
c17846b |
is currently no way to alter the value after instantiation)
|
|
|
c17846b |
"""
|
|
|
c17846b |
GnuCashCoreClass.__init__(self, num, denom, **kargs)
|
|
|
c17846b |
#if INSTANCE_ARG in kargs:
|
|
|
c17846b |
# GnuCashCoreClass.__init__(**kargs)
|
|
|
c17846b |
#else:
|
|
|
c17846b |
# self.set_denom(denom) # currently undefined
|
|
|
c17846b |
# self.set_num(num) # currently undefined
|
|
|
c17846b |
|
|
|
c17846b |
def __unicode__(self):
|
|
|
c17846b |
"""Returns a human readable numeric value string as UTF8."""
|
|
|
c17846b |
if self.denom() == 0:
|
|
|
c17846b |
return "Division by zero"
|
|
|
c17846b |
else:
|
|
|
c17846b |
value_float = self.to_double()
|
|
|
c17846b |
value_str = u"{0:.{1}f}".format(value_float,2) ## The second argument is the precision. It would be nice to be able to make it configurable.
|
|
|
c17846b |
return value_str
|
|
|
c17846b |
|
|
|
c17846b |
def __str__(self):
|
|
|
c17846b |
"""returns a human readable numeric value string as bytes."""
|
|
|
c17846b |
return unicode(self).encode('utf-8')
|
|
|
c17846b |
|
|
|
c17846b |
class GncPrice(GnuCashCoreClass):
|
|
|
c17846b |
'''
|
|
|
c17846b |
Each priceEach price in the database represents an "instantaneous"
|
|
|
c17846b |
quote for a given commodity with respect to another commodity.
|
|
|
c17846b |
For example, a given price might represent the value of LNUX in USD on 2001-02-03.
|
|
|
c17846b |
|
|
|
c17846b |
Fields:
|
|
|
c17846b |
* commodity: the item being priced.
|
|
|
c17846b |
* currency: the denomination of the value of the item being priced.
|
|
|
c17846b |
* value: the value of the item being priced.
|
|
|
c17846b |
* time: the time the price was valid.
|
|
|
c17846b |
* source: a string describing the source of the quote. These strings will be something like this:
|
|
|
c17846b |
"Finance::Quote", "user:misc", "user:foo", etc. If the quote came from a user, as a matter of policy,
|
|
|
c17846b |
you *must* prefix the string you give with "user:". For now, the only other reserved values are
|
|
|
c17846b |
"Finance::Quote" and "old-file-import". Any string used must be added to the source_list array in
|
|
|
c17846b |
dialog-price-edit-db.c so that it can be properly translated. (There are unfortunately many strings
|
|
|
c17846b |
in users' databases, so this string must be translated on output instead of always being used in untranslated form).
|
|
|
c17846b |
* type: the type of quote - types possible right now are bid, ask, last, nav, and
|
|
|
c17846b |
unknown.Each price in the database represents an "instantaneous" quote for a given
|
|
|
c17846b |
commodity with respect to another commodity.
|
|
|
c17846b |
For example, a given price might represent the value of LNUX in USD on 2001-02-03.
|
|
|
c17846b |
|
|
|
c17846b |
See also http://code.gnucash.org/docs/head/group__Price.html
|
|
|
c17846b |
'''
|
|
|
c17846b |
pass
|
|
|
c17846b |
GncPrice.add_methods_with_prefix('gnc_price_')
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
class GncPriceDB(GnuCashCoreClass):
|
|
|
c17846b |
'''
|
|
|
c17846b |
a simple price database for gnucash.
|
|
|
c17846b |
The PriceDB is intended to be a database of price quotes, or more specifically,
|
|
|
c17846b |
a database of GNCPrices. For the time being, it is still a fairly simple
|
|
|
c17846b |
database supporting only fairly simple queries. It is expected that new
|
|
|
c17846b |
queries will be added as needed, and that there is some advantage to delaying
|
|
|
c17846b |
complex queries for now in the hope that we get a real DB implementation
|
|
|
c17846b |
before they're really needed.
|
|
|
c17846b |
|
|
|
c17846b |
Every QofBook contains a GNCPriceDB, accessible via gnc_pricedb_get_db.
|
|
|
c17846b |
|
|
|
c17846b |
Definition in file gnc-pricedb.h.
|
|
|
c17846b |
See also http://code.gnucash.org/docs/head/gnc-pricedb_8h.html
|
|
|
c17846b |
'''
|
|
|
c17846b |
|
|
|
c17846b |
GncPriceDB.add_methods_with_prefix('gnc_pricedb_')
|
|
|
c17846b |
PriceDB_dict = {
|
|
|
c17846b |
'lookup_latest' : GncPrice,
|
|
|
c17846b |
'lookup_nearest_in_time' : GncPrice,
|
|
|
c17846b |
'lookup_latest_before' : GncPrice,
|
|
|
c17846b |
'convert_balance_latest_price' : GncNumeric,
|
|
|
c17846b |
'convert_balance_nearest_price' : GncNumeric,
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(GncPriceDB,PriceDB_dict)
|
|
|
c17846b |
GncPriceDB.get_prices = method_function_returns_instance_list(
|
|
|
c17846b |
GncPriceDB.get_prices, GncPrice )
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
class GncCommodity(GnuCashCoreClass): pass
|
|
|
c17846b |
|
|
|
c17846b |
class GncCommodityTable(GnuCashCoreClass):
|
|
|
c17846b |
"""A CommodityTable provides a way to store and lookup commodities.
|
|
|
c17846b |
Commodities are primarily currencies, but other tradable things such as
|
|
|
c17846b |
stocks, mutual funds, and material substances are possible.
|
|
|
c17846b |
|
|
|
c17846b |
Users of this library should not create their own CommodityTable, instead
|
|
|
c17846b |
the get_table method from the Book class should be used.
|
|
|
c17846b |
|
|
|
c17846b |
This table is automatically populated with the GnuCash default commodity's
|
|
|
c17846b |
which includes most of the world's currencies.
|
|
|
c17846b |
"""
|
|
|
c17846b |
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
class GncCommodityNamespace(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
class GncLot(GnuCashCoreClass):
|
|
|
c17846b |
def GetInvoiceFromLot(self):
|
|
|
c17846b |
from gnucash_business import Invoice
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncInvoiceGetInvoiceFromLot, Invoice )
|
|
|
c17846b |
|
|
|
c17846b |
class Transaction(GnuCashCoreClass):
|
|
|
c17846b |
"""A GnuCash Transaction
|
|
|
c17846b |
|
|
|
c17846b |
Consists of at least one (generally two) splits to represent a transaction
|
|
|
c17846b |
between two accounts.
|
|
|
c17846b |
|
|
|
c17846b |
|
|
|
c17846b |
Has a GetImbalance() method that returns a list of all the imbalanced
|
|
|
c17846b |
currencies. Each list item is a two element tuple, the first element is
|
|
|
c17846b |
the imbalanced commodity, the second element is the value.
|
|
|
c17846b |
|
|
|
c17846b |
Warning, the commodity.get_instance() value can be None when there
|
|
|
c17846b |
is no currency set for the transaction.
|
|
|
c17846b |
"""
|
|
|
c17846b |
_new_instance = 'xaccMallocTransaction'
|
|
|
c17846b |
def GetNthSplit(self, n):
|
|
|
c17846b |
return self.GetSplitList().pop(n)
|
|
|
c17846b |
|
|
|
c17846b |
def GetInvoiceFromTxn(self):
|
|
|
c17846b |
from gnucash_business import Transaction
|
|
|
c17846b |
return self.do_lookup_create_oo_instance(
|
|
|
c17846b |
gncInvoiceGetInvoiceFromTxn, Transaction )
|
|
|
c17846b |
|
|
|
c17846b |
def decorate_monetary_list_returning_function(orig_function):
|
|
|
c17846b |
def new_function(self):
|
|
|
c17846b |
# warning, item.commodity has been shown to be None
|
|
|
c17846b |
# when the transaction doesn't have a currency
|
|
|
c17846b |
return [(GncCommodity(instance=item.commodity),
|
|
|
c17846b |
GncNumeric(instance=item.value))
|
|
|
c17846b |
for item in orig_function(self) ]
|
|
|
c17846b |
return new_function
|
|
|
c17846b |
|
|
|
c17846b |
class Split(GnuCashCoreClass):
|
|
|
c17846b |
"""A GnuCash Split
|
|
|
c17846b |
|
|
|
c17846b |
The most basic representation of a movement of currency from one account to
|
|
|
c17846b |
another.
|
|
|
c17846b |
"""
|
|
|
c17846b |
_new_instance = 'xaccMallocSplit'
|
|
|
c17846b |
|
|
|
c17846b |
class Account(GnuCashCoreClass):
|
|
|
c17846b |
"""A GnuCash Account.
|
|
|
c17846b |
|
|
|
c17846b |
A fundamental entity in accounting, an Account provides representation
|
|
|
c17846b |
for a financial object, such as a ACCT_TYPE_BANK account, an
|
|
|
c17846b |
ACCT_TYPE_ASSET (like a building),
|
|
|
c17846b |
a ACCT_TYPE_LIABILITY (such as a bank loan), a summary of some type of
|
|
|
c17846b |
ACCT_TYPE_EXPENSE, or a summary of some source of ACCT_TYPE_INCOME .
|
|
|
c17846b |
|
|
|
c17846b |
The words in upper case are the constants that GnuCash and this library uses
|
|
|
c17846b |
to describe account type. Here is the full list:
|
|
|
c17846b |
ACCT_TYPE_ASSET, ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CHECKING, \
|
|
|
c17846b |
ACCT_TYPE_CREDIT, ACCT_TYPE_EQUITY, ACCT_TYPE_EXPENSE, ACCT_TYPE_INCOME, \
|
|
|
c17846b |
ACCT_TYPE_LIABILITY, ACCT_TYPE_MUTUAL, ACCT_TYPE_PAYABLE, \
|
|
|
c17846b |
ACCT_TYPE_RECEIVABLE, ACCT_TYPE_STOCK, ACCT_TYPE_ROOT, ACCT_TYPE_TRADING
|
|
|
c17846b |
|
|
|
c17846b |
These are not strings, they are attributes you can import from this
|
|
|
c17846b |
module
|
|
|
c17846b |
"""
|
|
|
c17846b |
_new_instance = 'xaccMallocAccount'
|
|
|
c17846b |
|
|
|
c17846b |
class GUID(GnuCashCoreClass):
|
|
|
c17846b |
_new_instance = 'guid_new_return'
|
|
|
c17846b |
|
|
|
c17846b |
# Session
|
|
|
c17846b |
Session.add_constructor_and_methods_with_prefix('qof_session_', 'new')
|
|
|
c17846b |
|
|
|
c17846b |
def one_arg_default_none(function):
|
|
|
c17846b |
return default_arguments_decorator(function, None, None)
|
|
|
c17846b |
Session.decorate_functions(one_arg_default_none, "load", "save")
|
|
|
c17846b |
|
|
|
c17846b |
Session.decorate_functions( Session.raise_backend_errors_after_call,
|
|
|
c17846b |
"begin", "load", "save", "end")
|
|
|
c17846b |
Session.get_book = method_function_returns_instance(
|
|
|
c17846b |
Session.get_book, Book )
|
|
|
c17846b |
|
|
|
c17846b |
Session.book = property( Session.get_book )
|
|
|
c17846b |
|
|
|
c17846b |
# import all of the session backend error codes into this module
|
|
|
c17846b |
this_module_dict = globals()
|
|
|
c17846b |
for error_name, error_value, error_name_after_prefix in \
|
|
|
c17846b |
extract_attributes_with_prefix(gnucash_core_c, 'ERR_'):
|
|
|
c17846b |
this_module_dict[ error_name ] = error_value
|
|
|
c17846b |
|
|
|
c17846b |
#backend error codes used for reverse lookup
|
|
|
c17846b |
backend_error_dict = {}
|
|
|
c17846b |
for error_name, error_value, error_name_after_prefix in \
|
|
|
c17846b |
extract_attributes_with_prefix(gnucash_core_c, 'ERR_'):
|
|
|
c17846b |
backend_error_dict[ error_value ] = error_name
|
|
|
c17846b |
|
|
|
c17846b |
# GncNumeric denominator computation schemes
|
|
|
c17846b |
# Used for the denom argument in arithmetic functions like GncNumeric.add
|
|
|
c17846b |
from gnucash.gnucash_core_c import GNC_DENOM_AUTO
|
|
|
c17846b |
|
|
|
c17846b |
# GncNumeric rounding instructions
|
|
|
c17846b |
# used for the how argument in arithmetic functions like GncNumeric.add
|
|
|
c17846b |
from gnucash.gnucash_core_c import \
|
|
|
c17846b |
GNC_HOW_RND_FLOOR, GNC_HOW_RND_CEIL, GNC_HOW_RND_TRUNC, \
|
|
|
c17846b |
GNC_HOW_RND_PROMOTE, GNC_HOW_RND_ROUND_HALF_DOWN, \
|
|
|
c17846b |
GNC_HOW_RND_ROUND_HALF_UP, GNC_HOW_RND_ROUND, GNC_HOW_RND_NEVER
|
|
|
c17846b |
|
|
|
c17846b |
# GncNumeric denominator types
|
|
|
c17846b |
# used for the how argument in arithmetic functions like GncNumeric.add
|
|
|
c17846b |
from gnucash.gnucash_core_c import \
|
|
|
c17846b |
GNC_HOW_DENOM_EXACT, GNC_HOW_DENOM_REDUCE, GNC_HOW_DENOM_LCD, \
|
|
|
c17846b |
GNC_HOW_DENOM_FIXED
|
|
|
c17846b |
|
|
|
c17846b |
# import account types
|
|
|
c17846b |
from gnucash.gnucash_core_c import \
|
|
|
c17846b |
ACCT_TYPE_ASSET, ACCT_TYPE_BANK, ACCT_TYPE_CASH, ACCT_TYPE_CHECKING, \
|
|
|
c17846b |
ACCT_TYPE_CREDIT, ACCT_TYPE_EQUITY, ACCT_TYPE_EXPENSE, ACCT_TYPE_INCOME, \
|
|
|
c17846b |
ACCT_TYPE_LIABILITY, ACCT_TYPE_MUTUAL, ACCT_TYPE_PAYABLE, \
|
|
|
c17846b |
ACCT_TYPE_RECEIVABLE, ACCT_TYPE_STOCK, ACCT_TYPE_ROOT, ACCT_TYPE_TRADING
|
|
|
c17846b |
|
|
|
c17846b |
#Book
|
|
|
c17846b |
Book.add_constructor_and_methods_with_prefix('qof_book_', 'new')
|
|
|
c17846b |
Book.add_method('gnc_book_get_root_account', 'get_root_account')
|
|
|
c17846b |
Book.add_method('gnc_book_set_root_account', 'set_root_account')
|
|
|
c17846b |
Book.add_method('gnc_commodity_table_get_table', 'get_table')
|
|
|
c17846b |
Book.add_method('gnc_pricedb_get_db', 'get_price_db')
|
|
|
c17846b |
Book.add_method('qof_book_increment_and_format_counter', 'increment_and_format_counter')
|
|
|
c17846b |
|
|
|
c17846b |
#Functions that return Account
|
|
|
c17846b |
Book.get_root_account = method_function_returns_instance(
|
|
|
c17846b |
Book.get_root_account, Account )
|
|
|
c17846b |
#Functions that return GncCommodityTable
|
|
|
c17846b |
Book.get_table = method_function_returns_instance(
|
|
|
c17846b |
Book.get_table, GncCommodityTable )
|
|
|
c17846b |
#Functions that return GNCPriceDB
|
|
|
c17846b |
Book.get_price_db = method_function_returns_instance(
|
|
|
c17846b |
Book.get_price_db, GncPriceDB)
|
|
|
c17846b |
|
|
|
c17846b |
# GncNumeric
|
|
|
c17846b |
GncNumeric.add_constructor_and_methods_with_prefix('gnc_numeric_', 'create')
|
|
|
c17846b |
|
|
|
c17846b |
gncnumeric_dict = {
|
|
|
c17846b |
'same' : GncNumeric,
|
|
|
c17846b |
'add' : GncNumeric,
|
|
|
c17846b |
'sub' : GncNumeric,
|
|
|
c17846b |
'mul' : GncNumeric,
|
|
|
c17846b |
'div' : GncNumeric,
|
|
|
c17846b |
'neg' : GncNumeric,
|
|
|
c17846b |
'abs' : GncNumeric,
|
|
|
c17846b |
'add_fixed' : GncNumeric,
|
|
|
c17846b |
'sub_fixed' : GncNumeric,
|
|
|
c17846b |
'add_with_error' : GncNumeric,
|
|
|
c17846b |
'sub_with_error' : GncNumeric,
|
|
|
c17846b |
'mul_with_error' : GncNumeric,
|
|
|
c17846b |
'div_with_error' : GncNumeric,
|
|
|
c17846b |
'convert' : GncNumeric,
|
|
|
c17846b |
'reduce' : GncNumeric
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(GncNumeric, gncnumeric_dict)
|
|
|
c17846b |
|
|
|
c17846b |
# GncCommodity
|
|
|
c17846b |
GncCommodity.add_constructor_and_methods_with_prefix('gnc_commodity_', 'new')
|
|
|
c17846b |
#Functions that return GncCommodity
|
|
|
c17846b |
GncCommodity.clone = method_function_returns_instance(
|
|
|
c17846b |
GncCommodity.clone, GncCommodity )
|
|
|
c17846b |
|
|
|
c17846b |
# GncCommodityTable
|
|
|
c17846b |
GncCommodityTable.add_methods_with_prefix('gnc_commodity_table_')
|
|
|
c17846b |
commoditytable_dict = {
|
|
|
c17846b |
'lookup' : GncCommodity,
|
|
|
c17846b |
'lookup_unique' : GncCommodity,
|
|
|
c17846b |
'find_full' : GncCommodity,
|
|
|
c17846b |
'insert' : GncCommodity,
|
|
|
c17846b |
'add_namespace': GncCommodityNamespace,
|
|
|
c17846b |
'find_namespace': GncCommodityNamespace,
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(GncCommodityTable, commoditytable_dict)
|
|
|
c17846b |
|
|
|
c17846b |
methods_return_instance_lists(
|
|
|
c17846b |
GncCommodityTable, { 'get_namespaces': GncCommodityNamespace,
|
|
|
c17846b |
'get_namespaces_list': GncCommodityNamespace,
|
|
|
c17846b |
'get_commodities': GncCommodity,
|
|
|
c17846b |
'get_quotable_commodities': GncCommodity,
|
|
|
c17846b |
|
|
|
c17846b |
} )
|
|
|
c17846b |
|
|
|
c17846b |
# GncCommodityNamespace
|
|
|
c17846b |
GncCommodityNamespace.add_methods_with_prefix('gnc_commodity_namespace_')
|
|
|
c17846b |
GncCommodityNamespace.get_commodity_list = \
|
|
|
c17846b |
method_function_returns_instance_list(
|
|
|
c17846b |
GncCommodityNamespace.get_commodity_list, GncCommodity )
|
|
|
c17846b |
|
|
|
c17846b |
# GncLot
|
|
|
c17846b |
GncLot.add_constructor_and_methods_with_prefix('gnc_lot_', 'new')
|
|
|
c17846b |
|
|
|
c17846b |
gnclot_dict = {
|
|
|
c17846b |
'get_account' : Account,
|
|
|
c17846b |
'get_book' : Book,
|
|
|
c17846b |
'get_earliest_split' : Split,
|
|
|
c17846b |
'get_latest_split' : Split,
|
|
|
c17846b |
'get_balance' : GncNumeric,
|
|
|
c17846b |
'lookup' : GncLot,
|
|
|
c17846b |
'make_default' : GncLot
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(GncLot, gnclot_dict)
|
|
|
c17846b |
|
|
|
c17846b |
# Transaction
|
|
|
c17846b |
Transaction.add_methods_with_prefix('xaccTrans')
|
|
|
c17846b |
Transaction.add_method('gncTransGetGUID', 'GetGUID');
|
|
|
c17846b |
|
|
|
c17846b |
trans_dict = {
|
|
|
c17846b |
'GetSplit': Split,
|
|
|
c17846b |
'FindSplitByAccount': Split,
|
|
|
c17846b |
'Clone': Transaction,
|
|
|
c17846b |
'Reverse': Transaction,
|
|
|
c17846b |
'GetReversedBy': Transaction,
|
|
|
c17846b |
'GetImbalanceValue': GncNumeric,
|
|
|
c17846b |
'GetAccountValue': GncNumeric,
|
|
|
c17846b |
'GetAccountAmount': GncNumeric,
|
|
|
c17846b |
'GetAccountConvRate': GncNumeric,
|
|
|
c17846b |
'GetAccountBalance': GncNumeric,
|
|
|
c17846b |
'GetCurrency': GncCommodity,
|
|
|
c17846b |
'GetGUID': GUID
|
|
|
c17846b |
}
|
|
|
c17846b |
|
|
|
c17846b |
methods_return_instance(Transaction, trans_dict)
|
|
|
c17846b |
methods_return_instance_lists(
|
|
|
c17846b |
Transaction, { 'GetSplitList': Split,
|
|
|
c17846b |
})
|
|
|
c17846b |
Transaction.decorate_functions(
|
|
|
c17846b |
decorate_monetary_list_returning_function, 'GetImbalance')
|
|
|
c17846b |
|
|
|
c17846b |
# Split
|
|
|
c17846b |
Split.add_methods_with_prefix('xaccSplit')
|
|
|
c17846b |
Split.add_method('gncSplitGetGUID', 'GetGUID');
|
|
|
c17846b |
|
|
|
c17846b |
split_dict = {
|
|
|
c17846b |
'GetBook': Book,
|
|
|
c17846b |
'GetAccount': Account,
|
|
|
c17846b |
'GetParent': Transaction,
|
|
|
c17846b |
'Lookup': Split,
|
|
|
c17846b |
'GetOtherSplit': Split,
|
|
|
c17846b |
'GetAmount': GncNumeric,
|
|
|
c17846b |
'GetValue': GncNumeric,
|
|
|
c17846b |
'GetSharePrice': GncNumeric,
|
|
|
c17846b |
'ConvertAmount': GncNumeric,
|
|
|
c17846b |
'GetBaseValue': GncNumeric,
|
|
|
c17846b |
'GetBalance': GncNumeric,
|
|
|
c17846b |
'GetClearedBalance': GncNumeric,
|
|
|
c17846b |
'GetReconciledBalance': GncNumeric,
|
|
|
c17846b |
'VoidFormerAmount': GncNumeric,
|
|
|
c17846b |
'VoidFormerValue': GncNumeric,
|
|
|
c17846b |
'GetGUID': GUID
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(Split, split_dict)
|
|
|
c17846b |
|
|
|
c17846b |
Split.account = property( Split.GetAccount, Split.SetAccount )
|
|
|
c17846b |
Split.parent = property( Split.GetParent, Split.SetParent )
|
|
|
c17846b |
|
|
|
c17846b |
# Account
|
|
|
c17846b |
Account.add_methods_with_prefix('xaccAccount')
|
|
|
c17846b |
Account.add_methods_with_prefix('gnc_account_')
|
|
|
c17846b |
Account.add_method('gncAccountGetGUID', 'GetGUID');
|
|
|
c17846b |
|
|
|
c17846b |
account_dict = {
|
|
|
c17846b |
'get_book' : Book,
|
|
|
c17846b |
'Lookup' : Account,
|
|
|
c17846b |
'get_parent' : Account,
|
|
|
c17846b |
'get_root' : Account,
|
|
|
c17846b |
'nth_child' : Account,
|
|
|
c17846b |
'lookup_by_code' : Account,
|
|
|
c17846b |
'lookup_by_name' : Account,
|
|
|
c17846b |
'lookup_by_full_name' : Account,
|
|
|
c17846b |
'FindTransByDesc' : Transaction,
|
|
|
c17846b |
'FindSplitByDesc' : Split,
|
|
|
c17846b |
'GetBalance' : GncNumeric,
|
|
|
c17846b |
'GetClearedBalance' : GncNumeric,
|
|
|
c17846b |
'GetReconciledBalance' : GncNumeric,
|
|
|
c17846b |
'GetPresentBalance' : GncNumeric,
|
|
|
c17846b |
'GetProjectedMinimumBalance' : GncNumeric,
|
|
|
c17846b |
'GetBalanceAsOfDate' : GncNumeric,
|
|
|
c17846b |
'ConvertBalanceToCurrency' : GncNumeric,
|
|
|
c17846b |
'ConvertBalanceToCurrencyAsOfDate' : GncNumeric,
|
|
|
c17846b |
'GetBalanceInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetClearedBalanceInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetReconciledBalanceInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetPresentBalanceInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetProjectedMinimumBalanceInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetBalanceAsOfDateInCurrency' : GncNumeric,
|
|
|
c17846b |
'GetBalanceChangeForPeriod' : GncNumeric,
|
|
|
c17846b |
'GetCommodity' : GncCommodity,
|
|
|
c17846b |
'GetGUID': GUID
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(Account, account_dict)
|
|
|
c17846b |
methods_return_instance_lists(
|
|
|
c17846b |
Account, { 'GetSplitList': Split,
|
|
|
c17846b |
'get_children': Account,
|
|
|
c17846b |
'get_children_sorted': Account,
|
|
|
c17846b |
'get_descendants': Account,
|
|
|
c17846b |
'get_descendants_sorted': Account
|
|
|
c17846b |
})
|
|
|
c17846b |
Account.name = property( Account.GetName, Account.SetName )
|
|
|
c17846b |
|
|
|
c17846b |
#GUID
|
|
|
c17846b |
GUID.add_methods_with_prefix('guid_')
|
|
|
c17846b |
GUID.add_method('xaccAccountLookup', 'AccountLookup')
|
|
|
c17846b |
GUID.add_method('xaccTransLookup', 'TransLookup')
|
|
|
c17846b |
GUID.add_method('xaccSplitLookup', 'SplitLookup')
|
|
|
c17846b |
|
|
|
c17846b |
## define addition methods for GUID object - do we need these
|
|
|
c17846b |
GUID.add_method('guid_to_string', 'to_string')
|
|
|
c17846b |
#GUID.add_method('string_to_guid', 'string_to_guid')
|
|
|
c17846b |
|
|
|
c17846b |
guid_dict = {
|
|
|
c17846b |
'copy' : GUID,
|
|
|
c17846b |
'TransLookup': Transaction,
|
|
|
c17846b |
'AccountLookup': Account,
|
|
|
c17846b |
'SplitLookup': Split
|
|
|
c17846b |
}
|
|
|
c17846b |
methods_return_instance(GUID, guid_dict)
|
|
|
c17846b |
|
|
|
c17846b |
#GUIDString
|
|
|
c17846b |
class GUIDString(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
GUIDString.add_constructor_and_methods_with_prefix('string_', 'to_guid')
|
|
|
c17846b |
|
|
|
c17846b |
#Query
|
|
|
c17846b |
from gnucash_core_c import \
|
|
|
c17846b |
QOF_QUERY_AND, \
|
|
|
c17846b |
QOF_QUERY_OR, \
|
|
|
c17846b |
QOF_QUERY_NAND, \
|
|
|
c17846b |
QOF_QUERY_NOR, \
|
|
|
c17846b |
QOF_QUERY_XOR
|
|
|
c17846b |
|
|
|
c17846b |
from gnucash_core_c import \
|
|
|
c17846b |
QOF_STRING_MATCH_NORMAL, \
|
|
|
c17846b |
QOF_STRING_MATCH_CASEINSENSITIVE
|
|
|
c17846b |
|
|
|
c17846b |
from gnucash_core_c import \
|
|
|
c17846b |
QOF_COMPARE_LT, \
|
|
|
c17846b |
QOF_COMPARE_LTE, \
|
|
|
c17846b |
QOF_COMPARE_EQUAL, \
|
|
|
c17846b |
QOF_COMPARE_GT, \
|
|
|
c17846b |
QOF_COMPARE_GTE, \
|
|
|
c17846b |
QOF_COMPARE_NEQ
|
|
|
c17846b |
|
|
|
c17846b |
from gnucash_core_c import \
|
|
|
c17846b |
INVOICE_TYPE
|
|
|
c17846b |
|
|
|
c17846b |
from gnucash_core_c import \
|
|
|
c17846b |
INVOICE_IS_PAID
|
|
|
c17846b |
|
|
|
c17846b |
class Query(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
Query.add_constructor_and_methods_with_prefix('qof_query_', 'create')
|
|
|
c17846b |
|
|
|
c17846b |
Query.add_method('qof_query_set_book', 'set_book')
|
|
|
c17846b |
Query.add_method('qof_query_search_for', 'search_for')
|
|
|
c17846b |
Query.add_method('qof_query_run', 'run')
|
|
|
c17846b |
Query.add_method('qof_query_add_term', 'add_term')
|
|
|
c17846b |
Query.add_method('qof_query_add_boolean_match', 'add_boolean_match')
|
|
|
c17846b |
Query.add_method('qof_query_destroy', 'destroy')
|
|
|
c17846b |
|
|
|
c17846b |
class QueryStringPredicate(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
QueryStringPredicate.add_constructor_and_methods_with_prefix('qof_query_', 'string_predicate')
|
|
|
c17846b |
|
|
|
c17846b |
class QueryBooleanPredicate(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
QueryBooleanPredicate.add_constructor_and_methods_with_prefix('qof_query_', 'boolean_predicate')
|
|
|
c17846b |
|
|
|
c17846b |
class QueryInt32Predicate(GnuCashCoreClass):
|
|
|
c17846b |
pass
|
|
|
c17846b |
|
|
|
c17846b |
QueryInt32Predicate.add_constructor_and_methods_with_prefix('qof_query_', 'int32_predicate')
|