Beispiel #1
0
def main():

    if len(argv) < 3:
        print 'not enough parameters'
        print 'usage: new_book_with_opening_balances.py {source_book_url} {destination_book_url}'
        print 'examples:'
        print "gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'sqlite3:///home/username/new_test.gnucash'"
        print "gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'xml:///crypthome/username/finances/new_test.gnucash'"
        return

    #have everything in a try block to unable us to release our hold on stuff to the extent possible
    try:
        original_book_session = Session(argv[1], is_new=False)
        new_book_session = Session(argv[2], is_new=True)
        new_book = new_book_session.get_book()
        new_book_root = new_book.get_root_account()

        commodtable = new_book.get_table()
        # we discovered that if we didn't have this save early on, there would
        # be trouble later
        new_book_session.save()

        opening_balance_per_currency = {}
        recursivly_build_account_tree(
            original_book_session.get_book().get_root_account(), new_book_root,
            new_book, commodtable, opening_balance_per_currency,
            ACCOUNT_TYPES_TO_OPEN)

        (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE
        if (namespace, mnemonic) in opening_balance_per_currency:
            opening_trans, opening_amount = opening_balance_per_currency[(
                namespace, mnemonic)]
            simple_opening_name_used = create_opening_balance_transaction(
                commodtable, namespace, mnemonic, new_book_root, new_book,
                opening_trans, opening_amount, False)
            del opening_balance_per_currency[
                PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE]
        else:
            simple_opening_name_used = False

        for (namespace, mnemonic), (opening_trans, opening_amount) in \
                opening_balance_per_currency.iteritems() :
            simple_opening_name_used = create_opening_balance_transaction(
                commodtable, namespace, mnemonic, new_book_root, new_book,
                opening_trans, opening_amount, simple_opening_name_used)

        new_book_session.save()
        new_book_session.end()
        original_book_session.end()
    except:
        if "original_book_session" in locals():
            original_book_session.end()

        if "new_book_session" in locals():
            new_book_session.end()

        raise
def main():
    original_book_session = Session(argv[1], False)
    new_book_session = Session(argv[2], True)
    new_book = new_book_session.get_book()
    new_book_root = new_book.get_root_account()

    commodtable = new_book.get_table()
    # we discovered that if we didn't have this save early on, there would
    # be trouble later
    new_book_session.save()

    opening_balance_per_currency = {}
    recursivly_build_account_tree(
        original_book_session.get_book().get_root_account(),
        new_book_root,
        new_book,
        commodtable,
        opening_balance_per_currency,
        ACCOUNT_TYPES_TO_OPEN
        )

    (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE
    if (namespace, mnemonic) in opening_balance_per_currency:
        opening_trans, opening_amount = opening_balance_per_currency[
            (namespace, mnemonic)]
        simple_opening_name_used = create_opening_balance_transaction(
            commodtable, namespace, mnemonic,
            new_book_root, new_book,
            opening_trans, opening_amount,
            False )
        del opening_balance_per_currency[
            PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE]
    else:
        simple_opening_name_used = False

    for (namespace, mnemonic), (opening_trans, opening_amount) in \
            opening_balance_per_currency.iteritems() :
        simple_opening_name_used = create_opening_balance_transaction(
            commodtable, namespace, mnemonic,
            new_book_root, new_book,
            opening_trans, opening_amount,
            simple_opening_name_used )

    new_book_session.save()
    new_book_session.end()
    original_book_session.end()
Beispiel #3
0
class CommoditySession(TestCase):
    def setUp(self):
        self.ses = Session()
        self.book = self.ses.get_book()
        self.table = self.book.get_table()

    def tearDown(self):
        self.ses.end()
Beispiel #4
0
class TestSession(TestCase):
    def test_create_empty_session(self):
        self.ses = Session()

    def test_session_deprecated_arguments(self):
        """use deprecated arguments ignore_lock, is_new, force_new"""
        self.ses = Session(ignore_lock=False, is_new=True, force_new=False)

    def test_session_mode(self):
        """use mode argument"""
        self.ses = Session(mode=SessionOpenMode.SESSION_NORMAL_OPEN)

    def test_session_with_new_file(self):
        """create Session with new xml file"""
        from tempfile import TemporaryDirectory
        from urllib.parse import urlunparse
        with TemporaryDirectory() as tempdir:
            uri = urlunparse(("xml", tempdir, "tempfile", "", "", ""))
            with Session(uri, SessionOpenMode.SESSION_NEW_STORE) as ses:
                pass

            # try to open nonexistent file without NEW mode - should raise Exception
            uri = urlunparse(("xml", tempdir, "tempfile2", "", "", ""))
            with Session() as ses:
                with self.assertRaises(GnuCashBackendException):
                    ses.begin(uri, mode=SessionOpenMode.SESSION_NORMAL_OPEN)

            # try to open nonexistent file without NEW mode - should raise Exception
            # use deprecated arg is_new
            uri = urlunparse(("xml", tempdir, "tempfile2", "", "", ""))
            with Session() as ses:
                with self.assertRaises(GnuCashBackendException):
                    ses.begin(uri, is_new=False)

            uri = urlunparse(("xml", tempdir, "tempfile3", "", "", ""))
            with Session() as ses:
                ses.begin(uri, mode=SessionOpenMode.SESSION_NEW_STORE)

            # test using deprecated args
            uri = urlunparse(("xml", tempdir, "tempfile4", "", "", ""))
            with Session() as ses:
                ses.begin(uri, is_new=True)

    def test_app_utils_get_current_session(self):
        from gnucash import _sw_app_utils
        self.ses_instance = _sw_app_utils.gnc_get_current_session()
        self.ses = Session(instance=self.ses_instance)
        self.assertIsInstance(obj=self.ses, cls=Session)

    def test_get_book_from_current_session(self):
        from gnucash import _sw_app_utils
        from gnucash import Book
        self.ses_instance = _sw_app_utils.gnc_get_current_session()
        self.ses = Session(instance=self.ses_instance)
        self.book = self.ses.get_book()
        self.assertIsInstance(obj=self.book, cls=Book)
def main():
    original_book_session = Session(argv[1], is_new=False)
    new_book_session = Session(argv[2], in_new=True)
    new_book = new_book_session.get_book()
    new_book_root = new_book.get_root_account()

    commodtable = new_book.get_table()
    # we discovered that if we didn't have this save early on, there would
    # be trouble later
    new_book_session.save()

    opening_balance_per_currency = {}
    recursivly_build_account_tree(
        original_book_session.get_book().get_root_account(), new_book_root,
        new_book, commodtable, opening_balance_per_currency,
        ACCOUNT_TYPES_TO_OPEN)

    (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE
    if (namespace, mnemonic) in opening_balance_per_currency:
        opening_trans, opening_amount = opening_balance_per_currency[(
            namespace, mnemonic)]
        simple_opening_name_used = create_opening_balance_transaction(
            commodtable, namespace, mnemonic, new_book_root, new_book,
            opening_trans, opening_amount, False)
        del opening_balance_per_currency[
            PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE]
    else:
        simple_opening_name_used = False

    for (namespace, mnemonic), (opening_trans, opening_amount) in \
            opening_balance_per_currency.iteritems() :
        simple_opening_name_used = create_opening_balance_transaction(
            commodtable, namespace, mnemonic, new_book_root, new_book,
            opening_trans, opening_amount, simple_opening_name_used)

    new_book_session.save()
    new_book_session.end()
    original_book_session.end()
Beispiel #6
0
class TestSession(TestCase):
    def test_create_empty_session(self):
        self.ses = Session()

    def test_app_utils_get_current_session(self):
        from gnucash import _sw_app_utils
        self.ses_instance = _sw_app_utils.gnc_get_current_session()
        self.ses = Session(instance=self.ses_instance)
        self.assertIsInstance(obj=self.ses, cls=Session)

    def test_get_book_from_current_session(self):
        from gnucash import _sw_app_utils
        from gnucash import Book
        self.ses_instance = _sw_app_utils.gnc_get_current_session()
        self.ses = Session(instance=self.ses_instance)
        self.book = self.ses.get_book()
        self.assertIsInstance(obj=self.book, cls=Book)
Beispiel #7
0
#!/usr/bin/env python

##  @file
#   @brief Simple example for a book
#   @ingroup python_bindings_examples

import sys
from gnucash import Session

# We need to tell GnuCash the data format to create the new file as (xml://)
uri = "xml:///tmp/simple_book.gnucash"

print "uri:", uri
ses = Session(uri, is_new=True)
book = ses.get_book()

# Call some methods that produce output to show that Book works
book.get_root_account().SetDescription("hello, book")
print "Book is saved:", not book.not_saved()

print "saving..."
ses.save()

print "Book is saved:", not book.not_saved()
ses.end()
Beispiel #8
0
class BookSession( TestCase ):
    def setUp(self):
        self.ses = Session()
        self.book = self.ses.get_book()
Beispiel #9
0
class GnuCash():
    """ 

    In "/home/user/.odontuxrc" lies the odontux configuration, that tells
    about gnucash.
    
    In order that several dentists may use odontux together, the 
    "profissionnalaccounting_url", which specify the gnucash account place is 
    store in the user (ROLE_DENTIST) session :
    "models.users.OdontuxUser.profissionnalaccounting_url".
    
    The inside of gnucash needs at least :
        * assets  ( all of the dentist assets )
            * receivables  ( what the patient owes to the dentist )
            * dentalfund  ( what the patient paid to the dentist, but ain't 
                            usable right away ; needs to pass by the bank )
        * incomes  ( all of the dentist incomes )
            * dentalincomes  ( incomes coming from dental practice activity )

    While coding the assistant/secretary salary, the buying of dental supplies
    and all, we'll add "outcomes", liabilities...

    See commands/compta.py for :
        * assets
            * dentalfund
            * check
            * cash
            * card
            * transfer
            * paypal
    """
    def __init__(self, patient_id, dentist_id):
        self.parser = ConfigParser.ConfigParser()
        home = os.path.expanduser("~")
        self.parser.read(os.path.join(home, ".odontuxrc"))
        self.dentist = ( meta.session.query(users.OdontuxUser)
            .filter(users.OdontuxUser.id == dentist_id)
            .one()
        )
        profissionnalaccounting_url = self.dentist.gnucash_url.encode("utf_8")
        if profissionnalaccounting_url[-3:] == "xml":
            self.gnucashtype = "xml"
        elif "postgresql" in profissionnalaccounting_url.split("://"):
            self.gnucashtype = "postgresql"
        else:
            self.gnucashtype = "xml"

        assets = constants.ASSETS
        receivables = constants.RECEIVABLES
        dentalfund = constants.DENTAL_FUND

        incomes = constants.INCOMES
        dentalincomes = constants.DENTAL_INCOMES

        # Precise on which patient we'll work on
        self.patient_id = patient_id
        self.patient = meta.session.query(administration.Patient).filter(
                                administration.Patient.id == patient_id).one()

        # Set the gnucash patient_id
        self.gcpatient_id = "pat_" + str(self.patient_id)
        # Set up the Book for accounting
        self.gcsession = GCSession(profissionnalaccounting_url, True)
        self.book = self.gcsession.get_book()

        # set the currency we'll use
        currency = constants.GNUCASH_CURRENCY
        commod_tab = self.book.get_table()
        self.currency = commod_tab.lookup("CURRENCY", currency)

        # Set up the root on accounting book
        self.root = self.book.get_root_account()
        # Assets
        self.assets = self.root.lookup_by_name(assets)
        # What the patient owes to dental office
        self.receivables = self.assets.lookup_by_name(receivables)
        if not self.receivables.lookup_by_name(self.gcpatient_id):
            self.patient_receivables = Account(self.book)
            self.receivables.append_child(self.patient_receivables)
            self.patient_receivables.SetName(self.gcpatient_id)
            self.patient_receivables.SetType(gnc_core_c.ACCT_TYPE_RECEIVABLE)
            self.patient_receivables.SetCommodity(self.currency)
        else:
            self.patient_receivables = self.receivables.lookup_by_name(
                                                            self.gcpatient_id)
        # What the patient paid to dental office, but not usable
        # because it needs to pass by the bank.
        # the detail of dental fund is build in commands/compta.py
        # while getting the paymenttype.
        self.dentalfund = self.assets.lookup_by_name(dentalfund)
        # Incomes
        self.incomes = self.root.lookup_by_name(incomes)
        self.dentalincomes = self.incomes.lookup_by_name(dentalincomes)

    def gnc_numeric_from_decimal(self, decimal_value):
        sign, digits, exponent = decimal_value.as_tuple()

        # convert decimal digits to a fractional numerator
        # equivlent to
        # numerator = int(''.join(digits))
        # but without the wated conversion to string and back,
        # this is probably the same algorithm int() uses
        numerator = 0
        TEN = int(Decimal(0).radix()) # this is always 10
        numerator_place_value = 1
        # add each digit to the final value multiplied by the place value
        # from least significant to most sigificant
        for i in xrange(len(digits)-1,-1,-1):
            numerator += digits[i] * numerator_place_value
            numerator_place_value *= TEN

        if decimal_value.is_signed():
            numerator = -numerator

        # if the exponent is negative, we use it to set the denominator
        if exponent < 0 :
            denominator = TEN ** (-exponent)
        # if the exponent isn't negative, we bump up the numerator
        # and set the denominator to 1
        else:
            numerator *= TEN ** exponent
            denominator = 1

        return GncNumeric(numerator, denominator)
Beispiel #10
0
#!/usr/bin/env python

##  @file
#   @brief Simple example for a book
#   @ingroup python_bindings_examples

import sys
from gnucash import Session

# We need to tell GnuCash the data format to create the new file as (xml://)
uri = "xml:///tmp/simple_book.gnucash"

print("uri:", uri)
ses = Session(uri, is_new=True)
book = ses.get_book()

#Call some methods that produce output to show that Book works
book.get_root_account().SetDescription("hello, book")
print("Book is saved:", not book.session_not_saved())

print("saving...")
ses.save()

print("Book is saved:", not book.session_not_saved())
ses.end()
Beispiel #11
0
class BookSession(TestCase):
    def setUp(self):
        self.ses = Session()
        self.book = self.ses.get_book()
Beispiel #12
0
class BookSession(TestCase):
    def setUp(self):
        self.ses = Session()
        self.book = self.ses.get_book()
        table = self.book.get_table()
        self.currency = table.lookup('CURRENCY', 'EUR')
def main():

    if len(argv) < 3:
        print('not enough parameters')
        print('usage: new_book_with_opening_balances.py {source_book_url} {destination_book_url}')
        print('examples:')
        print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'sqlite3:///home/username/new_test.gnucash'")
        print("gnucash-env python new_book_with_opening_balances.py '/home/username/test.gnucash' 'xml:///crypthome/username/finances/new_test.gnucash'")
        return

    #have everything in a try block to unable us to release our hold on stuff to the extent possible
    try:
        original_book_session = Session(argv[1], is_new=False)
        new_book_session = Session(argv[2], is_new=True)
        new_book = new_book_session.get_book()
        new_book_root = new_book.get_root_account()

        commodtable = new_book.get_table()
        # we discovered that if we didn't have this save early on, there would
        # be trouble later
        new_book_session.save()

        opening_balance_per_currency = {}
        recursivly_build_account_tree(
            original_book_session.get_book().get_root_account(),
            new_book_root,
            new_book,
            commodtable,
            opening_balance_per_currency,
            ACCOUNT_TYPES_TO_OPEN
            )

        (namespace, mnemonic) = PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE
        if (namespace, mnemonic) in opening_balance_per_currency:
            opening_trans, opening_amount = opening_balance_per_currency[
                (namespace, mnemonic)]
            simple_opening_name_used = create_opening_balance_transaction(
                commodtable, namespace, mnemonic,
                new_book_root, new_book,
                opening_trans, opening_amount,
                False )
            del opening_balance_per_currency[
                PREFERED_CURRENCY_FOR_SIMPLE_OPENING_BALANCE]
        else:
            simple_opening_name_used = False

        for (namespace, mnemonic), (opening_trans, opening_amount) in \
                opening_balance_per_currency.iteritems() :
            simple_opening_name_used = create_opening_balance_transaction(
                commodtable, namespace, mnemonic,
                new_book_root, new_book,
                opening_trans, opening_amount,
                simple_opening_name_used )

        new_book_session.save()
        new_book_session.end()
        original_book_session.end()
    except:
        if "original_book_session" in locals():
            original_book_session.end()
 
        if "new_book_session" in locals():
            new_book_session.end()

        raise
Beispiel #14
0
class BookSession( TestCase ):
    def setUp(self):
        self.ses = Session()
        self.book = self.ses.get_book()
        self.table = self.book.get_table()
        self.currency = self.table.lookup('CURRENCY', 'EUR')
Beispiel #15
0
def invoice_pdf(gnc_file, invoice_number, pdf_file):
    uri = "xml://{0}".format(os.path.abspath(gnc_file))
    ses = Session(uri, is_new=False)
    try:
        book = ses.get_book()
        commod_table = book.get_table()
        USD = commod_table.lookup("CURRENCY", "USD")

        invoice = book.InvoiceLookupByID(invoice_number)
        client = invoice.GetOwner()
        client_addr = client.GetAddr()

        pdf = Canvas(pdf_file, bottomup=False, pagesize=letter)

        pdf.setFont("Helvetica-Bold", 24)
        pdf.setFillColor(colors.lightgrey)
        pdf.drawCentredString(letter[0] / 2, inch * 0.75, "INVOICE")

        font_height = 10
        pdf.setFont("Helvetica", font_height)
        pdf.setFillColor(colors.black)
        from_header = pdf.beginText(inch * 0.75, inch * 0.75)
        to_header = pdf.beginText(inch * 0.75, inch * 2.25)

        header_file = "{0}/.gnc-invoice-header".format(os.environ["HOME"])
        with open(header_file, "r") as f:
            for line in f:
                from_header.textLine(line.strip())

        to_fields = [
            client.GetName(),
            client_addr.GetName(),
            client_addr.GetAddr1(),
            client_addr.GetAddr2(),
            client_addr.GetAddr3(),
            client_addr.GetAddr4(),
        ]
        for field in to_fields:
            if field:
                to_header.textLine(field)

        pdf.drawText(from_header)
        pdf.drawText(to_header)

        #
        # This is the summary table / box in the mid-upper right.
        #
        table_data = (
            ("Invoice #", invoice.GetID()),
            ("Date", invoice.GetDatePosted().strftime("%Y-%m-%d")),
            ("Amount Due (USD)", "${0:0.2f}".format(invoice.GetTotal().to_double())),
        )
        x = inch * 4.5
        y = (inch * 2.25) - font_height
        width = inch * 3
        height = inch * 0.75
        num_rows = 3
        num_cols = 2
        col_width = width / num_cols
        row_height = height / num_rows
        for row in range(num_rows):
            for col in range(num_cols):
                rect_x = x + (col_width * col)
                rect_y = y + (row_height * row)

                pdf.setFillColor(colors.darkgrey)
                pdf.rect(rect_x, rect_y, col_width, row_height, stroke=True, fill=(col == 0))

                pdf.setFillColor(colors.black)
                if col:
                    pdf.drawAlignedString(rect_x + col_width, rect_y + font_height + 2, table_data[row][col], "%")
                else:
                    pdf.drawString(rect_x + 5, rect_y + font_height + 2, table_data[row][col])

        #
        # This is the detail table in the lower half.
        #
        table_data = [("Date", "Description", "Hours", "Rate ($)", "Line Total")]
        for entry in [Entry(instance=e) for e in invoice.GetEntries()]:
            qty = GncNumeric(instance=entry.GetQuantity()).to_double()
            rate = GncNumeric(instance=entry.GetInvPrice()).to_double()
            line_total = GncNumeric(instance=entry.ReturnValue(True)).to_double()
            row = [
                entry.GetDate().strftime("%Y-%m-%d"),
                entry.GetDescription(),
                "{0:0.2f}".format(qty),
                "{0:0.2f}".format(rate),
                "{0:0.2f}".format(line_total),
            ]
            table_data.append(row)

        x = inch * 0.75
        y = inch * 4.0

        # Let column 1 consume the rest of the space.
        width = inch * 6.75
        widths = [80, 0, 50, 50, 80]
        widths[1] = width - sum(widths)

        height = font_height + 2 + 2  # 2pt spacing above and below.
        num_rows = 1
        num_cols = 5
        col_width = width / num_cols
        row_height = height / num_rows
        rect_x = x
        rect_y = y
        for row_num, row in enumerate(table_data):
            rect_x = x
            for col_num, col in enumerate(row):
                col_width = widths[col_num]
                rect_y = y + (row_height * row_num)

                pdf.setFillColor(colors.darkgrey)
                pdf.rect(rect_x, rect_y, col_width, row_height, stroke=True, fill=(row_num == 0))

                pdf.setFillColor(colors.black)
                if col_num > 1:
                    pdf.drawAlignedString(rect_x + col_width, rect_y + font_height + 2, col, "%")
                else:
                    pdf.drawString(rect_x + 5, rect_y + font_height + 2, col)

                rect_x = rect_x + col_width

        # Draw the outer detail box.
        detail_height = inch * 5.0
        pdf.setFillColor(colors.black)
        pdf.rect(x, y, width, detail_height, stroke=True, fill=False)

        # Total box above payment terms.
        totalbox_text_vpad = 6
        totalbox_text_height = font_height + (totalbox_text_vpad * 2)
        totalbox_rows = 4
        totalbox_height = totalbox_text_height * (totalbox_rows + 1)
        totalbox_y = y + detail_height - totalbox_height
        pdf.rect(x, totalbox_y, width, totalbox_height, stroke=True, fill=False)

        # Total, balance due, etc boxes inside total box.
        total_amount = invoice.GetTotal().to_double()
        totalbox_data = [
            ("Subtotal:", "${0:0.2f}".format(total_amount)),
            ("Total:", "${0:0.2f}".format(total_amount)),
            ("Amount Paid:", "$0.00"),
            ("Balance Due:", "${0:0.2f}".format(total_amount)),
        ]
        balance_height = row_height
        balance_y = totalbox_y + totalbox_height - totalbox_text_height * 2
        for n in xrange(totalbox_rows):
            thisbox_y = totalbox_y + totalbox_text_height * n
            thisbox_text_y = thisbox_y + totalbox_text_height - totalbox_text_vpad
            pdf.setFillColor(colors.lightgrey)
            pdf.rect(
                x + width / 2, thisbox_y, width / 2, totalbox_text_height, stroke=True, fill=(n == (totalbox_rows - 1))
            )
            pdf.setFillColor(colors.black)
            pdf.drawAlignedString(x + width / 2 + (inch * 1.5), thisbox_text_y, totalbox_data[n][0], ":")
            pdf.drawAlignedString(x + width - 20, thisbox_text_y, totalbox_data[n][1], ".")

        # Payment terms in the bottom of the detail box.
        pdf.setFillColor(colors.black)
        pdf.rect(x, y + detail_height - totalbox_text_height, width, totalbox_text_height, stroke=True, fill=False)

        if invoice.GetTerms() and invoice.GetTerms().GetDueDays():
            due = "Payment due within %d days of invoice date." % (invoice.GetTerms().GetDueDays())
            pdf.setFillColor(colors.black)
            pdf.drawCentredString(x + (width / 2), y + detail_height - totalbox_text_vpad, due)

        pdf.showPage()
        pdf.save()
    finally:
        ses.end()
class TransactionListing(object):
    """
    Extracts all transactions from a specific account in a GnuCash file
    and returns them as a list"""

    def load(self, filename):
        """
        Load a GnuCash file, e.g. xml:///tmp/test.gnucash
        """
        self.session = Session(filename, is_new=False, ignore_lock=True)
        self.book = self.session.get_book()

    def format_guid(self, gnc_guid):
        as_string = gnc_guid.to_string()
        uuid = UUID(as_string)
        return str(uuid)

    def get_all_transactions(self, account, positive_only=False):
        """
        Yields a list of all transactions as a tuple.

        @param str account
        @return tuple(unix time stamp, memo, value as string)
        """
        account = self.get_account(account)
        transactions = []
        split_list = account.GetSplitList()

        def get_transaction_str_amount(transaction):
            return numeric_to_doublestr(
                    transaction.GetAccountAmount(account))

        # this temporary list is used so that duplicate transactions
        # can be detected (these appear when multiple splits of the
        # same transaction belong to the current account)
        gnc_transactions = []
        known_transactions = set()
        for split in split_list:
            transaction = split.GetParent()
            amount = get_transaction_str_amount(transaction)
            if positive_only and amount[0] == '-':
                continue
            guid = self.format_guid(transaction.GetGUID())
            if guid in known_transactions:
                continue
            known_transactions.add(guid)
            gnc_transactions.append(transaction)

        for transaction in gnc_transactions:
            guid = self.format_guid(transaction.GetGUID())
            date = transaction.GetDate()
            desc = transaction.GetDescription().decode(CHARSET)
            amount = get_transaction_str_amount(transaction)
            if not desc.strip() and not float(amount):
                continue
            yield (
                guid,
                date,
                desc,
                amount)

    def get_account(self, account):
        """
        Looks up an account object by a given navigation string
        (e.g. Aktiva:Foo:Bar)

        @param str account
        @param GnuCash.Account account
        """
        account_path = account.split(':')
        search = self.book.get_root_account()
        found = True
        while found and account_path:
            account_name = account_path.pop(0).lower()
            found = False
            for account in search.get_children():
                if account.name.lower() == account_name:
                    search = account
                    found = True
                    break
        if not found:
            raise RuntimeError("Account not found")
        return account