GnuCash 2.4.99
latex_invoices.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: UTF-8 -*-
00003 
00004 ##@file
00005 # @ingroup python_bindings_examples
00006 # @author Christoph Holtermann (c.holtermann (at) gmx.de)
00007 # @date May 2011
00008 # @brief Exports an invoice to lco-file for use with LaTeX
00009 #
00010 # The output file can be imported into KOMA-Script-letters.
00011 # This works primarily for germany. Internationalization welcome!
00012 #
00013 # Additional files:
00014 #
00015 # - Invoice.tex\n
00016 # Example template file. Should be modified according to personal needs.
00017 # - rechnung.sty\n
00018 # style file for invoices.\n
00019 # This file is not part of the python-bindings!\n
00020 # For an example where to get it see section credits below.
00021 #
00022 # Usage :
00023 # \code latex_invoice file://testfile \endcode
00024 # will create file data.lco.
00025 # \code latex --output-format=pdf Invoice.tex \endcode
00026 # should run latex on file Invoice.tex and result in Invoice.pdf. Invoice.tex includes data.lco.
00027 #
00028 # Additional information :
00029 #
00030 # - http://www.uweziegenhagen.de/latex/documents/rechnung/rechnungen.pdf (german)
00031 # 
00032 # Credits to and ideas from
00033 #
00034 # - Main function as proposed by Guido van Rossum
00035 #   at http://www.artima.com/weblogs/viewpost.jsp?thread=4829
00036 # - Invoice.tex is derived from\n
00037 #   scrlttr2.tex v0.3. (c) by Juergen Fenn <juergen.fenn@gmx.de>\n
00038 #   http://www.komascript.de/node/355\n
00039 #   english translation: ftp://ftp.dante.de/tex-archive/info/templates/fenn/scrlttr2en.tex
00040 # - rechnung.sty\n
00041 #   from M G Berberich (berberic@fmi.uni-passau.de) and Ulrich Sibiller (uli42@web.de)
00042 #   Ver3.10 from http://www.forwiss.uni-passau.de/~berberic/TeX/Rechnung/index.html
00043 #
00044 # To Do:
00045 #
00046 # - get own contact data from gnucash
00047 # - have own bank information in footline
00048 # - nicer formatting of invoice date and date due
00049 # - is there anything else missing in this invoice ?
00050 
00051 try:
00052     import sys
00053     import getopt
00054     import gnucash
00055     import str_methods
00056     from IPython.Shell import IPShellEmbed
00057     from gnucash.gnucash_business import Customer, Employee, Vendor, Job, \
00058         Address, Invoice, Entry, TaxTable, TaxTableEntry, GNC_AMT_TYPE_PERCENT, \
00059             GNC_DISC_PRETAX
00060     import locale
00061 except ImportError as import_error:
00062     print "Problem importing modules."
00063     print import_error
00064     sys.exit(2) 
00065 
00066 class Usage(Exception):
00067     def __init__(self, msg):
00068         self.msg = msg
00069 
00070 def get_all_lots(account):
00071   """Return all lots in account and descendants"""
00072   ltotal=[]
00073   descs = account.get_descendants()
00074   for desc in descs:
00075     if type(desc).__name__ == 'SwigPyObject':
00076         desc = gnucash.Account(instance=desc)
00077     ll=desc.GetLotList()
00078     ltotal+=ll
00079   return ltotal
00080 
00081 def get_all_invoices_from_lots(account):
00082   """Return all invoices in account and descendants
00083 
00084   This is based on lots. So invoices without lots will be missed."""
00085 
00086   lot_list=get_all_lots(account)
00087   invoice_list=[]
00088   for lot in lot_list:
00089     if type(lot).__name__ == 'SwigPyObject':
00090         lot = gnucash.GncLot(instance=lot)
00091     invoice=gnucash.gnucash_core_c.gncInvoiceGetInvoiceFromLot(lot.instance)
00092     if invoice:
00093       invoice_list.append(Invoice(instance=invoice))
00094   return invoice_list
00095 
00096 def invoice_to_lco(invoice):
00097   """returns a string which forms a lco-file for use with LaTeX"""
00098 
00099   lco_out=u"\ProvidesFile{data.lco}[]\n"
00100   
00101   def write_variable(ukey, uvalue, replace_linebreak=True):
00102 
00103     outstr = u""
00104     if uvalue.endswith("\n"):
00105         uvalue=uvalue[0:len(uvalue)-1]
00106 
00107     if not ukey in [u"fromaddress",u"toaddress",u"date"]:
00108         outstr += u'\\newkomavar{'
00109         outstr += ukey
00110         outstr += u"}\n"
00111 
00112     outstr += u"\\setkomavar{"
00113     outstr += ukey
00114     outstr += u"}{"
00115     if replace_linebreak:
00116         outstr += uvalue.replace(u"\n",u"\\\\")+"}"
00117     return outstr
00118 
00119   # Write owners address
00120   add_str=u""
00121   owner = invoice.GetOwner()
00122   if owner.GetName() != "":
00123     add_str += owner.GetName()+"\n"
00124 
00125   addr  = owner.GetAddr()
00126   if addr.GetName() != "":
00127     add_str += addr.GetName().decode("UTF-8")+"\n"
00128   if addr.GetAddr1() != "":
00129     add_str += addr.GetAddr1().decode("UTF-8")+"\n"
00130   if addr.GetAddr2() != "":
00131     add_str += addr.GetAddr2().decode("UTF-8")+"\n"
00132   if addr.GetAddr3() != "":
00133     add_str += addr.GetAddr3().decode("UTF-8")+"\n"
00134   if addr.GetAddr4() != "":
00135     add_str += addr.GetAddr4().decode("UTF-8")+"\n"
00136 
00137   lco_out += write_variable("toaddress2",add_str)
00138 
00139   # Invoice number
00140   inr_str = invoice.GetID()
00141   lco_out += write_variable("rechnungsnummer",inr_str)
00142 
00143   # date
00144   date      = invoice.GetDatePosted()
00145   udate     = date.strftime("%d.%m.%Y")
00146   lco_out  += write_variable("date",udate)+"\n"
00147 
00148   # date due
00149   date_due  = invoice.GetDateDue()
00150   udate_due = date_due.strftime("%d.%m.%Y")
00151   lco_out  += write_variable("date_due",udate_due)+"\n"
00152 
00153 
00154   # Write the entries
00155   ent_str = u""
00156   locale.setlocale(locale.LC_ALL,"de_DE")
00157   for n,ent in enumerate(invoice.GetEntries()): 
00158       
00159       line_str = u""
00160 
00161       if type(ent) != Entry:
00162         ent=Entry(instance=ent)                                 # Add to method_returns_list
00163       
00164       descr = ent.GetDescription()
00165       price = gnucash.GncNumeric(instance=ent.GetInvPrice()).to_double()
00166       n     = gnucash.GncNumeric(instance=ent.GetQuantity())    # change gncucash_core.py
00167      
00168       uprice = locale.currency(price).rstrip(" EUR") 
00169       un = unicode(int(float(n.num())/n.denom()))               # choose best way to format numbers according to locale
00170 
00171       line_str =  u"\Artikel{"
00172       line_str += un
00173       line_str += u"}{"
00174       line_str += descr.decode("UTF-8")
00175       line_str += u"}{"
00176       line_str += uprice
00177       line_str += u"}"
00178 
00179       #print line_str
00180       ent_str += line_str
00181 
00182   lco_out += write_variable("entries",ent_str)
00183 
00184   return lco_out
00185 
00186 
00187 def main(argv=None):
00188     if argv is None:
00189         argv = sys.argv
00190     try:
00191         prog_name = argv[0]
00192         with_ipshell = False
00193         ignore_lock = False
00194         no_latex_output = False
00195         list_invoices = False
00196         output_file_name = "data.lco"
00197 
00198         try:
00199             opts, args = getopt.getopt(argv[1:], "fhiln:po:", ["help"])
00200         except getopt.error, msg:
00201              raise Usage(msg)
00202         
00203         for opt in opts:
00204             if opt[0] in ["-f"]:
00205                 print "ignoring lock"
00206                 ignore_lock = True
00207             if opt[0] in ["-h","--help"]:
00208                 raise Usage("Help:")
00209             if opt[0] in ["-i"]:
00210                 print "Using ipshell"
00211                 with_ipshell = True
00212             if opt[0] in ["-l"]:
00213                 print "listing all invoices"
00214                 list_invoices=True
00215             if opt[0] in ["-n"]:
00216                 invoice_number = int(opt[1])
00217                 print "using invoice number", invoice_number
00218             if opt[0] in ["-o"]:
00219                 output_file_name = opt[1]
00220                 print "using outpu file", output_file_name
00221             if opt[0] in ["-p"]:
00222                 print "no latex output"
00223                 no_latex_output=True
00224         if len(args)>1:
00225             print "opts:",opts,"args:",args
00226             raise Usage("Only one input can be accepted !")
00227         if len(args)==0:
00228             raise Usage("No input given !")
00229         input_url = args[0]
00230     except Usage, err:
00231         if err.msg == "Help:":
00232             retcode=0
00233         else:
00234             print >>sys.stderr, "Error:",err.msg
00235             print >>sys.stderr, "for help use --help"
00236             retcode=2
00237         
00238         print "Prints out all invoices that have corresponding lots."
00239         print
00240         print "Usage:"
00241         print
00242         print "Invoke with",prog_name,"input."
00243         print "where input is"
00244         print "   filename"
00245         print "or file://filename" 
00246         print "or mysql://user:password@host/databasename" 
00247         print
00248         print "-f             force open = ignore lock"
00249         print "-h or --help   for this help"
00250         print "-i             for ipython shell"
00251         print "-l             list all invoices"
00252         print "-n number      use invoice number (no. from previous run -l)"
00253         print "-o name        use name as outputfile. default: data.lco"
00254         print "-p             pretend (=no) latex output"
00255         
00256         return retcode
00257 
00258     # Try to open the given input
00259     try:
00260         session = gnucash.Session(input_url,ignore_lock=ignore_lock)
00261     except Exception as exception:
00262         print "Problem opening input."
00263         print exception
00264         return 2
00265     
00266     book = session.book
00267     root_account = book.get_root_account()
00268     comm_table = book.get_table()
00269     EUR = comm_table.lookup("CURRENCY", "EUR")
00270 
00271     invoice_list=get_all_invoices_from_lots(root_account)
00272 
00273     if list_invoices:
00274         for number,invoice in enumerate(invoice_list):
00275             print str(number)+")"
00276             print invoice
00277 
00278     if not (no_latex_output):
00279 
00280         if invoice_number == None:
00281             print "Using the first invoice:"
00282             invoice_number=0
00283         
00284         invoice=invoice_list[invoice_number]
00285         print "Using the following invoice:"
00286         print invoice
00287     
00288         lco_str=invoice_to_lco(invoice)
00289 
00290         # Opening output file
00291         f=open(output_file_name,"w")
00292         lco_str=lco_str.encode("latin1")
00293         f.write(lco_str)
00294         f.close()
00295 
00296     if with_ipshell:
00297         ipshell= IPShellEmbed()
00298         ipshell() 
00299 
00300     #session.save()
00301     session.end()
00302 
00303 if __name__ == "__main__":
00304     sys.exit(main())
00305 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines