r21255 - gnucash/trunk/src/optional/python-bindings - Bug #651175 - Script to export invoices to LaTeX
Geert Janssens
gjanssens at code.gnucash.org
Sun Sep 11 10:54:07 EDT 2011
Author: gjanssens
Date: 2011-09-11 10:54:07 -0400 (Sun, 11 Sep 2011)
New Revision: 21255
Trac: http://svn.gnucash.org/trac/changeset/21255
Added:
gnucash/trunk/src/optional/python-bindings/example_scripts/Invoice.tex
gnucash/trunk/src/optional/python-bindings/example_scripts/latex_invoices.py
Modified:
gnucash/trunk/src/optional/python-bindings/Makefile.am
Log:
Bug #651175 - Script to export invoices to LaTeX
Patch by Christoph Holtermann
Modified: gnucash/trunk/src/optional/python-bindings/Makefile.am
===================================================================
--- gnucash/trunk/src/optional/python-bindings/Makefile.am 2011-09-11 14:32:58 UTC (rev 21254)
+++ gnucash/trunk/src/optional/python-bindings/Makefile.am 2011-09-11 14:54:07 UTC (rev 21255)
@@ -86,6 +86,8 @@
EXTRA_DIST = \
$(SWIG_FILES) \
+ example_scripts/Invoice.tex \
+ example_scripts/latex_invoices.py \
example_scripts/simple_book.py \
example_scripts/simple_session.py \
example_scripts/simple_test.py \
Added: gnucash/trunk/src/optional/python-bindings/example_scripts/Invoice.tex
===================================================================
--- gnucash/trunk/src/optional/python-bindings/example_scripts/Invoice.tex (rev 0)
+++ gnucash/trunk/src/optional/python-bindings/example_scripts/Invoice.tex 2011-09-11 14:54:07 UTC (rev 21255)
@@ -0,0 +1,154 @@
+%---------------------------------------------------------------------------
+% Invoice.tex v0.1 by Christoph Holtermann (c.holtermann at gmx.de)
+%
+% modified from
+% scrlttr2.tex v0.3. (c) by Juergen Fenn <juergen.fenn at gmx.de>
+% Template for a letter to be typeset with scrlttr2.cls from KOMA-Script.
+% Latest version of the LaTeX Project Public License is applicable.
+% File may not be modified and redistributed under the same name
+% without the author's prior consent.
+%---------------------------------------------------------------------------
+\documentclass%%
+%---------------------------------------------------------------------------
+ [fontsize=12pt,%% Schriftgroesse
+%---------------------------------------------------------------------------
+% Satzspiegel
+ paper=a4,%% Papierformat
+ enlargefirstpage=off,%% Erste Seite anders
+ pagenumber=headright,%% Seitenzahl oben mittig
+%---------------------------------------------------------------------------
+% Layout
+ headsepline=on,%% Linie unter der Seitenzahl
+ parskip=half,%% Abstand zwischen Absaetzen
+%---------------------------------------------------------------------------
+% Briefkopf und Anschrift
+ fromalign=right,%% Platzierung des Briefkopfs
+ fromphone=on,%% Telefonnummer im Absender
+ fromrule=off,%% Linie im Absender (aftername, afteraddress)
+ fromfax=on,%% Faxnummer
+ fromemail=on,%% Emailadresse
+ fromurl=off,%% Homepage
+ fromlogo=off,%% Firmenlogo
+ addrfield=on,%% Adressfeld fuer Fensterkuverts
+ backaddress=on,%% ...und Absender im Fenster
+ subject=beforeopening,%% Plazierung der Betreffzeile
+ locfield=narrow,%% zusaetzliches Feld fuer Absender
+ foldmarks=on,%% Faltmarken setzen
+ numericaldate=off,%% Datum numerisch ausgeben
+ refline=narrow,%% Geschaeftszeile im Satzspiegel
+%---------------------------------------------------------------------------
+% Formatierung
+ draft=off,%% Entwurfsmodus
+ version=last,
+ data%% data.lco ist die Datei aus der die Rechnungsdaten gelesen werden ( invoice-data to be read from data.lco )
+]{scrlttr2}
+%---------------------------------------------------------------------------
+\usepackage[ngerman]{babel}
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\usepackage{url}
+\usepackage{eurosym}
+\usepackage{rechnung}
+\usepackage{textcomp}
+%---------------------------------------------------------------------------
+% Fonts
+\setkomafont{fromname}{\sffamily \LARGE}
+\setkomafont{fromaddress}{\sffamily}%% statt \small
+\setkomafont{pagenumber}{\sffamily}
+\setkomafont{subject}{\mdseries}
+\setkomafont{backaddress}{\mdseries}
+\usepackage{mathptmx}%% Schrift Times
+%\usepackage{mathpazo}%% Schrift Palatino
+%\setkomafont{fromname}{\LARGE}
+%---------------------------------------------------------------------------
+\begin{document}
+%---------------------------------------------------------------------------
+% Briefstil und Position des Briefkopfs
+\LoadLetterOption{DIN} %% oder: DINmtext, SN, SNleft, KOMAold.
+\makeatletter
+\@setplength{firstheadvpos}{20mm}
+\@setplength{firstheadwidth}{\paperwidth}
+\ifdim \useplength{toaddrhpos}>\z@
+ \@addtoplength[-2]{firstheadwidth}{\useplength{toaddrhpos}}
+\else
+ \@addtoplength[2]{firstheadwidth}{\useplength{toaddrhpos}}
+\fi
+\@setplength{foldmarkhpos}{6.5mm}
+%\setlength{\footskip}{1cm}
+\makeatother
+%---------------------------------------------------------------------------
+% Absender
+\setkomavar{fromname}{fromname}
+\setkomavar{fromaddress}{fromaddress}
+\setkomavar{fromphone}{fromphone}
+\renewcommand{\phonename}{Telefon}
+\setkomavar{fromfax}{fromfax}
+\setkomavar{fromemail}{fromemail}
+\setkomavar{backaddressseparator}{. }
+\setkomavar{signature}{(signature)}
+\setkomavar{frombank}{---NAME --- BANK ACCOUNT --- BANK NUMBER --- BANK NAME ---}
+\setkomavar{location}{\\[8ex]\raggedleft{\footnotesize{\usekomavar{fromaddress}\\
+ Telefon: \usekomavar{fromphone}\\Mobil: mobile-number\\Fax: \usekomavar{fromfax}\\\usekomavar{fromemail}}}}%% Neben dem Adressfenster
+%---------------------------------------------------------------------------
+\firsthead{}
+%---------------------------------------------------------------------------
+% Fußzeile
+\firstfoot{%
+ \parbox[b]{\linewidth}{%
+ \centering\def\\{, }\footnotesize\usekomavar{frombank}%
+ }%
+}%
+%---------------------------------------------------------------------------
+% Geschaeftszeilenfelder
+%\setkomavar{place}{Stadel}
+%\setkomavar{placeseparator}{, den }
+%\setkomavar{date}{\today}
+%\setkomavar{yourmail}{1. 1. 2003}%% 'Ihr Schreiben...'
+%\setkomavar{yourref} {abcdefg}%% 'Ihr Zeichen...'
+%\setkomavar{myref}{}%% Unser Zeichen
+\setkomavar{invoice}{\usekomavar{rechnungsnummer}}%% Rechnungsnummer
+%\setkomavar{phoneseparator}{}
+
+%---------------------------------------------------------------------------
+% Versendungsart
+%\setkomavar{specialmail}{Einschreiben mit R�ckschein}
+%---------------------------------------------------------------------------
+% Anlage neu definieren
+\renewcommand{\enclname}{Anlage}
+\setkomavar{enclseparator}{: }
+%---------------------------------------------------------------------------
+% Seitenstil
+\pagestyle{plain}%% keine Header in der Kopfzeile
+%---------------------------------------------------------------------------
+% Rechnungsoptionen
+\Euro
+%---------------------------------------------------------------------------
+\begin{letter}{\usekomavar{toaddress2}}
+%---------------------------------------------------------------------------
+% Weitere Optionen
+\KOMAoptions{%%
+}
+%---------------------------------------------------------------------------
+%\setkomavar{subject}{Rechnungsnummer \usekomavar{rechnungsnummer}}
+%---------------------------------------------------------------------------
+\opening{Sehr geehrte Damen und Herren,}
+
+Ich erlaube mir, Ihnen folgende Beträge in Rechnung zu stellen:
+
+\begin{Rechnung}[N] %oder [N]
+\Steuersatz{0}{0}
+\usekomavar{entries}
+\end{Rechnung}
+
+Bitte zahlen Sie den Betrag von \Gesamtsumme \, bis zum \usekomavar{date_due} auf mein unten angegebenes Konto.
+
+\closing{Mit bestem Dank und freundlichen Grüßen,}
+%---------------------------------------------------------------------------
+%\ps{PS:}
+%\encl{}
+%\cc{}
+%---------------------------------------------------------------------------
+\end{letter}
+%---------------------------------------------------------------------------
+\end{document}
+%---------------------------------------------------------------------------
Added: gnucash/trunk/src/optional/python-bindings/example_scripts/latex_invoices.py
===================================================================
--- gnucash/trunk/src/optional/python-bindings/example_scripts/latex_invoices.py (rev 0)
+++ gnucash/trunk/src/optional/python-bindings/example_scripts/latex_invoices.py 2011-09-11 14:54:07 UTC (rev 21255)
@@ -0,0 +1,305 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+##@file
+# @ingroup python_bindings_examples
+# @author Christoph Holtermann (c.holtermann (at) gmx.de)
+# @date May 2011
+# @brief Exports an invoice to lco-file for use with LaTeX
+#
+# The output file can be imported into KOMA-Script-letters.
+# This works primarily for germany. Internationalization welcome!
+#
+# Additional files:
+#
+# - Invoice.tex\n
+# Example template file. Should be modified according to personal needs.
+# - rechnung.sty\n
+# style file for invoices.\n
+# This file is not part of the python-bindings!\n
+# For an example where to get it see section credits below.
+#
+# Usage :
+# \code latex_invoice file://testfile \endcode
+# will create file data.lco.
+# \code latex --output-format=pdf Invoice.tex \endcode
+# should run latex on file Invoice.tex and result in Invoice.pdf. Invoice.tex includes data.lco.
+#
+# Additional information :
+#
+# - http://www.uweziegenhagen.de/latex/documents/rechnung/rechnungen.pdf (german)
+#
+# Credits to and ideas from
+#
+# - Main function as proposed by Guido van Rossum
+# at http://www.artima.com/weblogs/viewpost.jsp?thread=4829
+# - Invoice.tex is derived from\n
+# scrlttr2.tex v0.3. (c) by Juergen Fenn <juergen.fenn at gmx.de>\n
+# http://www.komascript.de/node/355\n
+# english translation: ftp://ftp.dante.de/tex-archive/info/templates/fenn/scrlttr2en.tex
+# - rechnung.sty\n
+# from M G Berberich (berberic at fmi.uni-passau.de) and Ulrich Sibiller (uli42 at web.de)
+# Ver3.10 from http://www.forwiss.uni-passau.de/~berberic/TeX/Rechnung/index.html
+#
+# To Do:
+#
+# - get own contact data from gnucash
+# - have own bank information in footline
+# - nicer formatting of invoice date and date due
+# - is there anything else missing in this invoice ?
+
+try:
+ import sys
+ import getopt
+ import gnucash
+ import str_methods
+ from IPython.Shell import IPShellEmbed
+ from gnucash.gnucash_business import Customer, Employee, Vendor, Job, \
+ Address, Invoice, Entry, TaxTable, TaxTableEntry, GNC_AMT_TYPE_PERCENT, \
+ GNC_DISC_PRETAX
+ import locale
+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 get_all_lots(account):
+ """Return all lots in account and descendants"""
+ ltotal=[]
+ descs = account.get_descendants()
+ for desc in descs:
+ if type(desc).__name__ == 'SwigPyObject':
+ desc = gnucash.Account(instance=desc)
+ ll=desc.GetLotList()
+ ltotal+=ll
+ return ltotal
+
+def get_all_invoices_from_lots(account):
+ """Return all invoices in account and descendants
+
+ This is based on lots. So invoices without lots will be missed."""
+
+ lot_list=get_all_lots(account)
+ invoice_list=[]
+ for lot in lot_list:
+ if type(lot).__name__ == 'SwigPyObject':
+ lot = gnucash.GncLot(instance=lot)
+ invoice=gnucash.gnucash_core_c.gncInvoiceGetInvoiceFromLot(lot.instance)
+ if invoice:
+ invoice_list.append(Invoice(instance=invoice))
+ return invoice_list
+
+def invoice_to_lco(invoice):
+ """returns a string which forms a lco-file for use with LaTeX"""
+
+ lco_out=u"\ProvidesFile{data.lco}[]\n"
+
+ def write_variable(ukey, uvalue, replace_linebreak=True):
+
+ outstr = u""
+ if uvalue.endswith("\n"):
+ uvalue=uvalue[0:len(uvalue)-1]
+
+ if not ukey in [u"fromaddress",u"toaddress",u"date"]:
+ outstr += u'\\newkomavar{'
+ outstr += ukey
+ outstr += u"}\n"
+
+ outstr += u"\\setkomavar{"
+ outstr += ukey
+ outstr += u"}{"
+ if replace_linebreak:
+ outstr += uvalue.replace(u"\n",u"\\\\")+"}"
+ return outstr
+
+ # Write owners address
+ add_str=u""
+ owner = invoice.GetOwner()
+ if owner.GetName() != "":
+ add_str += owner.GetName()+"\n"
+
+ addr = owner.GetAddr()
+ if addr.GetName() != "":
+ add_str += addr.GetName().decode("UTF-8")+"\n"
+ if addr.GetAddr1() != "":
+ add_str += addr.GetAddr1().decode("UTF-8")+"\n"
+ if addr.GetAddr2() != "":
+ add_str += addr.GetAddr2().decode("UTF-8")+"\n"
+ if addr.GetAddr3() != "":
+ add_str += addr.GetAddr3().decode("UTF-8")+"\n"
+ if addr.GetAddr4() != "":
+ add_str += addr.GetAddr4().decode("UTF-8")+"\n"
+
+ lco_out += write_variable("toaddress2",add_str)
+
+ # Invoice number
+ inr_str = invoice.GetID()
+ lco_out += write_variable("rechnungsnummer",inr_str)
+
+ # date
+ date = invoice.GetDatePosted()
+ udate = date.strftime("%d.%m.%Y")
+ lco_out += write_variable("date",udate)+"\n"
+
+ # date due
+ date_due = invoice.GetDateDue()
+ udate_due = date_due.strftime("%d.%m.%Y")
+ lco_out += write_variable("date_due",udate_due)+"\n"
+
+
+ # Write the entries
+ ent_str = u""
+ locale.setlocale(locale.LC_ALL,"de_DE")
+ for n,ent in enumerate(invoice.GetEntries()):
+
+ line_str = u""
+
+ if type(ent) != Entry:
+ ent=Entry(instance=ent) # Add to method_returns_list
+
+ descr = ent.GetDescription()
+ price = gnucash.GncNumeric(instance=ent.GetInvPrice()).to_double()
+ n = gnucash.GncNumeric(instance=ent.GetQuantity()) # change gncucash_core.py
+
+ uprice = locale.currency(price).rstrip(" EUR")
+ un = unicode(int(float(n.num())/n.denom())) # choose best way to format numbers according to locale
+
+ line_str = u"\Artikel{"
+ line_str += un
+ line_str += u"}{"
+ line_str += descr.decode("UTF-8")
+ line_str += u"}{"
+ line_str += uprice
+ line_str += u"}"
+
+ #print line_str
+ ent_str += line_str
+
+ lco_out += write_variable("entries",ent_str)
+
+ return lco_out
+
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+ try:
+ prog_name = argv[0]
+ with_ipshell = False
+ ignore_lock = False
+ no_latex_output = False
+ list_invoices = False
+ output_file_name = "data.lco"
+
+ try:
+ opts, args = getopt.getopt(argv[1:], "fhiln:po:", ["help"])
+ except getopt.error, 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"]:
+ print "Using ipshell"
+ with_ipshell = True
+ if opt[0] in ["-l"]:
+ print "listing all invoices"
+ list_invoices=True
+ if opt[0] in ["-n"]:
+ invoice_number = int(opt[1])
+ print "using invoice number", invoice_number
+ if opt[0] in ["-o"]:
+ output_file_name = opt[1]
+ print "using outpu file", output_file_name
+ if opt[0] in ["-p"]:
+ print "no latex output"
+ no_latex_output=True
+ if len(args)>1:
+ print "opts:",opts,"args:",args
+ raise Usage("Only one input can be accepted !")
+ if len(args)==0:
+ raise Usage("No input given !")
+ input_url = args[0]
+ except Usage, err:
+ if err.msg == "Help:":
+ retcode=0
+ else:
+ print >>sys.stderr, "Error:",err.msg
+ print >>sys.stderr, "for help use --help"
+ retcode=2
+
+ print "Prints out all invoices that have corresponding lots."
+ print
+ print "Usage:"
+ print
+ print "Invoke with",prog_name,"input."
+ 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 "-h or --help for this help"
+ print "-i for ipython shell"
+ print "-l list all invoices"
+ print "-n number use invoice number (no. from previous run -l)"
+ print "-o name use name as outputfile. default: data.lco"
+ print "-p pretend (=no) latex output"
+
+ return retcode
+
+ # Try to open the given input
+ try:
+ 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_from_lots(root_account)
+
+ if list_invoices:
+ for number,invoice in enumerate(invoice_list):
+ print str(number)+")"
+ print invoice
+
+ if not (no_latex_output):
+
+ if invoice_number == None:
+ print "Using the first invoice:"
+ invoice_number=0
+
+ invoice=invoice_list[invoice_number]
+ print "Using the following invoice:"
+ print invoice
+
+ lco_str=invoice_to_lco(invoice)
+
+ # Opening output file
+ f=open(output_file_name,"w")
+ lco_str=lco_str.encode("latin1")
+ f.write(lco_str)
+ f.close()
+
+ if with_ipshell:
+ ipshell= IPShellEmbed()
+ ipshell()
+
+ #session.save()
+ session.end()
+
+if __name__ == "__main__":
+ sys.exit(main())
+
More information about the gnucash-changes
mailing list