#!/usr/bin/env python3 # -*- coding: utf-8 -*- ##@file # @brief exports an invoice from gnucash using a template file, see \ref py_invoice_export # @ingroup python_bindings_examples # @author Christoph Holtermann (c.holtermann (at) gmx.de) # @date 2014-2018 # # @details # Input is a template file that will be filled with information from # gnucash Invoices. Jinja2 templating engine ist used. Templates can # be Latex, Html or anything. # # Example templates for german invoices: # - Invoice.tex.tmpl # - Invoice_2.tex.tmpl # # This is a sequel to latex_invoices.py that exported to a lco file # to be imported into a LaTeX letter. # The approach used here is not as dependent on external files and # more modular as it allows to use arbitrary templates # # Doxygen docs: # - https://code.gnucash.org/docs/MAINT or MASTER # - see page \ref py_invoice_export # # Questions / Issues: # - How much logic in the template, how much preprocessing in this file ? # - Internationalization - currencies, formatting of numbers # - Providing data of gnucash owner try: import locale import os import sys import getopt import gnucash import str_methods import jinja2 from gncinvoicefkt import * except ImportError as import_error: print("Problem importing modules.") print(import_error) sys.exit(2) class Usage(Exception): def __init__(self, msg): self.msg = msg def main(argv=None): if argv is None: argv = sys.argv try: # default values prog_name = argv[0] ignore_lock = True filename_template = None filename_output = None no_output = False list_invoices = False invoice_number = None invoice_id = None filename_from_invoice = False output_path = None with_ipshell = False try: opts, args = getopt.getopt(argv[1:], "fhliI:t:o:OP:", ["help"]) except getopt.error as msg: raise Usage(msg) for opt in opts: if opt[0] in ["-f"]: print("ignoring lock") ignore_lock = True if opt[0] in ["-h","--help"]: raise Usage("Help:") if opt[0] in ["-I"]: invoice_id = opt[1] print ("using invoice ID '" + str(invoice_id) + "'.") if opt[0] in ["-i"]: print ("Using ipshell") with_ipshell = True if opt[0] in ["-o"]: filename_output = opt[1] print("using output file", filename_output) if opt[0] in ["-O"]: if filename_output: print ("given output filename will be overwritten,") print ("creating output filename from Invoice data.") filename_from_invoice = True if opt[0] in ["-t"]: filename_template = opt[1] print("using template file", filename_template) if opt[0] in ["-l"]: list_invoices = True print("listing invoices") if opt[0] in ["-P"]: output_path = opt[1] print ("output path is", output_path + ".") # Check for correct input if len(args)>1: print("opts:",opts,"args:",args) raise Usage("Only one input possible !") if len(args)==0: raise Usage("No input given !") input_url = args[0] # Check for correct template if not filename_template: no_output = True if not list_invoices: raise Usage("No template given !") # Check for output file if not (filename_output or filename_from_invoice): if filename_template: filename_output = filename_template + ".out" print("no output filename given, will be:", filename_output) except Usage as err: if err.msg == "Help:": retcode=0 else: print("Error:", err.msg, file=sys.stderr) print("for help use --help", file=sys.stderr) retcode=2 print() print("Usage:") print() print("Invoke with",prog_name,"gnucash_url.") print("where input is") print(" filename") print("or file://filename") print("or mysql://user:password@host/databasename") print() print("-f force open = ignore lock") print("-l list all invoices") print("-h or --help for this help") print("-I ID use invoice ID") print("-t filename use filename as template file") print("-o filename use filename as output file") print("-O create output filename by date, owner and invoice number") print("-P path path for output file. Overwrites path in -o option") return retcode # Try to open the given input try: print("Opening", input_url, ".") session = gnucash.Session(input_url, ignore_lock=ignore_lock) except Exception as exception: print("Problem opening input.") print(exception) return 2 book = session.book root_account = book.get_root_account() comm_table = book.get_table() EUR = comm_table.lookup("CURRENCY", "EUR") invoice_list = get_all_invoices(book) if list_invoices: for number,invoice in enumerate(invoice_list): print(str(number)+")") print(invoice) if not (no_output): if invoice_id: invoice = book.InvoiceLookupByID(invoice_id) if not invoice: print("ID not found.") return 2 if invoice_number: invoice = invoice_list[invoice_number] print("Using the following invoice:") print(invoice) path_template = os.path.dirname(filename_template) filename_template_basename = os.path.basename(filename_template) loader = jinja2.FileSystemLoader(path_template) env = jinja2.Environment(loader=loader) template = env.get_template(filename_template_basename) #company = gnucash_business.Company(book.instance) output = template.render(invoice=invoice, locale=locale) #, company=company) if filename_from_invoice: filename_date = str(invoice.GetDatePosted()) # something like 2014-11-01 filename_owner_name = str(invoice.GetOwner().GetName()) filename_invoice_id = str(invoice.GetID()) filename_output = filename_date + "_" + filename_owner_name + "_" + filename_invoice_id + ".tex" if output_path: filename_output = os.path.join(output_path, os.path.basename(filename_output)) print ("Writing output", filename_output, ".") with open(filename_output, 'w') as f: f.write(output) if with_ipshell: import IPython IPython.embed() if __name__ == "__main__": sys.exit(main())