auto calculate total
This commit is contained in:
parent
b13a80160d
commit
4444e709f8
3 changed files with 66 additions and 35 deletions
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue