-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
176 lines (142 loc) · 5.46 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import json
import locale
from decimal import Decimal
import click
from models.companies import Company
from models.database import Database
from models.invoices import (
CompanyInvoiceRegistry,
Invoice,
InvoiceRecord,
InvoiceRegistry,
)
from scripts.json_utils import DecimalEncoder
locale.setlocale(locale.LC_ALL, "nl_BE.UTF-8")
def validate_company(value, number_of_companies) -> int:
if int(value) < 0 or int(value) > number_of_companies - 1:
raise click.BadParameter("Company not found")
return int(value)
def validate_customer(value, raise_error) -> str:
if raise_error:
raise click.BadParameter("Customer not found in the customer list")
return value
@click.command()
def cli() -> None:
"""A CLI program that asks for input in multiple stages."""
### Load Database
filename = "./data/input.json"
with open(filename) as file:
data: dict = json.load(file)
database = Database.parse_obj(data)
### Choose Company
for i, company_enum in enumerate(database.companies):
click.echo(f"{i}. {company_enum.name}")
registry_key = click.prompt(
"Choose company you want to create an invoice for",
type=lambda x: validate_company(x, len(database.companies)),
)
company: Company = database.companies[registry_key]
### Choose Customer
for customer in company.get_active_customers():
click.echo(f"{customer.abbreviation}: {customer.name}")
customer_key = click.prompt(
"Choose customer",
type=lambda x: validate_customer(x, not company.check_if_key_in_registry(x)),
)
selected_customer = company.get_customer_by_key(customer_key)
if not selected_customer:
raise click.BadArgumentUsage("Selected customer is not found")
### Create Invoice
invoice = Invoice(customer=selected_customer, counter=company.counter)
### Select invoice number
invoice_number = click.prompt(
"Set invoice number",
default=invoice.get_default_invoice_number(company.counter),
type=str,
)
### Select invoice date
invoice_date = click.prompt(
"Set invoice date",
default=invoice.invoice_date,
type=click.DateTime(["%Y/%m/%d", "%Y-%m-%d"]),
)
### Select Period date
period = click.prompt(
"Set period", default=invoice_date.strftime("%B %Y"), type=str
)
### Iterate Service Lines
for i, service_line in enumerate(selected_customer.service_list, 1):
click.echo(
f"{i}. {service_line.description} (price: {service_line.unit_price} / {service_line.unit})"
)
input_records = []
while True:
number = click.prompt(
'Please enter the name of the service line you want to add to the invoice. Type "0" to stop adding service lines.',
type=int,
default=0,
)
chosen_service_line = selected_customer.service_list[number - 1]
if number == 0:
break
amount = click.prompt(
f"{chosen_service_line.description} (price: {chosen_service_line.unit_price} / {chosen_service_line.unit})",
type=float,
default=0,
)
amount_decimal = round(Decimal(amount), 2)
if amount:
comment = click.prompt(
"Specify extra info on the invoice line.", type=str, default=""
)
invoice_record = InvoiceRecord(
service=chosen_service_line,
amount=amount_decimal,
comment=comment,
vat=selected_customer.service_list[number - 1].vat
if selected_customer.vat_required
else 0,
)
input_records.append(invoice_record)
invoice = Invoice(
customer=selected_customer,
period=period,
counter=company.counter,
invoice_date=invoice_date,
invoice_number=invoice_number,
records=input_records,
)
### Save Invoice To File
invoice.save_to_file(
template=company.template,
template_css=company.template_css,
path=f'output/{company.name.lower()}/factuur_{invoice.invoice_date.strftime("%Y")}_{invoice.invoice_index}_{invoice.customer.abbreviation}.pdf',
)
### Increase counter only if invoice number is default
if str(company.counter) in invoice_number:
company.counter += 1
### Save Database to File
database_dict = database.dict()
with open("data/input.json", "w") as f:
json.dump(database_dict, f, cls=DecimalEncoder)
### Save Invoice To Invoice Registry
filename = "./data/output.json"
with open(filename, "r") as output_file:
output_data: dict = json.load(output_file)
if not output_data:
# Script can stop in this case
return None
invoice_registry = InvoiceRegistry.parse_obj(output_data)
# Check if company Exists
company_invoice: CompanyInvoiceRegistry | None = None
if not invoice_registry.check_if_company_exists(company=company.name):
company_invoice = CompanyInvoiceRegistry(company_name=company.name)
invoice_registry.companies.append(company_invoice)
company_invoice = invoice_registry.get_registry_by_company_name(company.name)
if company_invoice:
company_invoice.invoices.append(invoice)
invoice_registry_dict = invoice_registry.dict()
with open(filename, "w") as file:
json.dump(invoice_registry_dict, file, cls=DecimalEncoder)
if __name__ == "__main__":
cli()