mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug #651175 - Script to export invoices to LaTeX
Patch by Christoph Holtermann git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@21255 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
acad985837
commit
6f5756c178
@ -86,6 +86,8 @@ endif
|
||||
|
||||
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 \
|
||||
|
154
src/optional/python-bindings/example_scripts/Invoice.tex
Normal file
154
src/optional/python-bindings/example_scripts/Invoice.tex
Normal file
@ -0,0 +1,154 @@
|
||||
%---------------------------------------------------------------------------
|
||||
% Invoice.tex v0.1 by Christoph Holtermann (c.holtermann@gmx.de)
|
||||
%
|
||||
% modified from
|
||||
% scrlttr2.tex v0.3. (c) by Juergen Fenn <juergen.fenn@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}
|
||||
%---------------------------------------------------------------------------
|
305
src/optional/python-bindings/example_scripts/latex_invoices.py
Normal file
305
src/optional/python-bindings/example_scripts/latex_invoices.py
Normal file
@ -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@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@fmi.uni-passau.de) and Ulrich Sibiller (uli42@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())
|
||||
|
Loading…
Reference in New Issue
Block a user