PyInvoice/pyinvoice/templates.py
2015-06-06 17:31:18 +08:00

147 lines
No EOL
5.1 KiB
Python

from __future__ import unicode_literals
from datetime import datetime, date
from reportlab.lib.enums import TA_CENTER
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph
from pyinvoice.components import SimpleTable, TableWithHeader, PaidStamp
from pyinvoice.models import PDFInfo, Item, Transaction, InvoiceInfo, ServiceProviderInfo, ClientInfo
class SimpleInvoice(SimpleDocTemplate):
default_pdf_info = PDFInfo(title='Invoice', author='CiCiApp.com', subject='Invoice')
def __init__(self, invoice_path, pdf_info=None):
if not pdf_info:
pdf_info = self.default_pdf_info
SimpleDocTemplate.__init__(
self,
invoice_path,
pagesize=letter,
rightMargin=inch,
leftMargin=inch,
topMargin=inch,
bottomMargin=inch,
**pdf_info.__dict__
)
self.invoice_info = None
self.service_provider_info = None
self.client_info = None
self.is_paid = False
self._items = []
self._transactions = []
self._story = []
@property
def items(self):
return self._items[:]
def add_item(self, item):
if isinstance(item, Item):
self._items.append(item)
@property
def transactions(self):
return self._transactions[:]
def add_transaction(self, t):
if isinstance(t, Transaction):
self._transactions.append(t)
@staticmethod
def __format_value(value):
if isinstance(value, datetime):
value = value.strftime('%Y-%m-%d %H:%M')
elif isinstance(value, date):
value = value.strftime('%Y-%m-%d')
return value
def __attribute_to_table_data(self, instance, attribute_verbose_name_list):
data = []
for property_name, verbose_name in attribute_verbose_name_list:
attr = getattr(instance, property_name)
if attr:
attr = self.__format_value(attr)
data.append(['{0}:'.format(verbose_name), attr])
return data
def __build_invoice_info(self):
if isinstance(self.invoice_info, InvoiceInfo):
props = [('invoice_id', 'Invoice id'), ('invoice_datetime', 'Invoice date'),
('due_datetime', 'Invoice due date')]
self._story.append(
SimpleTable(self.__attribute_to_table_data(self.invoice_info, props), horizontal_align='LEFT')
)
def __build_service_provider_info(self):
if isinstance(self.service_provider_info, ServiceProviderInfo):
props = [('name', 'Name'), ('street', 'Street'), ('city', 'City'), ('state', 'State'),
('country', 'Country'), ('post_code', 'Post code')]
self._story.append(
SimpleTable(self.__attribute_to_table_data(self.service_provider_info, props), horizontal_align='RIGHT')
)
def __build_client_info(self):
# ClientInfo
if isinstance(self.client_info, ClientInfo):
props = [('name', 'Name'), ('street', 'Street'), ('city', 'City'), ('state', 'State'),
('country', 'Country'), ('post_code', 'Post code'), ('email', 'Email'), ('client_id', 'Client id')]
self._story.append(
SimpleTable(self.__attribute_to_table_data(self.client_info, props), horizontal_align='LEFT')
)
def __build_items(self):
# Items
item_table_paragraph_style = ParagraphStyle(
'ItemTableParagraph',
parent=getSampleStyleSheet()['Normal'],
alignment=TA_CENTER
)
item_data = [
(
item.item_id,
item.name,
Paragraph(item.description, item_table_paragraph_style),
item.units,
item.unit_price,
item.subtotal
) for item in self._items if isinstance(item, Item)
]
if item_data:
item_data.insert(0, ('Item id', 'Name', 'Description', 'Units', 'Unit Price', 'Subtotal'))
self._story.append(TableWithHeader(item_data, horizontal_align='LEFT'))
def __build_transactions(self):
# Transaction
transaction_table_data = [
(
t.transaction_id,
t.gateway,
self.__format_value(t.transaction_datetime),
t.amount
) for t in self._transactions if isinstance(t, Transaction)
]
if transaction_table_data:
transaction_table_data.insert(0, ('Transaction id', 'Gateway', 'Transaction date', 'Amount'))
self._story.append(TableWithHeader(transaction_table_data, horizontal_align='LEFT'))
def finish(self):
self._story = []
self.__build_invoice_info()
self.__build_service_provider_info()
self.__build_client_info()
self.__build_items()
self.__build_transactions()
self.build(self._story, onFirstPage=PaidStamp(7 * inch, 5.8 * inch) if self.is_paid else None)