#!/usr/bin/env python3 import sys import yaml def debug(*args): sys.stderr.write('{}\n'.format(' '.join(str(x) for x in args))) def euros(cents): return '%.02f' % (cents / 100.0) class Item: def __init__(self, itemdict): self.dict = dict(itemdict) count = itemdict['count'] if count == "": return unit_cents = int(itemdict['unit'] * 100.0) vatpc = float(itemdict['vatpc']) / 100.0 self.total_cents = count * unit_cents self.vat_cents = 0 if vatpc > 0: unit_cents_with_vat = int(unit_cents / (1.0 - vatpc)) unit_vat_cents = unit_cents_with_vat - unit_cents debug('dict', self.dict) debug('total_cents', self.total_cents) debug('vatpc', vatpc) debug('unit_cents_with_vat', unit_cents_with_vat) debug('unit_vat_cents', unit_vat_cents) debug('calc', int(vatpc * unit_cents_with_vat)) assert int(unit_cents_with_vat * vatpc) == unit_vat_cents assert unit_cents_with_vat == unit_cents + unit_vat_cents self.vat_cents = unit_vat_cents * count self.dict.update({ 'unit_euros': euros(unit_cents), 'total_cents': self.total_cents, 'total': euros(self.total_cents), 'unitwithvat': euros(unit_cents + self.vat_cents), 'vat_cents': self.vat_cents, 'vat': euros(self.vat_cents), 'vatsum': euros(self.vat_cents * count), 'totalwithvat': euros(count * (unit_cents + self.vat_cents)), }) item_template = ( r'\raggedbottom #number# & ' r'\parbox[t]{5.5cm}{#desc#\\#date#} & ' r'\raggedbottom #count# & ' r'\raggedbottom #unit_euros# & ' r'\raggedbottom #unitwithvat# & ' r'\raggedbottom #vatpc#\% & ' r'\raggedbottom #total# & ' r'\raggedbottom #vatsum# & ' r'\raggedbottom #totalwithvat# \\[2.2ex]' ) def cat(filename): with open(filename) as f: return f.read() def substitute_all(text, subst): for key, value in subst.items(): pattern = '#{}#'.format(key) text = str(value).join(text.split(pattern)) return text text = cat('template.tex') with open(sys.argv[1]) as f: company = yaml.safe_load(f) with open(sys.argv[2]) as f: invoice = yaml.safe_load(f) items = invoice['invoiceitems'] values = dict(company) values.update(invoice) itemtext = '' total_cents = 0 total_vat = 0 total_sum = 0 for item in items: it = Item(item) itemtext += substitute_all(item_template, it.dict) total_cents += it.total_cents total_vat += it.vat_cents total_sum += it.total_cents + it.vat_cents values['itemtext'] = itemtext values['totalraw'] = euros(total_cents) values['totalvat'] = euros(total_vat) values['totalsum'] = euros(total_sum) values['amount'] = values['totalsum'] text = substitute_all(text, values) sys.stdout.write(text)