Class to generate a pdf invoiceClass for generating PDF documentsExtract Pages from PDF based on search in pythonRetrieve TOC from PDFVB.NET - Error Handling in Generic Class for PDF MergeDecrypting PDF-FilesPython script to extract text from PDF with imagesPython3 - Determing if a PDF is scanned or “searchable”Factory pattern for creating embossing machines
Log user out after change of IP address?
What does "2 fingers to Scotland" mean in Peter Grant's statement about Johnson not listening to the SNP's Westminster leader speeches?
Double feature: Health shakes
Adding coordinate constant to file in QGIS
Employer reneged on negotiated clauses that weren't part of agreed contract, citing budget cuts - what can I do?
Tapping 3 times on one leg and 4 times on another leg in 4 beats. What is it called and how to do it?
Is Basalt Monolith a 1-card infinite combo with no payoff?
Addressable RGB strip works fine individually but cannot set all LEDs to full white
How did composers "test" their music?
Why are there cows on my spaceship?
How does Deep Packet Inspection work with encrypted packets?
How does a Spacecraft change its orbit?
What the heck is the luraic language?
Is the "Watchmen" TV series a continuation of the movie or the comics?
If I am just replacing the car engine, do I need to replace the odometer as well?
What is the equivalent of "if you say so" in German?
'Have dinner by candlelight' - preposition 'By' means 'using'?
Why do gas water heater exhausts have an air gap before the chimney?
Add new column to dataframe based on dictionary
What is the speed of "electricity"?
In what way were Renaissance battles like chess matches?
Can the Wish spell be used to allow someone to be able to cast all of their spells at will?
Would webs catch fire if Fire Bolt is used on a creature inside of them?
/etc/shadow permissions security best practice (000 vs. 600 vs. 640)
Class to generate a pdf invoice
Class for generating PDF documentsExtract Pages from PDF based on search in pythonRetrieve TOC from PDFVB.NET - Error Handling in Generic Class for PDF MergeDecrypting PDF-FilesPython script to extract text from PDF with imagesPython3 - Determing if a PDF is scanned or “searchable”Factory pattern for creating embossing machines
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
$begingroup$
I am learning to work with OOP design patterns and so I challenged myself with the idea of creating a way to generate a pdf invoice based on some information entered. So, this is what I have done so far and would like to have some review on my approach and design.
Invoice.py
import fpdf
from datetime import datetime
class Creator:
def __init__(self,first_name,last_name,email,phone_num,address,city,country):
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone_num = phone_num
self.address = address
self.city = city
self.country = country
class Organization:
def __init__(self,name,address,city,country):
self.name = name
self.address = address
self.city = city
self.country = country
class BankAccountDetail:
def __init__(self,account_name,account_num,currency,bank_name,branch,branch_addr):
self.account_name = account_name
self.account_num = account_num
self.currency = currency
self.bank_name =bank_name
self.branch = branch
self.branch_addr = branch_addr
class Project:
def __init__(self,name,description,amount):
self.name = name
self.description = description
self.amount = amount
class Invoice:
'''
Invoice class used to model a invoice object which is a composition of
1. Creator Object
2. Organization Object
3. Project Object
4. BankDetail Object
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail):
self.invoice_num = invoice_num
self.creator = creator
self.organization = organization
self.project = project
self.bankaccountdetail = bankaccountdetail
class File:
def __init__(self,filename,font_size,line_height,orientation):
self.filename = filename
self.font_size = font_size
self.line_height = line_height
self.orientation = orientation
class PdfInvoice(Invoice):
'''
Inherits from the Parent Invoice class and has an extra feature
1. File Object : Used to specify some basic details about the file
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail,file):
super().__init__(invoice_num,creator,organization,project,bankaccountdetail)
self.file = file
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf.write(self.file.line_height,"Invoice Number #")
pdf.write(self.file.line_height,self.invoice_num)
pdf.ln()
pdf.write(self.file.line_height,"Date Invoiced #")
pdf.write(self.file.line_height,str(date))
pdf.ln()
pdf.write(self.file.line_height, "Billed By #")
pdf.write(self.file.line_height,"".format(self.creator.first_name,self.creator.last_name))
pdf.ln()
pdf.write(self.file.line_height,"Address #")
pdf.write(self.file.line_height,self.creator.address)
pdf.ln()
pdf.write(self.file.line_height, "City #")
pdf.write(self.file.line_height, self.creator.city)
pdf.ln()
pdf.write(self.file.line_height,"Country #")
pdf.write(self.file.line_height,self.creator.country)
pdf.ln()
pdf.write(self.file.line_height, "Email #")
pdf.write(self.file.line_height, self.creator.email)
pdf.ln()
pdf.write(self.file.line_height, "Phone Number #")
pdf.write(self.file.line_height, self.creator.phone_num)
pdf.ln()
pdf.write(self.file.line_height,"Billed To #")
pdf.ln()
pdf.write(self.file.line_height,"Organization Name #")
pdf.write(self.file.line_height,self.organization.name)
pdf.ln()
pdf.write(self.file.line_height, "Organization Address #")
pdf.write(self.file.line_height, self.organization.address)
pdf.ln()
pdf.write(self.file.line_height, "Organization City #")
pdf.write(self.file.line_height, self.organization.city)
pdf.ln()
pdf.write(self.file.line_height, "Organization Country #")
pdf.write(self.file.line_height, self.organization.country)
pdf.ln()
pdf.write(self.file.line_height, "Comments #")
pdf.write(self.file.line_height, self.project.description)
pdf.ln()
pdf.write(self.file.line_height, "Amount #")
pdf.write(self.file.line_height,str(self.project.amount))
pdf.ln()
pdf.write(self.file.line_height,'Account details ')
pdf.ln()
pdf.write('Account Name #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_name)
pdf.ln()
pdf.write('Account Number #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_num)
pdf.ln()
pdf.write('Account Currency #')
pdf.write(self.file.line_height, self.bankaccountdetail.currency)
pdf.ln()
pdf.write('Bank Name #')
pdf.write(self.file.line_height, self.bankaccountdetail.bank_name)
pdf.ln()
pdf.write('Branch Address #')
pdf.write(self.file.line_height, self.bankaccountdetail.branch_addr)
pdf.ln()
pdf.output(self.file.filename)
creator = Creator('Test','User','test@gmail.com',
'099006789','Joans Apartment, 123 Test road','Nairobi','Kenya')
organization = Organization('Test Org','Ndemi Road Kilimani', 'Nairobi','Kenya')
bank_detail = BankAccountDetail('Test User','999999678','KES',
'Test Bank','Kenya','BRANCH Way, ABC Place')
file = File("Invoice.pdf",12,5,"letter")
project = Project('Ecommerce site','Worked on the ecommerce site',10.900)
pdf_inv = PdfInvoice('1393939',creator,organization,project,bank_detail,file)
pdf_inv.generate_pdf()

python python-3.x object-oriented pdf
$endgroup$
add a comment
|
$begingroup$
I am learning to work with OOP design patterns and so I challenged myself with the idea of creating a way to generate a pdf invoice based on some information entered. So, this is what I have done so far and would like to have some review on my approach and design.
Invoice.py
import fpdf
from datetime import datetime
class Creator:
def __init__(self,first_name,last_name,email,phone_num,address,city,country):
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone_num = phone_num
self.address = address
self.city = city
self.country = country
class Organization:
def __init__(self,name,address,city,country):
self.name = name
self.address = address
self.city = city
self.country = country
class BankAccountDetail:
def __init__(self,account_name,account_num,currency,bank_name,branch,branch_addr):
self.account_name = account_name
self.account_num = account_num
self.currency = currency
self.bank_name =bank_name
self.branch = branch
self.branch_addr = branch_addr
class Project:
def __init__(self,name,description,amount):
self.name = name
self.description = description
self.amount = amount
class Invoice:
'''
Invoice class used to model a invoice object which is a composition of
1. Creator Object
2. Organization Object
3. Project Object
4. BankDetail Object
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail):
self.invoice_num = invoice_num
self.creator = creator
self.organization = organization
self.project = project
self.bankaccountdetail = bankaccountdetail
class File:
def __init__(self,filename,font_size,line_height,orientation):
self.filename = filename
self.font_size = font_size
self.line_height = line_height
self.orientation = orientation
class PdfInvoice(Invoice):
'''
Inherits from the Parent Invoice class and has an extra feature
1. File Object : Used to specify some basic details about the file
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail,file):
super().__init__(invoice_num,creator,organization,project,bankaccountdetail)
self.file = file
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf.write(self.file.line_height,"Invoice Number #")
pdf.write(self.file.line_height,self.invoice_num)
pdf.ln()
pdf.write(self.file.line_height,"Date Invoiced #")
pdf.write(self.file.line_height,str(date))
pdf.ln()
pdf.write(self.file.line_height, "Billed By #")
pdf.write(self.file.line_height,"".format(self.creator.first_name,self.creator.last_name))
pdf.ln()
pdf.write(self.file.line_height,"Address #")
pdf.write(self.file.line_height,self.creator.address)
pdf.ln()
pdf.write(self.file.line_height, "City #")
pdf.write(self.file.line_height, self.creator.city)
pdf.ln()
pdf.write(self.file.line_height,"Country #")
pdf.write(self.file.line_height,self.creator.country)
pdf.ln()
pdf.write(self.file.line_height, "Email #")
pdf.write(self.file.line_height, self.creator.email)
pdf.ln()
pdf.write(self.file.line_height, "Phone Number #")
pdf.write(self.file.line_height, self.creator.phone_num)
pdf.ln()
pdf.write(self.file.line_height,"Billed To #")
pdf.ln()
pdf.write(self.file.line_height,"Organization Name #")
pdf.write(self.file.line_height,self.organization.name)
pdf.ln()
pdf.write(self.file.line_height, "Organization Address #")
pdf.write(self.file.line_height, self.organization.address)
pdf.ln()
pdf.write(self.file.line_height, "Organization City #")
pdf.write(self.file.line_height, self.organization.city)
pdf.ln()
pdf.write(self.file.line_height, "Organization Country #")
pdf.write(self.file.line_height, self.organization.country)
pdf.ln()
pdf.write(self.file.line_height, "Comments #")
pdf.write(self.file.line_height, self.project.description)
pdf.ln()
pdf.write(self.file.line_height, "Amount #")
pdf.write(self.file.line_height,str(self.project.amount))
pdf.ln()
pdf.write(self.file.line_height,'Account details ')
pdf.ln()
pdf.write('Account Name #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_name)
pdf.ln()
pdf.write('Account Number #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_num)
pdf.ln()
pdf.write('Account Currency #')
pdf.write(self.file.line_height, self.bankaccountdetail.currency)
pdf.ln()
pdf.write('Bank Name #')
pdf.write(self.file.line_height, self.bankaccountdetail.bank_name)
pdf.ln()
pdf.write('Branch Address #')
pdf.write(self.file.line_height, self.bankaccountdetail.branch_addr)
pdf.ln()
pdf.output(self.file.filename)
creator = Creator('Test','User','test@gmail.com',
'099006789','Joans Apartment, 123 Test road','Nairobi','Kenya')
organization = Organization('Test Org','Ndemi Road Kilimani', 'Nairobi','Kenya')
bank_detail = BankAccountDetail('Test User','999999678','KES',
'Test Bank','Kenya','BRANCH Way, ABC Place')
file = File("Invoice.pdf",12,5,"letter")
project = Project('Ecommerce site','Worked on the ecommerce site',10.900)
pdf_inv = PdfInvoice('1393939',creator,organization,project,bank_detail,file)
pdf_inv.generate_pdf()

python python-3.x object-oriented pdf
$endgroup$
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
1
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21
add a comment
|
$begingroup$
I am learning to work with OOP design patterns and so I challenged myself with the idea of creating a way to generate a pdf invoice based on some information entered. So, this is what I have done so far and would like to have some review on my approach and design.
Invoice.py
import fpdf
from datetime import datetime
class Creator:
def __init__(self,first_name,last_name,email,phone_num,address,city,country):
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone_num = phone_num
self.address = address
self.city = city
self.country = country
class Organization:
def __init__(self,name,address,city,country):
self.name = name
self.address = address
self.city = city
self.country = country
class BankAccountDetail:
def __init__(self,account_name,account_num,currency,bank_name,branch,branch_addr):
self.account_name = account_name
self.account_num = account_num
self.currency = currency
self.bank_name =bank_name
self.branch = branch
self.branch_addr = branch_addr
class Project:
def __init__(self,name,description,amount):
self.name = name
self.description = description
self.amount = amount
class Invoice:
'''
Invoice class used to model a invoice object which is a composition of
1. Creator Object
2. Organization Object
3. Project Object
4. BankDetail Object
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail):
self.invoice_num = invoice_num
self.creator = creator
self.organization = organization
self.project = project
self.bankaccountdetail = bankaccountdetail
class File:
def __init__(self,filename,font_size,line_height,orientation):
self.filename = filename
self.font_size = font_size
self.line_height = line_height
self.orientation = orientation
class PdfInvoice(Invoice):
'''
Inherits from the Parent Invoice class and has an extra feature
1. File Object : Used to specify some basic details about the file
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail,file):
super().__init__(invoice_num,creator,organization,project,bankaccountdetail)
self.file = file
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf.write(self.file.line_height,"Invoice Number #")
pdf.write(self.file.line_height,self.invoice_num)
pdf.ln()
pdf.write(self.file.line_height,"Date Invoiced #")
pdf.write(self.file.line_height,str(date))
pdf.ln()
pdf.write(self.file.line_height, "Billed By #")
pdf.write(self.file.line_height,"".format(self.creator.first_name,self.creator.last_name))
pdf.ln()
pdf.write(self.file.line_height,"Address #")
pdf.write(self.file.line_height,self.creator.address)
pdf.ln()
pdf.write(self.file.line_height, "City #")
pdf.write(self.file.line_height, self.creator.city)
pdf.ln()
pdf.write(self.file.line_height,"Country #")
pdf.write(self.file.line_height,self.creator.country)
pdf.ln()
pdf.write(self.file.line_height, "Email #")
pdf.write(self.file.line_height, self.creator.email)
pdf.ln()
pdf.write(self.file.line_height, "Phone Number #")
pdf.write(self.file.line_height, self.creator.phone_num)
pdf.ln()
pdf.write(self.file.line_height,"Billed To #")
pdf.ln()
pdf.write(self.file.line_height,"Organization Name #")
pdf.write(self.file.line_height,self.organization.name)
pdf.ln()
pdf.write(self.file.line_height, "Organization Address #")
pdf.write(self.file.line_height, self.organization.address)
pdf.ln()
pdf.write(self.file.line_height, "Organization City #")
pdf.write(self.file.line_height, self.organization.city)
pdf.ln()
pdf.write(self.file.line_height, "Organization Country #")
pdf.write(self.file.line_height, self.organization.country)
pdf.ln()
pdf.write(self.file.line_height, "Comments #")
pdf.write(self.file.line_height, self.project.description)
pdf.ln()
pdf.write(self.file.line_height, "Amount #")
pdf.write(self.file.line_height,str(self.project.amount))
pdf.ln()
pdf.write(self.file.line_height,'Account details ')
pdf.ln()
pdf.write('Account Name #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_name)
pdf.ln()
pdf.write('Account Number #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_num)
pdf.ln()
pdf.write('Account Currency #')
pdf.write(self.file.line_height, self.bankaccountdetail.currency)
pdf.ln()
pdf.write('Bank Name #')
pdf.write(self.file.line_height, self.bankaccountdetail.bank_name)
pdf.ln()
pdf.write('Branch Address #')
pdf.write(self.file.line_height, self.bankaccountdetail.branch_addr)
pdf.ln()
pdf.output(self.file.filename)
creator = Creator('Test','User','test@gmail.com',
'099006789','Joans Apartment, 123 Test road','Nairobi','Kenya')
organization = Organization('Test Org','Ndemi Road Kilimani', 'Nairobi','Kenya')
bank_detail = BankAccountDetail('Test User','999999678','KES',
'Test Bank','Kenya','BRANCH Way, ABC Place')
file = File("Invoice.pdf",12,5,"letter")
project = Project('Ecommerce site','Worked on the ecommerce site',10.900)
pdf_inv = PdfInvoice('1393939',creator,organization,project,bank_detail,file)
pdf_inv.generate_pdf()

python python-3.x object-oriented pdf
$endgroup$
I am learning to work with OOP design patterns and so I challenged myself with the idea of creating a way to generate a pdf invoice based on some information entered. So, this is what I have done so far and would like to have some review on my approach and design.
Invoice.py
import fpdf
from datetime import datetime
class Creator:
def __init__(self,first_name,last_name,email,phone_num,address,city,country):
self.first_name = first_name
self.last_name = last_name
self.email = email
self.phone_num = phone_num
self.address = address
self.city = city
self.country = country
class Organization:
def __init__(self,name,address,city,country):
self.name = name
self.address = address
self.city = city
self.country = country
class BankAccountDetail:
def __init__(self,account_name,account_num,currency,bank_name,branch,branch_addr):
self.account_name = account_name
self.account_num = account_num
self.currency = currency
self.bank_name =bank_name
self.branch = branch
self.branch_addr = branch_addr
class Project:
def __init__(self,name,description,amount):
self.name = name
self.description = description
self.amount = amount
class Invoice:
'''
Invoice class used to model a invoice object which is a composition of
1. Creator Object
2. Organization Object
3. Project Object
4. BankDetail Object
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail):
self.invoice_num = invoice_num
self.creator = creator
self.organization = organization
self.project = project
self.bankaccountdetail = bankaccountdetail
class File:
def __init__(self,filename,font_size,line_height,orientation):
self.filename = filename
self.font_size = font_size
self.line_height = line_height
self.orientation = orientation
class PdfInvoice(Invoice):
'''
Inherits from the Parent Invoice class and has an extra feature
1. File Object : Used to specify some basic details about the file
'''
def __init__(self,invoice_num,creator,organization,project,bankaccountdetail,file):
super().__init__(invoice_num,creator,organization,project,bankaccountdetail)
self.file = file
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf.write(self.file.line_height,"Invoice Number #")
pdf.write(self.file.line_height,self.invoice_num)
pdf.ln()
pdf.write(self.file.line_height,"Date Invoiced #")
pdf.write(self.file.line_height,str(date))
pdf.ln()
pdf.write(self.file.line_height, "Billed By #")
pdf.write(self.file.line_height,"".format(self.creator.first_name,self.creator.last_name))
pdf.ln()
pdf.write(self.file.line_height,"Address #")
pdf.write(self.file.line_height,self.creator.address)
pdf.ln()
pdf.write(self.file.line_height, "City #")
pdf.write(self.file.line_height, self.creator.city)
pdf.ln()
pdf.write(self.file.line_height,"Country #")
pdf.write(self.file.line_height,self.creator.country)
pdf.ln()
pdf.write(self.file.line_height, "Email #")
pdf.write(self.file.line_height, self.creator.email)
pdf.ln()
pdf.write(self.file.line_height, "Phone Number #")
pdf.write(self.file.line_height, self.creator.phone_num)
pdf.ln()
pdf.write(self.file.line_height,"Billed To #")
pdf.ln()
pdf.write(self.file.line_height,"Organization Name #")
pdf.write(self.file.line_height,self.organization.name)
pdf.ln()
pdf.write(self.file.line_height, "Organization Address #")
pdf.write(self.file.line_height, self.organization.address)
pdf.ln()
pdf.write(self.file.line_height, "Organization City #")
pdf.write(self.file.line_height, self.organization.city)
pdf.ln()
pdf.write(self.file.line_height, "Organization Country #")
pdf.write(self.file.line_height, self.organization.country)
pdf.ln()
pdf.write(self.file.line_height, "Comments #")
pdf.write(self.file.line_height, self.project.description)
pdf.ln()
pdf.write(self.file.line_height, "Amount #")
pdf.write(self.file.line_height,str(self.project.amount))
pdf.ln()
pdf.write(self.file.line_height,'Account details ')
pdf.ln()
pdf.write('Account Name #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_name)
pdf.ln()
pdf.write('Account Number #')
pdf.write(self.file.line_height,self.bankaccountdetail.account_num)
pdf.ln()
pdf.write('Account Currency #')
pdf.write(self.file.line_height, self.bankaccountdetail.currency)
pdf.ln()
pdf.write('Bank Name #')
pdf.write(self.file.line_height, self.bankaccountdetail.bank_name)
pdf.ln()
pdf.write('Branch Address #')
pdf.write(self.file.line_height, self.bankaccountdetail.branch_addr)
pdf.ln()
pdf.output(self.file.filename)
creator = Creator('Test','User','test@gmail.com',
'099006789','Joans Apartment, 123 Test road','Nairobi','Kenya')
organization = Organization('Test Org','Ndemi Road Kilimani', 'Nairobi','Kenya')
bank_detail = BankAccountDetail('Test User','999999678','KES',
'Test Bank','Kenya','BRANCH Way, ABC Place')
file = File("Invoice.pdf",12,5,"letter")
project = Project('Ecommerce site','Worked on the ecommerce site',10.900)
pdf_inv = PdfInvoice('1393939',creator,organization,project,bank_detail,file)
pdf_inv.generate_pdf()

python python-3.x object-oriented pdf
python python-3.x object-oriented pdf
edited Jun 14 at 22:21
Sᴀᴍ Onᴇᴌᴀ
14.3k6 gold badges26 silver badges97 bronze badges
14.3k6 gold badges26 silver badges97 bronze badges
asked Jun 14 at 13:34
AnastaciaAnastacia
334 bronze badges
334 bronze badges
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
1
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21
add a comment
|
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
1
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
1
1
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21
add a comment
|
2 Answers
2
active
oldest
votes
$begingroup$
Data classes
Since you are using the classes as immutable data containers, it would be possible to significantly cut down the amount of code you have to write to create all of them using namedtuple from the collections module:
from collections import namedtuple
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
Organization = namedtuple("Organination", ["name", "address", "city", "country"])
BankAccountDetail = namedtuple("BankAccountDetail", ["account_name", "account_num",
"currency", "bank_name", "branch", "branch_addr"])
Project = namedtuple("Project", ["name", "description", "amount"])
File = namedtuple("File", ["filename", "font_size", "line_height", "orientation"])
dataclasses might also be used to get a similar result.
Code duplication
There is a massive amount of duplicate code in generate_pdf. You could layout the document using a list and string formatting and then iterate over that list to finally write it to a file. Let me give you a sketch of what I mean (Note: the code below is untested):
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf_content = [
f"Invoice Number #self.invoice_num",
f"Date Invoiced #date",
# and so on and so forth
]
for line in pdf_content:
pdf.write(self.file.line_height, line)
pdf.ln()
pdf.output(self.file.filename)
The code uses f-string, which are available since Python 3.6. If you are using an older version of Python you will have to use .format instead such as you do in several places already.
There might be even better ways to do this, but I have no specific knowledge about that special library.
Misc
It might be a good idea to have a look at the official Style Guide for Python Code (often just called PEP8) for short. It's a collection of style recommendations and other paradigms that allow you to write compelling and visually appealing Python code.
file in file = File("Invoice.pdf", 12, 5, "letter") is not a good variable name since you overwrite Python's file command with this. At least append a _ to make it file_ or choose another name altogether.
Maybe it would also be worth to have a look at if __name__ == "__main__": to separate the "library part" from the example code.
from datetime import datetime
from collections import namedtuple
import fpdf
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
# all the other code ...
if __name__ == "__main__":
creator = Creator('Test', 'User', 'test@gmail.com', '099006789',
'Joans Apartment, 123 Test road', 'Nairobi', 'Kenya')
organization = Organization('Test Org', 'Ndemi Road Kilimani', 'Nairobi',
'Kenya')
bank_detail = BankAccountDetail('Test User', '999999678', 'KES', 'Test Bank',
'Kenya', 'BRANCH Way, ABC Place')
file = File("Invoice.pdf", 12, 5, "letter")
project = Project('Ecommerce site', 'Worked on the ecommerce site', 10.900)
pdf_inv = PdfInvoice('1393939', creator, organization, project, bank_detail,
file)
pdf_inv.generate_pdf()
$endgroup$
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
add a comment
|
$begingroup$
Might want to look at LaTex. It's a lot less code and it IS possible to add comments in, so it's definetly possible to use it as both a template and a way to generate a pdf!
$endgroup$
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222285%2fclass-to-generate-a-pdf-invoice%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Data classes
Since you are using the classes as immutable data containers, it would be possible to significantly cut down the amount of code you have to write to create all of them using namedtuple from the collections module:
from collections import namedtuple
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
Organization = namedtuple("Organination", ["name", "address", "city", "country"])
BankAccountDetail = namedtuple("BankAccountDetail", ["account_name", "account_num",
"currency", "bank_name", "branch", "branch_addr"])
Project = namedtuple("Project", ["name", "description", "amount"])
File = namedtuple("File", ["filename", "font_size", "line_height", "orientation"])
dataclasses might also be used to get a similar result.
Code duplication
There is a massive amount of duplicate code in generate_pdf. You could layout the document using a list and string formatting and then iterate over that list to finally write it to a file. Let me give you a sketch of what I mean (Note: the code below is untested):
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf_content = [
f"Invoice Number #self.invoice_num",
f"Date Invoiced #date",
# and so on and so forth
]
for line in pdf_content:
pdf.write(self.file.line_height, line)
pdf.ln()
pdf.output(self.file.filename)
The code uses f-string, which are available since Python 3.6. If you are using an older version of Python you will have to use .format instead such as you do in several places already.
There might be even better ways to do this, but I have no specific knowledge about that special library.
Misc
It might be a good idea to have a look at the official Style Guide for Python Code (often just called PEP8) for short. It's a collection of style recommendations and other paradigms that allow you to write compelling and visually appealing Python code.
file in file = File("Invoice.pdf", 12, 5, "letter") is not a good variable name since you overwrite Python's file command with this. At least append a _ to make it file_ or choose another name altogether.
Maybe it would also be worth to have a look at if __name__ == "__main__": to separate the "library part" from the example code.
from datetime import datetime
from collections import namedtuple
import fpdf
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
# all the other code ...
if __name__ == "__main__":
creator = Creator('Test', 'User', 'test@gmail.com', '099006789',
'Joans Apartment, 123 Test road', 'Nairobi', 'Kenya')
organization = Organization('Test Org', 'Ndemi Road Kilimani', 'Nairobi',
'Kenya')
bank_detail = BankAccountDetail('Test User', '999999678', 'KES', 'Test Bank',
'Kenya', 'BRANCH Way, ABC Place')
file = File("Invoice.pdf", 12, 5, "letter")
project = Project('Ecommerce site', 'Worked on the ecommerce site', 10.900)
pdf_inv = PdfInvoice('1393939', creator, organization, project, bank_detail,
file)
pdf_inv.generate_pdf()
$endgroup$
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
add a comment
|
$begingroup$
Data classes
Since you are using the classes as immutable data containers, it would be possible to significantly cut down the amount of code you have to write to create all of them using namedtuple from the collections module:
from collections import namedtuple
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
Organization = namedtuple("Organination", ["name", "address", "city", "country"])
BankAccountDetail = namedtuple("BankAccountDetail", ["account_name", "account_num",
"currency", "bank_name", "branch", "branch_addr"])
Project = namedtuple("Project", ["name", "description", "amount"])
File = namedtuple("File", ["filename", "font_size", "line_height", "orientation"])
dataclasses might also be used to get a similar result.
Code duplication
There is a massive amount of duplicate code in generate_pdf. You could layout the document using a list and string formatting and then iterate over that list to finally write it to a file. Let me give you a sketch of what I mean (Note: the code below is untested):
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf_content = [
f"Invoice Number #self.invoice_num",
f"Date Invoiced #date",
# and so on and so forth
]
for line in pdf_content:
pdf.write(self.file.line_height, line)
pdf.ln()
pdf.output(self.file.filename)
The code uses f-string, which are available since Python 3.6. If you are using an older version of Python you will have to use .format instead such as you do in several places already.
There might be even better ways to do this, but I have no specific knowledge about that special library.
Misc
It might be a good idea to have a look at the official Style Guide for Python Code (often just called PEP8) for short. It's a collection of style recommendations and other paradigms that allow you to write compelling and visually appealing Python code.
file in file = File("Invoice.pdf", 12, 5, "letter") is not a good variable name since you overwrite Python's file command with this. At least append a _ to make it file_ or choose another name altogether.
Maybe it would also be worth to have a look at if __name__ == "__main__": to separate the "library part" from the example code.
from datetime import datetime
from collections import namedtuple
import fpdf
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
# all the other code ...
if __name__ == "__main__":
creator = Creator('Test', 'User', 'test@gmail.com', '099006789',
'Joans Apartment, 123 Test road', 'Nairobi', 'Kenya')
organization = Organization('Test Org', 'Ndemi Road Kilimani', 'Nairobi',
'Kenya')
bank_detail = BankAccountDetail('Test User', '999999678', 'KES', 'Test Bank',
'Kenya', 'BRANCH Way, ABC Place')
file = File("Invoice.pdf", 12, 5, "letter")
project = Project('Ecommerce site', 'Worked on the ecommerce site', 10.900)
pdf_inv = PdfInvoice('1393939', creator, organization, project, bank_detail,
file)
pdf_inv.generate_pdf()
$endgroup$
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
add a comment
|
$begingroup$
Data classes
Since you are using the classes as immutable data containers, it would be possible to significantly cut down the amount of code you have to write to create all of them using namedtuple from the collections module:
from collections import namedtuple
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
Organization = namedtuple("Organination", ["name", "address", "city", "country"])
BankAccountDetail = namedtuple("BankAccountDetail", ["account_name", "account_num",
"currency", "bank_name", "branch", "branch_addr"])
Project = namedtuple("Project", ["name", "description", "amount"])
File = namedtuple("File", ["filename", "font_size", "line_height", "orientation"])
dataclasses might also be used to get a similar result.
Code duplication
There is a massive amount of duplicate code in generate_pdf. You could layout the document using a list and string formatting and then iterate over that list to finally write it to a file. Let me give you a sketch of what I mean (Note: the code below is untested):
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf_content = [
f"Invoice Number #self.invoice_num",
f"Date Invoiced #date",
# and so on and so forth
]
for line in pdf_content:
pdf.write(self.file.line_height, line)
pdf.ln()
pdf.output(self.file.filename)
The code uses f-string, which are available since Python 3.6. If you are using an older version of Python you will have to use .format instead such as you do in several places already.
There might be even better ways to do this, but I have no specific knowledge about that special library.
Misc
It might be a good idea to have a look at the official Style Guide for Python Code (often just called PEP8) for short. It's a collection of style recommendations and other paradigms that allow you to write compelling and visually appealing Python code.
file in file = File("Invoice.pdf", 12, 5, "letter") is not a good variable name since you overwrite Python's file command with this. At least append a _ to make it file_ or choose another name altogether.
Maybe it would also be worth to have a look at if __name__ == "__main__": to separate the "library part" from the example code.
from datetime import datetime
from collections import namedtuple
import fpdf
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
# all the other code ...
if __name__ == "__main__":
creator = Creator('Test', 'User', 'test@gmail.com', '099006789',
'Joans Apartment, 123 Test road', 'Nairobi', 'Kenya')
organization = Organization('Test Org', 'Ndemi Road Kilimani', 'Nairobi',
'Kenya')
bank_detail = BankAccountDetail('Test User', '999999678', 'KES', 'Test Bank',
'Kenya', 'BRANCH Way, ABC Place')
file = File("Invoice.pdf", 12, 5, "letter")
project = Project('Ecommerce site', 'Worked on the ecommerce site', 10.900)
pdf_inv = PdfInvoice('1393939', creator, organization, project, bank_detail,
file)
pdf_inv.generate_pdf()
$endgroup$
Data classes
Since you are using the classes as immutable data containers, it would be possible to significantly cut down the amount of code you have to write to create all of them using namedtuple from the collections module:
from collections import namedtuple
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
Organization = namedtuple("Organination", ["name", "address", "city", "country"])
BankAccountDetail = namedtuple("BankAccountDetail", ["account_name", "account_num",
"currency", "bank_name", "branch", "branch_addr"])
Project = namedtuple("Project", ["name", "description", "amount"])
File = namedtuple("File", ["filename", "font_size", "line_height", "orientation"])
dataclasses might also be used to get a similar result.
Code duplication
There is a massive amount of duplicate code in generate_pdf. You could layout the document using a list and string formatting and then iterate over that list to finally write it to a file. Let me give you a sketch of what I mean (Note: the code below is untested):
def generate_pdf(self):
dt = datetime.now()
date = dt.date()
pdf = fpdf.FPDF(format=self.file.orientation)
pdf.add_page()
pdf.set_font("Arial", size=self.file.font_size)
pdf_content = [
f"Invoice Number #self.invoice_num",
f"Date Invoiced #date",
# and so on and so forth
]
for line in pdf_content:
pdf.write(self.file.line_height, line)
pdf.ln()
pdf.output(self.file.filename)
The code uses f-string, which are available since Python 3.6. If you are using an older version of Python you will have to use .format instead such as you do in several places already.
There might be even better ways to do this, but I have no specific knowledge about that special library.
Misc
It might be a good idea to have a look at the official Style Guide for Python Code (often just called PEP8) for short. It's a collection of style recommendations and other paradigms that allow you to write compelling and visually appealing Python code.
file in file = File("Invoice.pdf", 12, 5, "letter") is not a good variable name since you overwrite Python's file command with this. At least append a _ to make it file_ or choose another name altogether.
Maybe it would also be worth to have a look at if __name__ == "__main__": to separate the "library part" from the example code.
from datetime import datetime
from collections import namedtuple
import fpdf
Creator = namedtuple("Creator", ["first_name", "last_name", "email", "phone_num",
"address", "city", "country"])
# all the other code ...
if __name__ == "__main__":
creator = Creator('Test', 'User', 'test@gmail.com', '099006789',
'Joans Apartment, 123 Test road', 'Nairobi', 'Kenya')
organization = Organization('Test Org', 'Ndemi Road Kilimani', 'Nairobi',
'Kenya')
bank_detail = BankAccountDetail('Test User', '999999678', 'KES', 'Test Bank',
'Kenya', 'BRANCH Way, ABC Place')
file = File("Invoice.pdf", 12, 5, "letter")
project = Project('Ecommerce site', 'Worked on the ecommerce site', 10.900)
pdf_inv = PdfInvoice('1393939', creator, organization, project, bank_detail,
file)
pdf_inv.generate_pdf()
edited Jun 14 at 16:15
answered Jun 14 at 15:46
AlexVAlexV
4,9152 gold badges12 silver badges38 bronze badges
4,9152 gold badges12 silver badges38 bronze badges
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
add a comment
|
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
$begingroup$
@AlexV- This is so helpful. I really appreciate it.
$endgroup$
– Anastacia
Jun 14 at 20:53
add a comment
|
$begingroup$
Might want to look at LaTex. It's a lot less code and it IS possible to add comments in, so it's definetly possible to use it as both a template and a way to generate a pdf!
$endgroup$
add a comment
|
$begingroup$
Might want to look at LaTex. It's a lot less code and it IS possible to add comments in, so it's definetly possible to use it as both a template and a way to generate a pdf!
$endgroup$
add a comment
|
$begingroup$
Might want to look at LaTex. It's a lot less code and it IS possible to add comments in, so it's definetly possible to use it as both a template and a way to generate a pdf!
$endgroup$
Might want to look at LaTex. It's a lot less code and it IS possible to add comments in, so it's definetly possible to use it as both a template and a way to generate a pdf!
answered Jun 14 at 21:43
KoshVorlonKoshVorlon
785 bronze badges
785 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f222285%2fclass-to-generate-a-pdf-invoice%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
$begingroup$
Welcome to Code Review! Is this supposed to work in Python 2 or Python 3? Please add the according tag to your question.
$endgroup$
– AlexV
Jun 14 at 14:03
$begingroup$
@AlexV:- Thank you. I have added the tag.
$endgroup$
– Anastacia
Jun 14 at 14:18
1
$begingroup$
Rendering text onto the PDF using one statement per string is quite tedious. Consider using a higher-level library or templating language such as ReportLab.
$endgroup$
– 200_success
Jun 14 at 18:09
$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 5 → 4
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
Jun 14 at 22:21