#!/usr/bin/python
# coding=utf-8

import lxml.html
import datetime
import getopt

# make sure stdout is UTF-8, also when redirecting to pipe or file
import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)

prodcodemap = {
  '200701' : '3101-Medlem FIRMA',
  '200702' : '3102-Medlem FIRMA ekstra perso',
  '200703' : '3100-Medlem PERSONLIG',
  '200704' : '3100-Medlem PERSONLIG', # Student
  '200705' : '3110-Medlem SAGE',

  '200801' : '3101-Medlem FIRMA',
  '200802' : '3102-Medlem FIRMA ekstra perso',
  '200803' : '3100-Medlem PERSONLIG',
  '200804' : '3100-Medlem PERSONLIG',
  '200805' : '3110-Medlem SAGE',
  '200806' : '3110-Medlem SAGE', # SAGE student
  '200807' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '200808' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '200901' : '3101-Medlem FIRMA',
  '200902' : '3102-Medlem FIRMA ekstra perso',
  '200903' : '3100-Medlem PERSONLIG',
  '200904' : '3100-Medlem PERSONLIG',
  '200905' : '3110-Medlem SAGE',
  '200906' : '3110-Medlem SAGE', # SAGE student
  '200907' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '200908' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '201001' : '3101-Medlem FIRMA',
  '201002' : '3102-Medlem FIRMA ekstra perso',
  '201003' : '3100-Medlem PERSONLIG',
  '201004' : '3100-Medlem PERSONLIG',
  '201005' : '3110-Medlem SAGE',
  '201006' : '3110-Medlem SAGE', # SAGE student
  '201007' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '201008' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '201101' : '3101-Medlem FIRMA',
  '201102' : '3102-Medlem FIRMA ekstra perso',
  '201103' : '3100-Medlem PERSONLIG',
  '201104' : '3100-Medlem PERSONLIG',
  '201105' : '3110-Medlem SAGE',
  '201106' : '3110-Medlem SAGE', # SAGE student
  '201107' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '201108' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '201201' : '3101-Medlem FIRMA',
  '201202' : '3102-Medlem FIRMA ekstra perso',
  '201203' : '3100-Medlem PERSONLIG',
  '201204' : '3100-Medlem PERSONLIG',
  '201205' : '3110-Medlem SAGE',
  '201206' : '3110-Medlem SAGE', # SAGE student
  '201207' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '201208' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '201301' : '3101-Medlem FIRMA',
  '201302' : '3102-Medlem FIRMA ekstra perso',
  '201303' : '3100-Medlem PERSONLIG',
  '201304' : '3100-Medlem PERSONLIG',
  '201305' : '3110-Medlem SAGE',
  '201306' : '3110-Medlem SAGE', # SAGE student
  '201307' : '3100-Medlem PERSONLIG', # Personlig uten USENIX
  '201308' : '3100-Medlem PERSONLIG', # Student uten USENIX

  '301000' : 'Bidrag til FiksGataMi',
  '301001' : 'Bidrag til OpenStreetmap',
  }

descdict = {
  '3101-Medlem FIRMA':              'Kontingent',
  '3102-Medlem FIRMA ekstra perso': 'Kontingent',
  '3100-Medlem PERSONLIG':          'Kontingent',
  '3110-Medlem SAGE':               'Kontingent',
  '3100-Medlem PERSONLIG':          'Kontingent',

  'Bidrag til FiksGataMi':          'Bidrag til FiksGataMi',
  'Bidrag til OpenStreetmap':       'Bidrag til OpenStreetmap'
}

filename = "invoices.xml"

def getval(element, xpath):
  sub = element.xpath(xpath)
  if 0 < len(sub):
    return sub[0].text
  return None

def datestr2date(datestr):
    day, month, year = datestr.split('.')
    return datetime.date(2000+int(year), int(month), int(day))

def rightprint(lp, rp):
    # Take one left argument, string, and
    # one right argument, float
    s = ("  %-48s" % lp)
    if not isinstance(rp, float):
        rp = float(rp);
    if (len(s) > 50):
        print s[:47]+"...  {0:>12.2f}".format(rp)
    else:
        print s + "  {0:>12.2f}".format(rp)

def convert(year):
  tree = lxml.etree.parse(filename)
  invoices = tree.xpath('/invoices/invoice')
#print invoices
  for invoice in invoices:
    invoiceno = getval(invoice, './optional/invoiceNo')
    invoicedate = datestr2date(getval(invoice, './optional/invoiceDate'))
    if (0 != str(invoicedate).find(str(year))):
      continue
    custno = getval(invoice, './optional/recipientNo')
    total = float(getval(invoice, './optional/total'))
    if 'credit' == getval(invoice, './optional/invoiceType'):
      direction = -1
    else:
      direction = 1
    
    invoicetype = { 'ordinary': "faktura",
                    'credit': "kreditnota" }.get(getval(invoice, './optional/invoiceType'), "ukjent")
    lines = {}
    descset = set([])
    for line in invoice.xpath('./lines/line'):
      prodcode = getval(line, './prodCode');
      desc = getval(line, './desc');
      linetotal = getval(line, './lineTotal')
      if linetotal is not None and linetotal != "0.00":
        if prodcode:
            descset.add(descdict[prodcodemap[prodcode]])
            tag = ("result:%s" % prodcodemap[prodcode])
        else:
            descset.add("Manglende beskrivelse")
            tag = ("result:%s" % desc)
        if (tag in lines):
            lines[tag]+= float(linetotal)
        else:
            lines[tag] = float(linetotal)
    print "%s (%s #%s) %s" % (invoicedate, invoicetype, invoiceno, ", ".join(descset))
    rightprint(("customer:%s" % custno), -1*direction*total)
    for l in lines:
        rightprint(l, direction*lines[l]);
    print # record separator

def rightprint(lp, rp):
    lp = ("  %-48s" % lp)
    if not isinstance(rp, float):
        rp = float(rp);
    if (len(lp) > 50):
        print lp[:47]+"...  {0:>12.2f}".format(rp)
    else:
        print lp + "  {0:>12.2f}".format(rp)

def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
    except getopt.error, msg:
        print msg
        print "for help use --help"
        sys.exit(2)

    for o, a in opts:
        if o in ("-h", "--help"):
            print __doc__
            sys.exit(0)
    for arg in args:
      convert(int(arg))

if __name__ == "__main__":
    main()
