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 __future__ import unicode_literals
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
|
||||||
class PDFInfo(object):
|
class PDFInfo(object):
|
||||||
|
@ -55,22 +56,22 @@ class Item(object):
|
||||||
"""
|
"""
|
||||||
Product/Item information
|
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
|
Item modal init
|
||||||
:param item_id: Order id or Item id
|
|
||||||
:param name: Item name
|
:param name: Item name
|
||||||
:param units: Amount
|
:param units: Amount
|
||||||
:param unit_price: Unit price
|
:param unit_price: Unit price
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
self.item_id = item_id
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
self.units = units
|
self.units = units
|
||||||
self.unit_price = unit_price
|
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):
|
class Transaction(object):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
from decimal import Decimal
|
||||||
from reportlab.lib import colors
|
from reportlab.lib import colors
|
||||||
from reportlab.lib.enums import TA_CENTER, TA_RIGHT
|
from reportlab.lib.enums import TA_CENTER, TA_RIGHT
|
||||||
from reportlab.lib.pagesizes import letter
|
from reportlab.lib.pagesizes import letter
|
||||||
|
@ -42,8 +43,7 @@ class SimpleInvoice(SimpleDocTemplate):
|
||||||
self.client_info = None
|
self.client_info = None
|
||||||
self.is_paid = False
|
self.is_paid = False
|
||||||
self._items = []
|
self._items = []
|
||||||
self.item_tax_total = None
|
self._item_tax_rate = None
|
||||||
self.item_total = None
|
|
||||||
self._transactions = []
|
self._transactions = []
|
||||||
self._story = []
|
self._story = []
|
||||||
|
|
||||||
|
@ -55,6 +55,9 @@ class SimpleInvoice(SimpleDocTemplate):
|
||||||
if isinstance(item, Item):
|
if isinstance(item, Item):
|
||||||
self._items.append(item)
|
self._items.append(item)
|
||||||
|
|
||||||
|
def set_item_tax_rate(self, rate):
|
||||||
|
self._item_tax_rate = rate
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def transactions(self):
|
def transactions(self):
|
||||||
return self._transactions[:]
|
return self._transactions[:]
|
||||||
|
@ -162,37 +165,65 @@ class SimpleInvoice(SimpleDocTemplate):
|
||||||
|
|
||||||
def __build_items(self):
|
def __build_items(self):
|
||||||
# Items
|
# Items
|
||||||
item_data = [
|
item_data = []
|
||||||
(
|
item_subtotal = 0
|
||||||
item.item_id,
|
|
||||||
item.name,
|
for item in self._items:
|
||||||
Paragraph(item.description, self._defined_styles.get('TableParagraph')),
|
if not isinstance(item, Item):
|
||||||
item.units,
|
continue
|
||||||
item.unit_price,
|
|
||||||
item.vat_tax if item.vat_tax is not None else '-',
|
item_data.append(
|
||||||
item.subtotal
|
(
|
||||||
) for item in self._items if isinstance(item, Item)
|
item.name,
|
||||||
]
|
Paragraph(item.description, self._defined_styles.get('TableParagraph')),
|
||||||
|
item.units,
|
||||||
|
item.unit_price,
|
||||||
|
item.amount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
item_subtotal += item.amount
|
||||||
|
|
||||||
if item_data:
|
if item_data:
|
||||||
self._story.append(
|
self._story.append(
|
||||||
Paragraph('Detail', self._defined_styles.get('Heading1'))
|
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(
|
item_data.append(
|
||||||
(
|
('Vat/Tax ({0}%)'.format(self._item_tax_rate), '', '', '', tax_total)
|
||||||
'Total', '', '', '', '',
|
|
||||||
self.item_tax_total if self.item_tax_total else '-',
|
|
||||||
self.item_total if self.item_total else '-'
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
style = [
|
sum_start_y_index += 1
|
||||||
('SPAN', (0, len(item_data) - 1), (4, len(item_data) - 1)),
|
style.append(('SPAN', (0, sum_start_y_index), (sum_start_x_index, sum_start_y_index)))
|
||||||
('ALIGN', (0, len(item_data) - 1), (-3, -1), 'RIGHT'),
|
style.append(('ALIGN', (0, sum_start_y_index), (sum_end_x_index, -1), 'RIGHT'))
|
||||||
]
|
|
||||||
else:
|
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))
|
self._story.append(TableWithHeader(item_data, horizontal_align='LEFT', style=style))
|
||||||
|
|
||||||
def __build_transactions(self):
|
def __build_transactions(self):
|
||||||
|
|
|
@ -32,11 +32,10 @@ doc.client_info = ClientInfo(
|
||||||
post_code='222222'
|
post_code='222222'
|
||||||
)
|
)
|
||||||
|
|
||||||
doc.add_item(Item('0000', 'Item', 'Item', 1, '1.1', '1.32', '0.22'))
|
doc.add_item(Item('Item', 'Item desc', 1, '1.1'))
|
||||||
doc.add_item(Item('1111', 'Item', 'Item', 2, '2.2', '4.4'))
|
doc.add_item(Item('Item', 'Item desc', 2, '2.2'))
|
||||||
doc.add_item(Item('2222', 'Item', 'Item', 3, '3.3', '9.9'))
|
doc.add_item(Item('Item', 'Item desc', 3, '3.3'))
|
||||||
doc.item_tax_total = Decimal('.22')
|
doc.set_item_tax_rate(20) # 20%
|
||||||
doc.item_total = Decimal('16.2')
|
|
||||||
|
|
||||||
doc.add_transaction(Transaction('Paypal', 111, datetime.now(), 1))
|
doc.add_transaction(Transaction('Paypal', 111, datetime.now(), 1))
|
||||||
doc.add_transaction(Transaction('Strip', 222, datetime.now(), 2))
|
doc.add_transaction(Transaction('Strip', 222, datetime.now(), 2))
|
||||||
|
|
Loading…
Reference in a new issue