# Renewed populate_db.py: fills all models with relations and validation import os import django import random from faker import Faker from decimal import Decimal from datetime import datetime, timedelta from django.core.exceptions import ValidationError from django.utils import timezone os.environ.setdefault("DJANGO_SETTINGS_MODULE", "trznice.settings") django.setup() from booking.models import Square, Event, MarketSlot, Reservation from account.models import CustomUser from product.models import Product, EventProduct from commerce.models import Order from servicedesk.models import ServiceTicket fake = Faker("cs_CZ") def create_users(n=10): roles = ['admin', 'seller', 'squareManager', 'cityClerk', 'checker', None] account_types = ['company', 'individual'] users = [] for _ in range(n): first_name = fake.first_name() last_name = fake.last_name() role = random.choice(roles) email = fake.unique.email() prefix = random.choice(["601", "602", "603", "604", "605", "606", "607", "608", "720", "721", "722", "723", "724", "725", "730", "731", "732", "733", "734", "735", "736", "737", "738", "739"]) phone_number = "+420" + prefix + ''.join([str(random.randint(0, 9)) for _ in range(6)]) ico = fake.unique.msisdn()[0:8] rc = f"{fake.random_int(100000, 999999)}/{fake.random_int(100, 9999)}" psc = fake.postcode().replace(" ", "")[:5] bank_prefix = f"{random.randint(0, 999999)}-" if random.random() > 0.5 else "" bank_number = f"{random.randint(1000000000, 9999999999)}/0100" bank_account = f"{bank_prefix}{bank_number}" user = CustomUser( first_name=first_name, last_name=last_name, email=email, role=role, account_type=random.choice(account_types), phone_number=phone_number, ICO=ico, RC=rc, city=fake.city(), street=fake.street_name() + " " + str(fake.building_number()), PSC=psc, GDPR=True, email_verified=random.choice([True, False]), bank_account=bank_account, is_active=True, ) user.username = user.generate_login(first_name, last_name) user.set_password("password123") user.full_clean() user.save() users.append(user) print(f"✅ Vytvořeno {len(users)} uživatelů") return users def create_squares(n=3): squares = [] for _ in range(n): sq = Square( name=fake.city() + " náměstí", description=fake.text(max_nb_chars=200), street=fake.street_name(), city=fake.city(), psc=int(fake.postcode().replace(" ", "")), width=random.randint(20, 50), height=random.randint(20, 50), grid_rows=random.randint(40, 60), grid_cols=random.randint(40, 60), cellsize=10, ) sq.full_clean() sq.save() squares.append(sq) print(f"✅ Vytvořeno {len(squares)} náměstí") return squares def create_events(squares, n=7): events = [] attempts = 0 while len(events) < n and attempts < n * 5: sq = random.choice(squares) start = datetime.now() + timedelta(days=random.randint(1, 60)) end = start + timedelta(days=random.randint(1, 5)) overlap = Event.objects.filter(square=sq, start__lt=end, end__gt=start).exists() if overlap: attempts += 1 continue try: event = Event( name=fake.catch_phrase(), description=fake.text(max_nb_chars=300), square=sq, start=start, end=end, price_per_m2=Decimal(f"{random.randint(10, 100)}.00") ) event.full_clean() event.save() events.append(event) except ValidationError as e: continue print(f"✅ Vytvořeno {len(events)} eventů") return events def create_products(n=10): products = [] for _ in range(n): name = fake.word().capitalize() + " " + fake.word().capitalize() code = random.randint(10000, 99999) product = Product(name=name, code=code) product.full_clean() product.save() products.append(product) print(f"✅ Vytvořeno {len(products)} produktů") return products def create_event_products(events, products, n=15): event_products = [] for _ in range(n): product = random.choice(products) event = random.choice(events) start = event.start + timedelta(days=random.randint(0, 1)) end = min(event.end, start + timedelta(days=random.randint(1, 3))) # Ensure timezone-aware datetimes if timezone.is_naive(start): start = timezone.make_aware(start) if timezone.is_naive(end): end = timezone.make_aware(end) if timezone.is_naive(event.start): event_start = timezone.make_aware(event.start) else: event_start = event.start if timezone.is_naive(event.end): event_end = timezone.make_aware(event.end) else: event_end = event.end # Ensure end is not after event_end and start is not before event_start if start < event_start: start = event_start if end > event_end: end = event_end ep = EventProduct( product=product, event=event, start_selling_date=start, end_selling_date=end ) try: ep.full_clean() ep.save() event_products.append(ep) except ValidationError as e: print(f"❌ EventProduct error: {e}") continue print(f"✅ Vytvořeno {len(event_products)} event produktů") return event_products def create_market_slots(events, max_slots=8): slots = [] for event in events: count = random.randint(3, max_slots) for _ in range(count): slot = MarketSlot( event=event, status=random.choice(["allowed", "blocked"]), base_size=round(random.uniform(2, 10), 2), available_extension=round(random.uniform(0, 5), 2), x=random.randint(0, 30), y=random.randint(0, 30), width=random.randint(2, 10), height=random.randint(2, 10), price_per_m2=Decimal(f"{random.randint(10, 100)}.00") ) slot.full_clean() slot.save() # Check fields and relations assert slot.event == event assert slot.status in ["allowed", "blocked"] assert isinstance(slot.base_size, float) or isinstance(slot.base_size, Decimal) assert isinstance(slot.price_per_m2, Decimal) slots.append(slot) print(f"✅ Vytvořeno {len(slots)} prodejních míst") return slots def create_reservations(users, slots, event_products, max_per_user=2): reservations = [] for user in users: max_res_for_user = min(max_per_user, 5) user_slots = random.sample(slots, k=min(len(slots), max_res_for_user)) for slot in user_slots: event = slot.event event_start = event.start event_end = event.end if timezone.is_naive(event_start): event_start = timezone.make_aware(event_start) if timezone.is_naive(event_end): event_end = timezone.make_aware(event_end) allowed_durations = [1, 7, 30] duration_days = random.choice(allowed_durations) max_start = event_end - timedelta(days=duration_days) if max_start <= event_start: continue start = event_start + timedelta(seconds=random.randint(0, int((max_start - event_start).total_seconds()))) end = start + timedelta(days=duration_days) if timezone.is_naive(start): start = timezone.make_aware(start) if timezone.is_naive(end): end = timezone.make_aware(end) used_extension = round(random.uniform(0, slot.available_extension), 2) base_size = Decimal(str(slot.base_size)) price_per_m2 = slot.price_per_m2 final_price = (price_per_m2 * (base_size + Decimal(str(used_extension))) * Decimal(duration_days)).quantize(Decimal("0.01")) price = final_price # <-- set price field as well if final_price >= Decimal("1000000.00"): continue if user.user_reservations.count() >= 5: break try: res = Reservation( event=event, market_slot=slot, user=user, used_extension=used_extension, reserved_from=start, reserved_to=end, status="reserved", final_price=final_price, price=price, ) res.full_clean() res.save() # Check fields and relations assert res.event == event assert res.market_slot == slot assert res.user == user assert res.status == "reserved" # Add event_products to reservation if event_products: chosen_eps = random.sample(event_products, k=min(len(event_products), random.randint(0, 2))) res.event_products.add(*chosen_eps) reservations.append(res) except ValidationError: continue print(f"✅ Vytvořeno {len(reservations)} rezervací") return reservations def create_orders(users, reservations): orders = [] for res in reservations: user = res.user order = Order( user=user, reservation=res, status=random.choice(["payed", "pending", "cancelled"]), price_to_pay=res.final_price, note=fake.sentence(), ) try: order.full_clean() order.save() # Check fields and relations assert order.user == user assert order.reservation == res assert order.status in ["payed", "pending", "cancelled"] orders.append(order) except ValidationError: continue print(f"✅ Vytvořeno {len(orders)} objednávek") return orders def create_service_tickets(users, n=10): tickets = [] for _ in range(n): user = random.choice(users) ticket = ServiceTicket( title=fake.sentence(nb_words=6), description=fake.text(max_nb_chars=200), user=user, status=random.choice(["new", "in_progress", "resolved", "closed"]), category=random.choice(["tech", "reservation", "payment", "account", "content", "suggestion", "other"]), ) try: ticket.full_clean() ticket.save() tickets.append(ticket) except ValidationError: continue print(f"✅ Vytvořeno {len(tickets)} servisních tiketů") return tickets if __name__ == "__main__": users = create_users(10) squares = create_squares(3) events = create_events(squares, 7) products = create_products(10) event_products = create_event_products(events, products, 15) slots = create_market_slots(events, max_slots=8) reservations = create_reservations(users, slots, event_products, max_per_user=2) orders = create_orders(users, reservations) tickets = create_service_tickets(users, 10) print("🎉 Naplnění databáze dokončeno.")