· 5 years ago · Nov 19, 2020, 09:58 PM
1import requests
2import os
3from dataclasses import dataclass
4from typing import List
5import pathlib
6import csv
7import typer
8
9# For checking internet connection to website we're using
10url = "https://invoice-generator.com"
11timeout = 5
12# Current working directory
13currentpath = os.getcwd()
14# Folder we want to store invoices to
15invoiceFolder = "invoices"
16# Directory where we want invoices to go
17path = pathlib.Path(f"{currentpath}/{invoiceFolder}")
18# Number of invoices
19nInvoices = 0
20# Manually set attributes for the invoices
21# For my company
22# from_who = "Kelland Dairy\nLapford, Crediton\nEX17 6AG\n"
23# customNote = "Thank you for choosing Kelland Dairy!\n\nIf you need to contact us, you can email or call us.\nmilk@kellanddairy.co.uk\n01363 779134\n\nIf you want to know more about us, visit our website!\nwww.kellanddairy.co.uk"
24# ukCurrency = "GBP"
25# ourLogo = "https://www.kellanddairy.co.uk/wp-content/uploads/2018/07/Kelland-Dairy-Final-450-Logo.png"
26# bankInfo = "Payment methods: Bank Transfer, BACS, Standing order or Cheque\nSort code: 30-93-14\nAccount Number: 0556 9802"
27
28# For public show
29from_who = "Leaf Lane\nLeaf City\nLE4F C1T1\n"
30customNote = "Thank you for choosing Leaf!\n\nIf you need to contact us, you can email or call us.\nmilk@leaf.co.uk\n011111 11111\n\nIf you want to know more about us, visit our website!\nwww.leaf.co.uk"
31ukCurrency = "GBP"
32ourLogo = "https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/1f9ed517-f705-42e3-960a-9d56d8bb2f67/d7gesj7-99f809b9-6219-4e50-8a59-d1fd1b41a350.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOiIsImlzcyI6InVybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvMWY5ZWQ1MTctZjcwNS00MmUzLTk2MGEtOWQ1NmQ4YmIyZjY3XC9kN2dlc2o3LTk5ZjgwOWI5LTYyMTktNGU1MC04YTU5LWQxZmQxYjQxYTM1MC5wbmcifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6ZmlsZS5kb3dubG9hZCJdfQ.PeFz4A2VN7EPrkbSPt6cmhuhHLU4enYznwCE23GN85g"
33bankInfo = "Payment methods: Bank Transfer, BACS, Standing order or Cheque\nSort code: 01-02-03\nAccount Number: 1234 5678"
34
35
36@dataclass
37class Invoice:
38 name: str
39 # logo: str
40 date: str
41 items: List[dict]
42 # notes: str
43 # currency: str
44 # terms: str
45
46class CSVParser:
47 def __init__(self, csv_name: str) -> None:
48 # Information put into the invoice
49 self.field_names = (
50 'name',
51 # 'logo',
52 'date',
53 'items',
54 # 'terms'
55 # 'notes',
56 # 'currency'
57 )
58 self.csv_name = csv_name
59
60 def get_array_of_invoices(self) -> List[Invoice]:
61 with open(self.csv_name, 'r') as f:
62 reader = csv.DictReader(f, self.field_names)
63 header = 0
64 current_csv = []
65 for row in reader:
66 if header == 0:
67 header += 1
68 continue
69 invoice_obj = Invoice(**row)
70 invoice_obj.items = eval(invoice_obj.items)
71 current_csv.append(invoice_obj)
72 return current_csv
73
74class ApiConnector:
75 def __init__(self) -> None:
76 self.headers = {"Content-Type": "application/json"}
77 # Website that we're using to generate the PDF invoices
78 self.url = 'https://invoice-generator.com'
79 # TODO; write description
80 self.invoices_directory = f"{os.path.dirname(os.path.abspath(__file__))}/{'invoices'}"
81
82 def connect_to_api_and_save_invoice_pdf(self, invoice: Invoice) -> None:
83 invoice_parsed = {
84 'to': invoice.name,
85 'from': from_who,
86 'logo': ourLogo,
87 # 'date': invoice.date,
88 'items': invoice.items,
89 'notes': customNote,
90 'currency': ukCurrency,
91 'terms': bankInfo
92 }
93 r = requests.post(self.url, json=invoice_parsed, headers=self.headers)
94 if r.status_code == 200 or r.status_code == 201:
95 pdf = r.content
96 self.save_invoice_to_pdf(pdf, invoice)
97 # typer.echo("File Saved")
98 else:
99 typer.echo("Fail :", r.text)
100
101 def save_invoice_to_pdf(self, pdf_content: str, invoice: Invoice) -> None:
102 invoice_name = f"{invoice.name}_invoice.pdf"
103 invoice_path = f"{self.invoices_directory}/{invoice_name}"
104 with open(invoice_path, 'wb') as f:
105 typer.echo(f"[*]\t\tGenerated invoice for {invoice_name}")
106 f.write(pdf_content)
107
108# Checks internet connection
109def checkConnection():
110 try:
111 request = requests. get(url, timeout=timeout)
112 print("[*]\tInternet Connection : Estabilished")
113 return True
114 except (requests. ConnectionError, requests. Timeout) as exception:
115 print("[*]\tInternet Connection : Failed")
116 return False
117
118def createDirectory():
119 if path.exists() == False:
120 try:
121 os.mkdir(path)
122 except OSError:
123 print ("[*]\tCreation of the directory %s failed" % path)
124 else:
125 print ("[*]\tSuccessfully created the directory %s " % path)
126 else:
127 return
128 # print(f"[*]\tThere's already a directory called {invoiceFolder} that exists. I'll begin generating the invoices")
129
130def main(csv_name: str = typer.Argument('invoices.csv')):
131 print("[*]\tStarting invoice generator")
132 # Lets the user know it's running
133 if checkConnection() == False:
134 print("[*]\tInternet required to run")
135 print("[*]\tFailed to generate invoices")
136 exit()
137
138 createDirectory()
139 typer.echo(f"[*]\tGenerating invoices from : {csv_name}")
140 csv_reader = CSVParser(csv_name)
141 array_of_invoices = csv_reader.get_array_of_invoices()
142 api = ApiConnector()
143 # Number of invoices to generate from data
144 global nInvoices
145 nInvoices = len(array_of_invoices)
146 counter = 0
147 print(f"[*]\tThere are {nInvoices} invoices to generate")
148 for invoice in array_of_invoices:
149 counter += 1
150 api.connect_to_api_and_save_invoice_pdf(invoice)
151 if counter == nInvoices:
152 print("[*]\tAll invoices have been successfully generated!")
153
154 # input("[*]\tPress any key to exit")
155 print("[*]\tExited invoice generator!")
156
157# Function overload to take one invoice
158def main(invoice):
159 # print("[*]\tGenerating single invoice")
160 createDirectory()
161 api = ApiConnector()
162 try:
163 api.connect_to_api_and_save_invoice_pdf(invoice)
164 except Exception as e:
165 print(f"[*]\tUnable to save invoice\t{e}")
166 exit()
167
168
169if __name__ == "__main__":
170 typer.run(main)