summaryrefslogtreecommitdiff
path: root/fracture
diff options
context:
space:
mode:
Diffstat (limited to 'fracture')
-rw-r--r--fracture/__main__.py34
-rw-r--r--fracture/invoice.py67
2 files changed, 76 insertions, 25 deletions
diff --git a/fracture/__main__.py b/fracture/__main__.py
index d0305ab..c51c556 100644
--- a/fracture/__main__.py
+++ b/fracture/__main__.py
@@ -1,6 +1,7 @@
-from invoice import Invoice, Tax
+from invoice import Invoice, Tax, Product
import db
+from csv import DictWriter
import datetime
from functools import wraps
from argparse import ArgumentParser as ap
@@ -27,6 +28,10 @@ def load_config():
conf = ConfigParser()
conf.read(confile)
+ # VAT-types
+ for k in conf["vat"]:
+ Product.VATS += (float(conf["vat"][k]),)
+
# SERIES
for k in conf["series"]:
Invoice.SERIES[int(k)] = conf["series"][k]
@@ -55,10 +60,10 @@ def load_config():
templatefile = path.join(confile, templatefile)
# INVOICE LEVEL TAXES (like IRPF in Spain)
- tax = []
+ tax = ()
for k in conf["taxes"]:
- tax.append(Tax(k, conf.getfloat("taxes",k)))
- Invoice.DEFAULT_TAXES = tuple(tax)
+ tax += (Tax(k, conf.getfloat("taxes",k)),)
+ Invoice.DEFAULT_TAXES = tax
# DATABASE
Invoice.DB_FILE = path.join(basedir, "invoice.db")
@@ -112,7 +117,26 @@ def new_invoice():
@command
def summarize(xlsx=False, year=None, quarter=None):
invoices = Invoice.load_by_date(year, quarter)
- rows = map(lambda x: x.to_row(), invoices)
+ rows = sorted((map(lambda x: x.to_row(), invoices)),
+ key=lambda x: x["type"])
+
+ keys = list(rows[0].keys())
+ for r in rows:
+ for k in r.keys():
+ if k not in keys:
+ # TODO:
+ # Inserts all the taxes at the end, but this is not cool
+ # because it needs information about how is the invoice
+ # arranged
+ # Maybe move this to a static function in invoices and call it
+ # summary and make it work with some logic like: create the
+ # keys first and then go setting them in order
+ keys.insert(-1, k)
+ import sys
+ wrtr = DictWriter(sys.stdout, keys)
+ wrtr.writeheader()
+ for r in rows:
+ wrtr.writerow(r)
if __name__ == "__main__":
diff --git a/fracture/invoice.py b/fracture/invoice.py
index 84c0f9b..b3fa6b6 100644
--- a/fracture/invoice.py
+++ b/fracture/invoice.py
@@ -1,6 +1,7 @@
import sqlite3
from datetime import date, datetime, timedelta
from configparser import ConfigParser
+from collections import OrderedDict
import io
class Tax:
@@ -9,6 +10,7 @@ class Tax:
self.ratio = ratio
class Product:
+ VATS = ()
def __init__(self, description, units=1.0,
price_unit=0.0, vat = 0.21):
if len(description) == 0:
@@ -16,7 +18,15 @@ class Product:
self.description = description
self.units = units
self.price_unit = price_unit
- self.vat = vat
+ if vat in self.VATS:
+ self.vat = vat
+ else:
+ raise ValueError("Product: No valid VAT. Valid are:"+\
+ str(Product.VATS))
+ def calc_base(self):
+ return self.price_unit * self.units
+ def calc_charged_vat(self):
+ return self.calc_base() * self.vat
class Customer:
def __init__(self, name, id = "", address = ""):
@@ -323,26 +333,43 @@ class Invoice:
pass
def to_row(self):
- psum = ((i.price_unit*i.units,
- i.price_unit*i.units*i.vat) for i in self.products)
- base = 0
- vat = 0
- for i in psum:
- base += i[0]
- vat += i[1]
-
- row = {
- "type": self.type,
- "series": self.series,
- "id": self.format_id(),
- "date": self.date.strftime("%Y-%m-%d"),
- "customer_id": self.customer.id,
- "customer_name": self.customer.name,
- "base": round(base, self.CURRENCY_DECIMAL),
- "vat": round(vat, self.CURRENCY_DECIMAL)
- }
+ row = OrderedDict(
+ type = self.type,
+ id = self.format_id(),
+ date = self.date.strftime("%Y-%m-%d"),
+ customer_id = self.customer.id,
+ customer_name = self.customer.name,
+ )
+
+ total_base = 0
+ total_charged = 0
+
+ vats = sorted(Product.VATS)
+ to_base_key = lambda v: "base("+str(v*100)+"%)"
+ to_vat_key = lambda v: "VAT("+str(v*100)+"%)"
+ for vat in vats:
+ ps = filter(lambda p: p.vat == vat, self.products)
+
+ vat_base = 0
+ charged_vat = 0
+ for product in ps:
+ vat_base += product.calc_base()
+ charged_vat += product.calc_charged_vat()
+ row[to_base_key(vat)] = round(vat_base, self.CURRENCY_DECIMAL)
+ row[to_vat_key(vat)] = round(charged_vat, self.CURRENCY_DECIMAL)
+
+ total_base += vat_base
+ total_charged += vat_base + charged_vat
+
+ row["base(TOTAL)"] = round(total_base, self.CURRENCY_DECIMAL)
+
+ to_tax_key = lambda tax: tax.name + "("+ str(tax.ratio*100) +"%)"
for i in self.taxes:
- row["tax-" + i.name] = round(i.ratio * base, self.CURRENCY_DECIMAL)
+ tax_amount = i.ratio * total_base
+ row[to_tax_key(i)] = round(tax_amount, self.CURRENCY_DECIMAL)
+ total_charged += tax_amount
+
+ row["TOTAL"] = round(total_charged, self.CURRENCY_DECIMAL)
return row