GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
latex_invoices.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3 
4 ##@file
5 # @brief Exports an invoice to lco-file for use with LaTeX, see \ref py_invoice_export
6 # @ingroup python_bindings_examples
7 # @author Christoph Holtermann (c.holtermann (at) gmx.de)
8 # @date May 2011
9 #
10 # @details
11 # The output file can be imported into KOMA-Script-letters.
12 # This works primarily for germany. Internationalization welcome!
13 #
14 # Additional files:
15 #
16 # - Invoice.tex\n
17 # Example template file. Should be modified according to personal needs.
18 # - rechnung.sty\n
19 # style file for invoices.\n
20 # This file is not part of the python-bindings!\n
21 # For an example where to get it see section credits below.
22 #
23 # Usage :
24 # \code latex_invoice -l -f -n INVOICE_NUMBER file://testfile \endcode
25 # will create file data.lco.
26 # \code latex --output-format=pdf Invoice.tex \endcode
27 # should run latex on file Invoice.tex and result in Invoice.pdf. Invoice.tex includes data.lco.
28 #
29 # Additional information :
30 #
31 # - Doxygen docs: see page \ref py_invoice_export at http://svn.gnucash.org/docs/HEAD/
32 # - http://www.uweziegenhagen.de/latex/documents/rechnung/rechnungen.pdf (german)
33 #
34 # Credits to and ideas from
35 #
36 # - Main function as proposed by Guido van Rossum
37 # at http://www.artima.com/weblogs/viewpost.jsp?thread=4829
38 # - Invoice.tex is derived from\n
39 # scrlttr2.tex v0.3. (c) by Juergen Fenn <[email protected]>\n
40 # http://www.komascript.de/node/355\n
41 # english translation: ftp://ftp.dante.de/tex-archive/info/templates/fenn/scrlttr2en.tex
42 # - rechnung.sty\n
43 # from M G Berberich ([email protected]) and Ulrich Sibiller ([email protected])
44 # Ver3.10 from http://www.forwiss.uni-passau.de/~berberic/TeX/Rechnung/index.html
45 #
46 # To Do:
47 #
48 # - get own contact data from gnucash
49 # - have own bank information in footline
50 # - nicer formatting of invoice date and date due
51 # - is there anything else missing in this invoice ?
52 
53 try:
54  import sys
55  import getopt
56  import gnucash
57  import str_methods
58  from gncinvoicefkt import *
59  from IPython import version_info as IPython_version_info
60  if IPython_version_info[0]>=1:
61  from IPython.terminal.ipapp import TerminalIPythonApp
62  else:
63  from IPython.frontend.terminal.ipapp import TerminalIPythonApp
64  from gnucash.gnucash_business import Customer, Employee, Vendor, Job, \
65  Address, Invoice, Entry, TaxTable, TaxTableEntry, GNC_AMT_TYPE_PERCENT, \
66  GNC_DISC_PRETAX
67  import locale
68 except ImportError as import_error:
69  print "Problem importing modules."
70  print import_error
71  sys.exit(2)
72 
73 class Usage(Exception):
74  def __init__(self, msg):
75  self.msg = msg
76 
77 def invoice_to_lco(invoice):
78  """returns a string which forms a lco-file for use with LaTeX"""
79 
80  lco_out=u"\ProvidesFile{data.lco}[]\n"
81 
82  def write_variable(ukey, uvalue, replace_linebreak=True):
83 
84  outstr = u""
85  if uvalue.endswith("\n"):
86  uvalue=uvalue[0:len(uvalue)-1]
87 
88  if not ukey in [u"fromaddress",u"toaddress",u"date"]:
89  outstr += u'\\newkomavar{'
90  outstr += ukey
91  outstr += u"}\n"
92 
93  outstr += u"\\setkomavar{"
94  outstr += ukey
95  outstr += u"}{"
96  if replace_linebreak:
97  outstr += uvalue.replace(u"\n",u"\\\\")+"}"
98  return outstr
99 
100  # Write owners address
101  add_str=u""
102  owner = invoice.GetOwner()
103  if owner.GetName() != "":
104  add_str += owner.GetName().decode("UTF-8")+"\n"
105 
106  addr = owner.GetAddr()
107  if addr.GetName() != "":
108  add_str += addr.GetName().decode("UTF-8")+"\n"
109  if addr.GetAddr1() != "":
110  add_str += addr.GetAddr1().decode("UTF-8")+"\n"
111  if addr.GetAddr2() != "":
112  add_str += addr.GetAddr2().decode("UTF-8")+"\n"
113  if addr.GetAddr3() != "":
114  add_str += addr.GetAddr3().decode("UTF-8")+"\n"
115  if addr.GetAddr4() != "":
116  add_str += addr.GetAddr4().decode("UTF-8")+"\n"
117 
118  lco_out += write_variable("toaddress2",add_str)
119 
120  # Invoice number
121  inr_str = invoice.GetID()
122  lco_out += write_variable("rechnungsnummer",inr_str)
123 
124  # date
125  date = invoice.GetDatePosted()
126  udate = date.strftime("%d.%m.%Y")
127  lco_out += write_variable("date",udate)+"\n"
128 
129  # date due
130  date_due = invoice.GetDateDue()
131  udate_due = date_due.strftime("%d.%m.%Y")
132  lco_out += write_variable("date_due",udate_due)+"\n"
133 
134 
135  # Write the entries
136  ent_str = u""
137  locale.setlocale(locale.LC_ALL,"de_DE")
138  for n,ent in enumerate(invoice.GetEntries()):
139 
140  line_str = u""
141 
142  if type(ent) != Entry:
143  ent=Entry(instance=ent) # Add to method_returns_list
144 
145  descr = ent.GetDescription()
146  price = ent.GetInvPrice().to_double()
147  n = ent.GetQuantity()
148 
149  uprice = locale.currency(price).rstrip(" EUR")
150  un = unicode(int(float(n.num())/n.denom())) # choose best way to format numbers according to locale
151 
152  line_str = u"\Artikel{"
153  line_str += un
154  line_str += u"}{"
155  line_str += descr.decode("UTF-8")
156  line_str += u"}{"
157  line_str += uprice
158  line_str += u"}"
159 
160  #print line_str
161  ent_str += line_str
162 
163  lco_out += write_variable("entries",ent_str)
164 
165  return lco_out
166 
167 
168 def main(argv=None):
169  if argv is None:
170  argv = sys.argv
171  try:
172  prog_name = argv[0]
173  with_ipshell = False
174  ignore_lock = False
175  no_latex_output = True
176  list_invoices = False
177  output_file_name = "data.lco"
178  invoice_number = None
179 
180  try:
181  opts, args = getopt.getopt(argv[1:], "fhiln:po:", ["help"])
182  except getopt.error, msg:
183  raise Usage(msg)
184 
185  for opt in opts:
186  if opt[0] in ["-f"]:
187  print "ignoring lock"
188  ignore_lock = True
189  if opt[0] in ["-h","--help"]:
190  raise Usage("Help:")
191  if opt[0] in ["-i"]:
192  print "Using ipshell"
193  with_ipshell = True
194  if opt[0] in ["-l"]:
195  print "listing all invoices"
196  list_invoices=True
197  if opt[0] in ["-n"]:
198  invoice_number = int(opt[1])
199  print "using invoice number", invoice_number
200  no_latex_output = False
201  if opt[0] in ["-o"]:
202  output_file_name = opt[1]
203  print "using output file", output_file_name
204  if len(args)>1:
205  print "opts:",opts,"args:",args
206  raise Usage("Only one input can be accepted !")
207  if len(args)==0:
208  raise Usage("No input given !")
209  input_url = args[0]
210  except Usage, err:
211  if err.msg == "Help:":
212  retcode=0
213  else:
214  print >>sys.stderr, "Error:",err.msg
215  print >>sys.stderr, "for help use --help"
216  retcode=2
217 
218  print "Generate a LaTeX invoice or print out all invoices."
219  print
220  print "Usage:"
221  print
222  print "Invoke with",prog_name,"input."
223  print "where input is"
224  print " filename"
225  print "or file://filename"
226  print "or mysql://user:password@host/databasename"
227  print
228  print "-f force open = ignore lock"
229  print "-h or --help for this help"
230  print "-i for ipython shell"
231  print "-l list all invoices"
232  print "-n number use invoice number (no. from previous run with -l)"
233  print "-o name use name as outputfile. default: data.lco"
234 
235  return retcode
236 
237  # Try to open the given input
238  try:
239  session = gnucash.Session(input_url,ignore_lock=ignore_lock)
240  except Exception as exception:
241  print "Problem opening input."
242  print exception
243  return 2
244 
245  book = session.book
246  root_account = book.get_root_account()
247  comm_table = book.get_table()
248  EUR = comm_table.lookup("CURRENCY", "EUR")
249 
250  invoice_list=get_all_invoices(book)
251 
252  if list_invoices:
253  for number,invoice in enumerate(invoice_list):
254  print str(number)+")"
255  print invoice
256 
257  if not (no_latex_output):
258 
259  if invoice_number == None:
260  print "Using the first invoice:"
261  invoice_number=0
262 
263  invoice=invoice_list[invoice_number]
264  print "Using the following invoice:"
265  print invoice
266 
267  lco_str=invoice_to_lco(invoice)
268 
269  # Opening output file
270  f=open(output_file_name,"w")
271  lco_str=lco_str.encode("latin1")
272  f.write(lco_str)
273  f.close()
274 
275  if with_ipshell:
276  app = TerminalIPythonApp.instance()
277  app.initialize(argv=[]) # argv=[] instructs IPython to ignore sys.argv
278  app.start()
279 
280  #session.save()
281  session.end()
282 
283 if __name__ == "__main__":
284  sys.exit(main())
285