|
GnuCash 2.4.99
|
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
1.7.4