1
- from typing import List , Optional , Callable
1
+ from typing import Callable , List , Optional
2
2
3
+ import datetime
3
4
import random
5
+ from datetime import date , timedelta
4
6
from pathlib import Path
5
- from tuttle .calendar import Calendar , ICSCalendar
7
+ from decimal import Decimal
8
+
6
9
import faker
7
- import random
8
- import datetime
9
- from datetime import timedelta , date
10
10
import ics
11
- from sqlmodel import Field , SQLModel , create_engine , Session , select
11
+ import numpy
12
12
import sqlalchemy
13
13
from loguru import logger
14
- import numpy
14
+ from sqlmodel import Field , Session , SQLModel , create_engine , select
15
15
16
+ from tuttle import rendering
17
+ from tuttle .calendar import Calendar , ICSCalendar
16
18
from tuttle .model import (
17
19
Address ,
18
- Contact ,
20
+ BankAccount ,
19
21
Client ,
20
- Project ,
22
+ Contact ,
21
23
Contract ,
22
- TimeUnit ,
23
24
Cycle ,
24
- User ,
25
- BankAccount ,
26
25
Invoice ,
27
26
InvoiceItem ,
28
27
Timesheet ,
29
28
TimeTrackingItem ,
29
+ Project ,
30
+ TimeUnit ,
31
+ User ,
30
32
)
31
- from tuttle import rendering
32
33
33
34
34
35
def create_fake_contact (
35
36
fake : faker .Faker ,
36
37
):
37
- try :
38
- street_line , city_line = fake .address ().splitlines ()
39
- a = Address (
40
- id = id ,
41
- street = street_line .split (" " )[0 ],
42
- number = street_line .split (" " )[1 ],
43
- city = city_line .split (" " )[1 ],
44
- postal_code = city_line .split (" " )[0 ],
45
- country = fake .country (),
46
- )
47
- first_name , last_name = fake .name ().split (" " , 1 )
48
- contact = Contact (
49
- id = id ,
50
- first_name = first_name ,
51
- last_name = last_name ,
52
- email = fake .email (),
53
- company = fake .company (),
54
- address_id = a .id ,
55
- address = a ,
56
- )
57
- return contact
58
- except Exception as ex :
59
- logger .error (ex )
60
- logger .error (f"Failed to create fake contact, trying again" )
61
- return create_fake_contact (fake )
38
+
39
+ split_address_lines = fake .address ().splitlines ()
40
+ street_line = split_address_lines [0 ]
41
+ city_line = split_address_lines [1 ]
42
+ a = Address (
43
+ street = street_line ,
44
+ number = city_line ,
45
+ city = city_line .split (" " )[1 ],
46
+ postal_code = city_line .split (" " )[0 ],
47
+ country = fake .country (),
48
+ )
49
+ first_name , last_name = fake .name ().split (" " , 1 )
50
+ contact = Contact (
51
+ first_name = first_name ,
52
+ last_name = last_name ,
53
+ email = fake .email (),
54
+ company = fake .company (),
55
+ address_id = a .id ,
56
+ address = a ,
57
+ )
58
+ return contact
62
59
63
60
64
61
def create_fake_client (
65
62
invoicing_contact : Contact ,
66
63
fake : faker .Faker ,
67
64
):
68
65
client = Client (
69
- id = id ,
70
66
name = fake .company (),
71
67
invoicing_contact = invoicing_contact ,
72
68
)
69
+ assert client .invoicing_contact is not None
73
70
return client
74
71
75
72
@@ -94,7 +91,7 @@ def create_fake_contract(
94
91
start_date = fake .date_this_year (after_today = True ),
95
92
rate = rate ,
96
93
currency = "EUR" , # TODO: Use actual currency
97
- VAT_rate = round (random .uniform (0.05 , 0.2 ), 2 ),
94
+ VAT_rate = Decimal ( round (random .uniform (0.05 , 0.2 ), 2 ) ),
98
95
unit = unit ,
99
96
units_per_workday = random .randint (1 , 12 ),
100
97
volume = fake .random_int (1 , 1000 ),
@@ -108,11 +105,12 @@ def create_fake_project(
108
105
fake : faker .Faker ,
109
106
):
110
107
project_title = fake .bs ()
108
+ project_tag = f"#{ '-' .join (project_title .split (' ' )[:2 ]).lower ()} "
109
+
111
110
project = Project (
112
111
title = project_title ,
113
- tag = "-" . join ( project_title . split ( " " )[: 2 ]). lower () ,
112
+ tag = project_tag ,
114
113
description = fake .paragraph (nb_sentences = 2 ),
115
- unique_tag = project_title .split (" " )[0 ].lower (),
116
114
is_completed = fake .pybool (),
117
115
start_date = datetime .date .today (),
118
116
end_date = datetime .date .today () + datetime .timedelta (days = 80 ),
@@ -188,7 +186,7 @@ def create_fake_invoice(
188
186
"""
189
187
invoice_number = next (invoice_number_counter )
190
188
invoice = Invoice (
191
- number = str (invoice_number ), # TODO: replace with generated number
189
+ number = str (invoice_number ),
192
190
date = datetime .date .today (),
193
191
sent = fake .pybool (),
194
192
paid = fake .pybool (),
@@ -200,6 +198,7 @@ def create_fake_invoice(
200
198
number_of_items = fake .random_int (min = 1 , max = 5 )
201
199
for _ in range (number_of_items ):
202
200
unit = fake .random_element (elements = ("hours" , "days" ))
201
+ unit_price = 0
203
202
if unit == "hours" :
204
203
unit_price = abs (round (numpy .random .normal (50 , 20 ), 2 ))
205
204
elif unit == "days" :
@@ -210,12 +209,11 @@ def create_fake_invoice(
210
209
end_date = fake .date_this_decade (),
211
210
quantity = fake .random_int (min = 1 , max = 10 ),
212
211
unit = unit ,
213
- unit_price = unit_price ,
212
+ unit_price = Decimal ( unit_price ) ,
214
213
description = fake .sentence (),
215
- VAT_rate = vat_rate ,
214
+ VAT_rate = Decimal ( vat_rate ) ,
216
215
invoice = invoice ,
217
216
)
218
- assert invoice_item .invoice == invoice
219
217
220
218
try :
221
219
rendering .render_invoice (
@@ -272,7 +270,6 @@ def create_demo_user() -> User:
272
270
phone_number = "+55555555555" ,
273
271
VAT_number = "27B-6" ,
274
272
address = Address (
275
- name = "Harry Tuttle" ,
276
273
street = "Main Street" ,
277
274
number = "450" ,
278
275
city = "Somewhere" ,
@@ -289,6 +286,14 @@ def create_demo_user() -> User:
289
286
290
287
291
288
def create_fake_calendar (project_list : List [Project ]) -> ics .Calendar :
289
+ def random_datetime (start , end ):
290
+ return start + timedelta (
291
+ seconds = random .randint (0 , int ((end - start ).total_seconds ()))
292
+ )
293
+
294
+ def random_duration ():
295
+ return timedelta (hours = random .randint (1 , 8 ))
296
+
292
297
# create a new calendar
293
298
calendar = ics .Calendar ()
294
299
@@ -303,7 +308,7 @@ def create_fake_calendar(project_list: List[Project]) -> ics.Calendar:
303
308
for _ in range (random .randint (1 , 5 )):
304
309
# create a new event
305
310
event = ics .Event ()
306
- event .name = f"Meeting for # { project .tag } "
311
+ event .name = f"Meeting for { project .tag } "
307
312
308
313
# set the event's begin and end datetime
309
314
event .begin = random_datetime (month_ago , now )
@@ -314,16 +319,6 @@ def create_fake_calendar(project_list: List[Project]) -> ics.Calendar:
314
319
return calendar
315
320
316
321
317
- def random_datetime (start , end ):
318
- return start + timedelta (
319
- seconds = random .randint (0 , int ((end - start ).total_seconds ()))
320
- )
321
-
322
-
323
- def random_duration ():
324
- return timedelta (hours = random .randint (1 , 8 ))
325
-
326
-
327
322
def install_demo_data (
328
323
n_projects : int ,
329
324
db_path : str ,
@@ -377,7 +372,3 @@ def install_demo_data(
377
372
for project in projects :
378
373
session .add (project )
379
374
session .commit ()
380
-
381
-
382
- if __name__ == "__main__" :
383
- install_demo_data (n_projects = 10 )
0 commit comments