From 4444e709f8ad51b2e7c375b74174b54be7bc3ef5 Mon Sep 17 00:00:00 2001 From: zhangshine Date: Tue, 9 Jun 2015 22:20:04 +0800 Subject: [PATCH] auto calculate total --- pyinvoice/models.py | 11 +++--- pyinvoice/templates.py | 81 +++++++++++++++++++++++++++++------------- simple.py | 9 +++-- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/pyinvoice/models.py b/pyinvoice/models.py index e41da78..660b3b5 100644 --- a/pyinvoice/models.py +++ b/pyinvoice/models.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +from decimal import Decimal class PDFInfo(object): @@ -55,22 +56,22 @@ class Item(object): """ Product/Item information """ - def __init__(self, item_id, name, description, units, unit_price, subtotal, vat_tax=None): + def __init__(self, name, description, units, unit_price): """ Item modal init - :param item_id: Order id or Item id :param name: Item name :param units: Amount :param unit_price: Unit price :return: """ - self.item_id = item_id self.name = name self.description = description self.units = units self.unit_price = unit_price - self.vat_tax = vat_tax - self.subtotal = subtotal + + @property + def amount(self): + return int(self.units) * Decimal(self.unit_price) class Transaction(object): diff --git a/pyinvoice/templates.py b/pyinvoice/templates.py index adf2a47..1fca116 100644 --- a/pyinvoice/templates.py +++ b/pyinvoice/templates.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals from datetime import datetime, date +from decimal import Decimal from reportlab.lib import colors from reportlab.lib.enums import TA_CENTER, TA_RIGHT from reportlab.lib.pagesizes import letter @@ -42,8 +43,7 @@ class SimpleInvoice(SimpleDocTemplate): self.client_info = None self.is_paid = False self._items = [] - self.item_tax_total = None - self.item_total = None + self._item_tax_rate = None self._transactions = [] self._story = [] @@ -55,6 +55,9 @@ class SimpleInvoice(SimpleDocTemplate): if isinstance(item, Item): self._items.append(item) + def set_item_tax_rate(self, rate): + self._item_tax_rate = rate + @property def transactions(self): return self._transactions[:] @@ -162,37 +165,65 @@ class SimpleInvoice(SimpleDocTemplate): def __build_items(self): # Items - item_data = [ - ( - item.item_id, - item.name, - Paragraph(item.description, self._defined_styles.get('TableParagraph')), - item.units, - item.unit_price, - item.vat_tax if item.vat_tax is not None else '-', - item.subtotal - ) for item in self._items if isinstance(item, Item) - ] + item_data = [] + item_subtotal = 0 + + for item in self._items: + if not isinstance(item, Item): + continue + + item_data.append( + ( + item.name, + Paragraph(item.description, self._defined_styles.get('TableParagraph')), + item.units, + item.unit_price, + item.amount + ) + ) + item_subtotal += item.amount if item_data: self._story.append( Paragraph('Detail', self._defined_styles.get('Heading1')) ) - item_data.insert(0, ('#', 'Name', 'Description', 'Units', 'Unit Price', 'Vat/Tax', 'Subtotal')) - if self.item_tax_total or self.item_total: + + item_data_title = ('Name', 'Description', 'Units', 'Unit Price', 'Amount') + item_data.insert(0, item_data_title) # Insert title + + # Summary field + sum_start_y_index = len(item_data) + sum_end_x_index = -1 - 1 + sum_start_x_index = len(item_data_title) - abs(sum_end_x_index) + style = [] + + # ##### Subtotal ##### + item_data.append( + ('Subtotal', '', '', '', item_subtotal) + ) + + style.append(('SPAN', (0, sum_start_y_index), (sum_start_x_index, sum_start_y_index))) + style.append(('ALIGN', (0, sum_start_y_index), (sum_end_x_index, -1), 'RIGHT')) + + # Tax total + if self._item_tax_rate is not None: + tax_total = item_subtotal * (Decimal(str(self._item_tax_rate)) / Decimal('100')) item_data.append( - ( - 'Total', '', '', '', '', - self.item_tax_total if self.item_tax_total else '-', - self.item_total if self.item_total else '-' - ) + ('Vat/Tax ({0}%)'.format(self._item_tax_rate), '', '', '', tax_total) ) - style = [ - ('SPAN', (0, len(item_data) - 1), (4, len(item_data) - 1)), - ('ALIGN', (0, len(item_data) - 1), (-3, -1), 'RIGHT'), - ] + sum_start_y_index += 1 + style.append(('SPAN', (0, sum_start_y_index), (sum_start_x_index, sum_start_y_index))) + style.append(('ALIGN', (0, sum_start_y_index), (sum_end_x_index, -1), 'RIGHT')) else: - style = None + tax_total = None + + # Total + total = item_subtotal + tax_total if tax_total else Decimal('0') + item_data.append(('Total', '', '', '', total)) + sum_start_y_index += 1 + style.append(('SPAN', (0, sum_start_y_index), (sum_start_x_index, sum_start_y_index))) + style.append(('ALIGN', (0, sum_start_y_index), (sum_end_x_index, -1), 'RIGHT')) + self._story.append(TableWithHeader(item_data, horizontal_align='LEFT', style=style)) def __build_transactions(self): diff --git a/simple.py b/simple.py index 733f1e3..32a75df 100644 --- a/simple.py +++ b/simple.py @@ -32,11 +32,10 @@ doc.client_info = ClientInfo( post_code='222222' ) -doc.add_item(Item('0000', 'Item', 'Item', 1, '1.1', '1.32', '0.22')) -doc.add_item(Item('1111', 'Item', 'Item', 2, '2.2', '4.4')) -doc.add_item(Item('2222', 'Item', 'Item', 3, '3.3', '9.9')) -doc.item_tax_total = Decimal('.22') -doc.item_total = Decimal('16.2') +doc.add_item(Item('Item', 'Item desc', 1, '1.1')) +doc.add_item(Item('Item', 'Item desc', 2, '2.2')) +doc.add_item(Item('Item', 'Item desc', 3, '3.3')) +doc.set_item_tax_rate(20) # 20% doc.add_transaction(Transaction('Paypal', 111, datetime.now(), 1)) doc.add_transaction(Transaction('Strip', 222, datetime.now(), 2))