hospital-management/ebt_data_generator.py
2025-08-12 13:33:25 +03:00

1385 lines
57 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'airport_management.settings')
django.setup()
import random
import uuid
from decimal import Decimal
from datetime import date, datetime, timedelta
from django.utils import timezone
from django.db import models
from django.contrib.auth.models import User
from ebt.models import *
def create_users():
"""Create user accounts for the system"""
users = []
# Create admin user if it doesn't exist
admin_username = 'admin'
if not User.objects.filter(username=admin_username).exists():
admin_user = User.objects.create_superuser(
username=admin_username,
email='admin@example.com',
password='adminpassword',
first_name='System',
last_name='Administrator'
)
users.append(admin_user)
# Create staff users for different roles
staff_data = [
{'username': 'manager1', 'email': 'manager1@example.com', 'password': 'managerpassword',
'first_name': 'Abdullah', 'last_name': 'Al-Otaibi', 'is_staff': True},
{'username': 'supervisor1', 'email': 'supervisor1@example.com', 'password': 'supervisorpassword',
'first_name': 'Mohammed', 'last_name': 'Al-Ghamdi', 'is_staff': True},
{'username': 'agent1', 'email': 'agent1@example.com', 'password': 'agentpassword',
'first_name': 'Fatima', 'last_name': 'Al-Qahtani', 'is_staff': False},
{'username': 'agent2', 'email': 'agent2@example.com', 'password': 'agentpassword',
'first_name': 'Ali', 'last_name': 'Al-Harbi', 'is_staff': False},
{'username': 'agent3', 'email': 'agent3@example.com', 'password': 'agentpassword',
'first_name': 'Nora', 'last_name': 'Al-Shammari', 'is_staff': False},
{'username': 'auditor1', 'email': 'auditor1@example.com', 'password': 'auditorpassword',
'first_name': 'Khalid', 'last_name': 'Al-Dossari', 'is_staff': True},
{'username': 'finance1', 'email': 'finance1@example.com', 'password': 'financepassword',
'first_name': 'Sara', 'last_name': 'Al-Zahrani', 'is_staff': True},
]
for data in staff_data:
username = data['username']
if not User.objects.filter(username=username).exists():
user = User.objects.create_user(
username=username,
email=data['email'],
password=data['password'],
first_name=data['first_name'],
last_name=data['last_name'],
is_staff=data['is_staff']
)
users.append(user)
return users
def create_cashiers(users, airports):
"""Create cashier records for users"""
cashiers = []
# Get list of valid users that aren't already cashiers
existing_cashier_users = Cashier.objects.values_list('user_id', flat=True)
available_users = [u for u in users if u.id not in existing_cashier_users]
if not available_users:
print("No available users to create cashiers")
return cashiers
# Create a cashier for each airport with multiple users where possible
for airport in airports:
# Create between 2 and 5 cashiers per airport, depending on available users
num_cashiers = min(random.randint(2, 5), len(available_users))
for _ in range(num_cashiers):
if not available_users:
break
# Pick a random user and remove from available list
user = random.choice(available_users)
available_users.remove(user)
# Generate employee ID based on user and airport
employee_id = f"{airport.code}-{random.randint(1000, 9999)}"
# Create cashier
cashier,_ = Cashier.objects.get_or_create(
user=user,
employee_id=employee_id,
airport=airport,
is_active=True,
created_at=timezone.now()
)
cashiers.append(cashier)
return cashiers
def create_cash_shifts(cashiers, num_shifts=100):
"""Create cash shift records for cashiers"""
shifts = []
# Start date (14 days ago)
start_date = timezone.now() - timedelta(days=14)
# For each cashier, create a number of shifts
for cashier in cashiers:
# Random number of shifts per cashier over the period
cashier_shifts = random.randint(3, 10)
for shift_idx in range(cashier_shifts):
# Create shift date/time - distribute over the period
shift_day = random.randint(0, 13) # 0 to 13 days ago
shift_date = start_date + timedelta(days=shift_day)
# Set shift time (morning, afternoon, or night)
shift_type = random.choice(['morning', 'afternoon', 'night'])
if shift_type == 'morning':
shift_hour = random.randint(6, 9)
elif shift_type == 'afternoon':
shift_hour = random.randint(12, 15)
else: # night
shift_hour = random.randint(18, 21)
shift_minute = random.choice([0, 15, 30, 45])
# Set shift start time
shift_start = shift_date.replace(hour=shift_hour, minute=shift_minute, second=0, microsecond=0)
# Set shift duration (between 6 and 8 hours)
shift_duration_hours = random.uniform(6, 8)
# Set shift end time for closed shifts
if shift_start < timezone.now() - timedelta(hours=9):
# Shift is in the past and should be closed
shift_end = shift_start + timedelta(hours=shift_duration_hours)
status = 'closed'
else:
# Recent or current shift might still be open
if shift_start > timezone.now():
# Future shift
shift_end = None
status = 'pending'
elif shift_start + timedelta(hours=shift_duration_hours) < timezone.now():
# Past shift but might not be closed
if random.random() < 0.9: # 90% are closed properly
shift_end = shift_start + timedelta(hours=shift_duration_hours)
status = 'closed'
else:
shift_end = None
status = 'open' # Open shift that should be closed
else:
# Currently open shift
shift_end = None
status = 'open'
# Set opening cash (typically between 1000-2000 SAR)
opening_cash = Decimal(str(random.randint(1000, 2000)))
# Set closing cash for closed shifts
if status == 'closed':
# Closing should roughly match opening plus cash sales, but with some variance
# We'll set initial values and update them later based on actual transactions
closing_cash = opening_cash + Decimal(str(random.randint(0, 2000)))
else:
closing_cash = None
# Create shift
shift, _ = CashShift.objects.get_or_create(
cashier=cashier,
shift_start=shift_start,
shift_end=shift_end,
opening_cash=opening_cash,
closing_cash=closing_cash,
total_sales=Decimal('0.00'), # Will be updated later
cash_sales=Decimal('0.00'), # Will be updated later
pos_sales=Decimal('0.00'), # Will be updated later
status=status,
notes=f"Auto-generated {shift_type} shift" if random.random() < 0.3 else "",
created_at=shift_start
)
shifts.append(shift)
return shifts
def create_ticket_inventory(airlines, airports):
"""Create ticket inventory records"""
inventory_records = []
# Create ticket inventories for the last 12 months
today = date.today()
# Create ticket inventory for each airline at each airport
for airline in airlines:
for airport in airports:
# Create between 1 and 3 inventory records per airline per airport
num_inventories = random.randint(1, 3)
for _ in range(num_inventories):
# Determine inventory date (within last 12 months)
months_ago = random.randint(0, 11)
receive_date = today - timedelta(days=30 * months_ago)
# Set expiry date (6-12 months after received)
expiry_months = random.randint(6, 12)
expiry_date = receive_date + timedelta(days=30 * expiry_months)
# Generate EMD serial ranges
serial_prefix = f"{airline.code}{airport.code}"
serial_start_num = random.randint(100000, 999000)
# Create inventory quantity (typically 1000-5000 tickets)
quantity = random.randint(1000, 5000)
serial_end_num = serial_start_num + quantity - 1
emd_serial_start = f"{serial_prefix}{serial_start_num}"
emd_serial_end = f"{serial_prefix}{serial_end_num}"
# Determine usage (varies based on how old the inventory is)
usage_factor = min(0.9, months_ago / 12) # Older inventory has higher usage
usage_factor = max(0.1, usage_factor) # Even new inventory has some usage
# Add randomness to usage factor
usage_factor = usage_factor * random.uniform(0.8, 1.2)
usage_factor = min(0.95, usage_factor) # Cap at 95% usage
quantity_used = int(quantity * usage_factor)
quantity_remaining = quantity - quantity_used
# Determine status based on remaining quantity
if quantity_remaining <= 0:
status = 'depleted'
elif quantity_remaining < quantity * 0.1:
status = 'low'
elif expiry_date < today:
status = 'expired'
else:
status = 'active'
# Create inventory record
inventory, _ = TicketInventory.objects.get_or_create(
airline=airline,
airport=airport,
emd_serial_start=emd_serial_start,
emd_serial_end=emd_serial_end,
quantity_received=quantity,
quantity_used=quantity_used,
quantity_remaining=quantity_remaining,
status=status,
received_date=receive_date,
expiry_date=expiry_date,
notes=f"Batch {serial_start_num}" if random.random() < 0.3 else ""
)
inventory_records.append(inventory)
return inventory_records
def create_pos_devices(airports):
"""Create POS devices for airports"""
devices = []
# Create multiple POS devices for each airport
for airport in airports:
# Number of devices per airport (larger airports have more)
airport_size = len(airport.name) # Simple heuristic based on name length
num_devices = random.randint(2, max(3, airport_size // 3))
for i in range(num_devices):
# Generate device ID
device_id = f"POS-{airport.code}-{i + 1:02d}"
# Generate serial number
serial_number = f"M{random.randint(1000000, 9999999)}"
# Assign to terminal
terminal = random.choice(['T1', 'T2', 'T3', 'Main', 'Domestic', 'International'])
# Set location within terminal
locations = [
f"Check-in counter {random.randint(1, 50)}",
f"Gate {random.choice('ABCDEFG')}-{random.randint(1, 30)}",
f"EBT counter {random.randint(1, 10)}",
f"Customer service desk {random.randint(1, 5)}",
f"Airline office {random.randint(1, 15)}"
]
location = random.choice(locations)
# Set status (mostly active)
status_weights = {'active': 0.85, 'maintenance': 0.1, 'inactive': 0.05}
status = random.choices(
list(status_weights.keys()),
weights=list(status_weights.values()),
k=1
)[0]
# Set last reconciliation date for active devices
if status == 'active':
days_ago = random.randint(0, 7) # Last 7 days
last_reconciliation = timezone.now() - timedelta(days=days_ago)
else:
last_reconciliation = None
# Create device
device, _ = POSDevice.objects.get_or_create(
device_id=device_id,
serial_number=serial_number,
airport=airport,
terminal=terminal,
location=location,
status=status,
last_reconciliation=last_reconciliation,
created_at=timezone.now() - timedelta(days=random.randint(30, 365)), # Created 1-12 months ago
updated_at=timezone.now() - timedelta(days=random.randint(0, 30)) # Updated within last month
)
devices.append(device)
return devices
def create_airlines():
"""Create airline records"""
airlines = []
# Create airlines
airline_data = [
{'code': 'SV', 'name': 'Saudia', 'contact_email': 'contact@saudia.com'},
{'code': 'XY', 'name': 'flynas', 'contact_email': 'contact@flynas.com'},
{'code': 'F3', 'name': 'flyadeal', 'contact_email': 'contact@flyadeal.com'},
{'code': 'EK', 'name': 'Emirates', 'contact_email': 'contact@emirates.com'},
{'code': 'EY', 'name': 'Etihad Airways', 'contact_email': 'contact@etihad.ae'},
{'code': 'QR', 'name': 'Qatar Airways', 'contact_email': 'contact@qatarairways.com'},
{'code': 'GF', 'name': 'Gulf Air', 'contact_email': 'contact@gulfair.com'},
{'code': 'KU', 'name': 'Kuwait Airways', 'contact_email': 'contact@kuwaitairways.com'},
{'code': 'ME', 'name': 'Middle East Airlines', 'contact_email': 'contact@mea.com.lb'},
{'code': 'RJ', 'name': 'Royal Jordanian', 'contact_email': 'contact@rj.com'},
{'code': 'TK', 'name': 'Turkish Airlines', 'contact_email': 'contact@thy.com'},
{'code': 'BA', 'name': 'British Airways', 'contact_email': 'contact@ba.com'},
{'code': 'LH', 'name': 'Lufthansa', 'contact_email': 'contact@lufthansa.com'},
{'code': 'AF', 'name': 'Air France', 'contact_email': 'contact@airfrance.fr'},
{'code': 'MS', 'name': 'Egyptair', 'contact_email': 'contact@egyptair.com'},
]
for data in airline_data:
# Skip if airline already exists
if Airline.objects.filter(code=data['code']).exists():
airline = Airline.objects.get(code=data['code'])
else:
airline, _ = Airline.objects.get_or_create(
code=data['code'],
name=data['name'],
contact_email=data['contact_email'],
is_active=True,
created_at=timezone.now(),
updated_at=timezone.now()
)
airlines.append(airline)
return airlines
def create_airports():
"""Create airport records"""
airports = []
# Create airports
airport_data = [
{'code': 'RUH', 'name': 'King Khalid International Airport', 'city': 'Riyadh', 'country': 'Saudi Arabia'},
{'code': 'JED', 'name': 'King Abdulaziz International Airport', 'city': 'Jeddah', 'country': 'Saudi Arabia'},
{'code': 'DMM', 'name': 'King Fahd International Airport', 'city': 'Dammam', 'country': 'Saudi Arabia'},
{'code': 'MED', 'name': 'Prince Mohammed Bin Abdulaziz Airport', 'city': 'Medina', 'country': 'Saudi Arabia'},
{'code': 'TIF', 'name': 'Taif Regional Airport', 'city': 'Taif', 'country': 'Saudi Arabia'},
{'code': 'AHB', 'name': 'Abha International Airport', 'city': 'Abha', 'country': 'Saudi Arabia'},
{'code': 'GIZ', 'name': 'Jizan Airport', 'city': 'Jizan', 'country': 'Saudi Arabia'},
{'code': 'TUU', 'name': 'Tabuk Airport', 'city': 'Tabuk', 'country': 'Saudi Arabia'},
{'code': 'YNB', 'name': 'Yanbu Airport', 'city': 'Yanbu', 'country': 'Saudi Arabia'},
{'code': 'ELQ', 'name': 'Gassim Airport', 'city': 'Gassim', 'country': 'Saudi Arabia'},
{'code': 'DXB', 'name': 'Dubai International Airport', 'city': 'Dubai', 'country': 'United Arab Emirates'},
{'code': 'AUH', 'name': 'Abu Dhabi International Airport', 'city': 'Abu Dhabi',
'country': 'United Arab Emirates'},
{'code': 'DOH', 'name': 'Hamad International Airport', 'city': 'Doha', 'country': 'Qatar'},
{'code': 'BAH', 'name': 'Bahrain International Airport', 'city': 'Manama', 'country': 'Bahrain'},
{'code': 'KWI', 'name': 'Kuwait International Airport', 'city': 'Kuwait City', 'country': 'Kuwait'},
{'code': 'CAI', 'name': 'Cairo International Airport', 'city': 'Cairo', 'country': 'Egypt'},
{'code': 'AMM', 'name': 'Queen Alia International Airport', 'city': 'Amman', 'country': 'Jordan'},
{'code': 'BEY', 'name': 'BeirutRafic Hariri International Airport', 'city': 'Beirut', 'country': 'Lebanon'},
{'code': 'IST', 'name': 'Istanbul Airport', 'city': 'Istanbul', 'country': 'Turkey'},
{'code': 'LHR', 'name': 'Heathrow Airport', 'city': 'London', 'country': 'United Kingdom'},
{'code': 'CDG', 'name': 'Charles de Gaulle Airport', 'city': 'Paris', 'country': 'France'},
{'code': 'FRA', 'name': 'Frankfurt Airport', 'city': 'Frankfurt', 'country': 'Germany'},
{'code': 'FCO', 'name': 'Leonardo da VinciFiumicino Airport', 'city': 'Rome', 'country': 'Italy'},
]
for data in airport_data:
# Skip if airport already exists
if Airport.objects.filter(code=data['code']).exists():
airport = Airport.objects.get(code=data['code'])
else:
airport, _ = Airport.objects.get_or_create(
code=data['code'],
name=data['name'],
city=data['city'],
state='',
country=data['country'],
latitude=Decimal('0.0'),
longitude=Decimal('0.0'),
elevation_m=Decimal('0.0'),
is_active=True,
created_at=timezone.now()
)
airports.append(airport)
return airports
def create_flights(airlines, airports, num_flights=100):
"""Create flight data"""
flights = []
# Get common aircraft types
aircraft_types = {
'SV': ['Boeing 777-300ER', 'Boeing 787-9', 'Airbus A320-200', 'Airbus A330-300'],
'XY': ['Airbus A320neo', 'Airbus A320-200'],
'F3': ['Airbus A320-200'],
'EK': ['Boeing 777-300ER', 'Airbus A380-800', 'Boeing 777-200LR'],
'EY': ['Boeing 787-9', 'Boeing 777-300ER', 'Airbus A320-200'],
'QR': ['Boeing 777-300ER', 'Airbus A350-900', 'Boeing 787-8'],
'default': ['Boeing 737-800', 'Airbus A320-200', 'Boeing 777-200', 'Airbus A330-200']
}
# Flight durations between popular routes (in minutes)
route_durations = {
('RUH', 'JED'): 105,
('JED', 'RUH'): 110,
('RUH', 'DMM'): 70,
('DMM', 'RUH'): 75,
('JED', 'DMM'): 120,
('DMM', 'JED'): 125,
('RUH', 'DXB'): 105,
('DXB', 'RUH'): 110,
('JED', 'CAI'): 120,
('CAI', 'JED'): 125,
('RUH', 'CAI'): 180,
('CAI', 'RUH'): 185,
('RUH', 'DOH'): 75,
('DOH', 'RUH'): 80,
('JED', 'IST'): 240,
('IST', 'JED'): 245,
('default', 'default'): 120
}
# Common domestic routes in Saudi Arabia
domestic_routes = [
('RUH', 'JED'), ('JED', 'RUH'),
('RUH', 'DMM'), ('DMM', 'RUH'),
('JED', 'DMM'), ('DMM', 'JED'),
('RUH', 'MED'), ('MED', 'RUH'),
('JED', 'MED'), ('MED', 'JED'),
('RUH', 'AHB'), ('AHB', 'RUH'),
('JED', 'GIZ'), ('GIZ', 'JED'),
('RUH', 'TUU'), ('TUU', 'RUH'),
('RUH', 'TIF'), ('TIF', 'RUH'),
('JED', 'TIF'), ('TIF', 'JED'),
('RUH', 'ELQ'), ('ELQ', 'RUH'),
('RUH', 'YNB'), ('YNB', 'RUH'),
]
# Common international routes from Saudi Arabia
international_routes = [
('RUH', 'DXB'), ('DXB', 'RUH'),
('JED', 'DXB'), ('DXB', 'JED'),
('RUH', 'DOH'), ('DOH', 'RUH'),
('JED', 'DOH'), ('DOH', 'JED'),
('RUH', 'AUH'), ('AUH', 'RUH'),
('JED', 'CAI'), ('CAI', 'JED'),
('RUH', 'CAI'), ('CAI', 'RUH'),
('JED', 'AMM'), ('AMM', 'JED'),
('RUH', 'BAH'), ('BAH', 'RUH'),
('JED', 'IST'), ('IST', 'JED'),
('RUH', 'IST'), ('IST', 'RUH'),
('JED', 'KWI'), ('KWI', 'JED'),
('RUH', 'BEY'), ('BEY', 'RUH'),
('JED', 'LHR'), ('LHR', 'JED'),
('RUH', 'CDG'), ('CDG', 'RUH'),
]
# Get all Saudi airports
saudi_airports = [airport for airport in airports if airport.country == 'Saudi Arabia']
# Flight numbers for airlines
flight_number_ranges = {
'SV': (1000, 1999),
'XY': (100, 999),
'F3': (100, 999),
'EK': (800, 899),
'EY': (600, 699),
'QR': (1200, 1299),
'GF': (500, 599),
'KU': (100, 199),
'ME': (400, 499),
'MS': (600, 699),
'RJ': (300, 399),
'TK': (100, 199),
'default': (1000, 9999)
}
# Start date for flight schedules (7 days ago)
start_date = timezone.now() - timedelta(days=7)
# Create flights for the next 30 days
for day_offset in range(0, 30):
current_date = start_date + timedelta(days=day_offset)
# Create more flights for busier days (weekends)
is_weekend = current_date.weekday() >= 4 # Friday and Saturday in Middle East
daily_flights = int(num_flights / 20) * (2 if is_weekend else 1)
for _ in range(daily_flights):
# Select airline (with more weight to Saudi airlines)
airline_weights = [3 if a.code in ['SV', 'XY', 'F3'] else 1 for a in airlines]
airline = random.choices(airlines, weights=airline_weights, k=1)[0]
# Determine if domestic or international flight
is_domestic = random.random() < 0.6 if airline.code in ['SV', 'XY', 'F3'] else 0.1
# Select route
if is_domestic:
# Domestic route
if random.random() < 0.8 and domestic_routes:
origin_code, dest_code = random.choice(domestic_routes)
else:
# Random domestic route
if len(saudi_airports) >= 2:
origin, dest = random.sample(saudi_airports, 2)
origin_code, dest_code = origin.code, dest.code
else:
# Fallback if not enough Saudi airports
route = random.choice(domestic_routes or international_routes)
origin_code, dest_code = route
else:
# International route
if random.random() < 0.8 and international_routes:
origin_code, dest_code = random.choice(international_routes)
else:
# Random international route
saudi_airport = random.choice(saudi_airports)
international_airport = random.choice([a for a in airports if a.country != 'Saudi Arabia'])
if random.random() < 0.5:
origin_code, dest_code = saudi_airport.code, international_airport.code
else:
origin_code, dest_code = international_airport.code, saudi_airport.code
# Find the airport objects
origin_airport = next((a for a in airports if a.code == origin_code), None)
dest_airport = next((a for a in airports if a.code == dest_code), None)
if not origin_airport or not dest_airport:
continue
# Generate flight number
range_min, range_max = flight_number_ranges.get(airline.code, flight_number_ranges['default'])
flight_number = str(random.randint(range_min, range_max))
# Generate departure time
hour = random.randint(0, 23)
minute = random.choice([0, 15, 30, 45])
scheduled_departure = current_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
# Calculate flight duration and arrival time
route_key = (origin_code, dest_code)
default_key = ('default', 'default')
duration_minutes = route_durations.get(route_key, route_durations.get(default_key, 120))
# Add some randomness to duration
duration_minutes += random.randint(-10, 20)
scheduled_arrival = scheduled_departure + timedelta(minutes=duration_minutes)
# Determine flight type
flight_type = 'domestic' if is_domestic else 'international'
# Determine flight status based on departure time
now = timezone.now()
actual_departure = None
actual_arrival = None
if scheduled_departure > now + timedelta(hours=1):
status = 'scheduled'
elif scheduled_departure > now:
status = 'boarding'
elif scheduled_arrival > now:
status = 'departed'
# Set actual departure time
delay_minutes = random.choices(
[0, random.randint(1, 15), random.randint(16, 60), random.randint(61, 180)],
weights=[0.7, 0.15, 0.1, 0.05],
k=1
)[0]
actual_departure = scheduled_departure + timedelta(minutes=delay_minutes)
else:
status = 'arrived'
# Set actual departure and arrival times
delay_minutes = random.choices(
[0, random.randint(1, 15), random.randint(16, 60), random.randint(61, 180)],
weights=[0.7, 0.15, 0.1, 0.05],
k=1
)[0]
actual_departure = scheduled_departure + timedelta(minutes=delay_minutes)
# Actual arrival might be faster or slower than scheduled
arrival_variance = random.randint(-15, 30)
actual_flight_duration = duration_minutes + arrival_variance
actual_arrival = actual_departure + timedelta(minutes=actual_flight_duration)
# Randomly cancel some flights
if random.random() < 0.03: # 3% chance of cancellation
status = 'cancelled'
actual_departure = None
actual_arrival = None
# Set delays for some flights
if random.random() < 0.15 and status == 'scheduled': # 15% chance of delay
status = 'delayed'
# Determine aircraft type
aircraft_types_for_airline = aircraft_types.get(airline.code, aircraft_types['default'])
aircraft_type = random.choice(aircraft_types_for_airline)
# Generate aircraft registration
if airline.code == 'SV':
registration = f"HZ-A{random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ')}{random.randint(10, 99)}"
else:
country_codes = {'EK': 'A6-', 'EY': 'A6-', 'QR': 'A7-', 'GF': 'A9C-', 'KU': '9K-'}
prefix = country_codes.get(airline.code, random.choice(['N', 'G-', 'F-', 'D-', 'C-', 'B-', 'VH-']))
registration = f"{prefix}{random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ')}{random.randint(100, 999)}"
# Set passenger capacity based on aircraft type
if 'A380' in aircraft_type:
passenger_capacity = random.randint(480, 615)
elif '777-300' in aircraft_type:
passenger_capacity = random.randint(340, 420)
elif '777-200' in aircraft_type:
passenger_capacity = random.randint(280, 350)
elif '787' in aircraft_type:
passenger_capacity = random.randint(240, 330)
elif 'A350' in aircraft_type:
passenger_capacity = random.randint(300, 370)
elif 'A330' in aircraft_type:
passenger_capacity = random.randint(250, 330)
elif '737' in aircraft_type or 'A320' in aircraft_type:
passenger_capacity = random.randint(150, 200)
else:
passenger_capacity = random.randint(100, 350)
# Set cargo capacity
if 'A380' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(40000, 60000)))
elif '777' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(20000, 35000)))
elif '787' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(15000, 25000)))
elif 'A350' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(18000, 28000)))
elif 'A330' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(15000, 25000)))
elif '737' in aircraft_type or 'A320' in aircraft_type:
cargo_capacity_kg = Decimal(str(random.randint(5000, 10000)))
else:
cargo_capacity_kg = Decimal(str(random.randint(3000, 20000)))
# Set terminal and gate information
departure_terminal = random.choice(['1', '2', '3', '4', 'A', 'B', 'C', 'D', 'International', 'Domestic'])
departure_gate = f"{random.choice('ABCDEFG')}{random.randint(1, 50)}"
arrival_terminal = random.choice(['1', '2', '3', '4', 'A', 'B', 'C', 'D', 'International', 'Domestic'])
arrival_gate = f"{random.choice('ABCDEFG')}{random.randint(1, 50)}"
# Create the flight
flight, _ = Flight.objects.get_or_create(
flight_number=flight_number,
airline=airline,
origin_airport=origin_airport,
destination_airport=dest_airport,
scheduled_departure=scheduled_departure,
scheduled_arrival=scheduled_arrival,
actual_departure=actual_departure,
actual_arrival=actual_arrival,
aircraft_type=aircraft_type,
aircraft_registration=registration,
flight_type=flight_type,
status=status,
passenger_capacity=passenger_capacity,
cargo_capacity_kg=cargo_capacity_kg,
departure_terminal=departure_terminal,
departure_gate=departure_gate,
arrival_terminal=arrival_terminal,
arrival_gate=arrival_gate,
notes=''
)
flights.append(flight)
return flights
def create_passengers(flights, users):
"""Create passenger data for flights"""
passengers = []
# Names data
first_names_male = [
'Mohammed', 'Abdullah', 'Ahmed', 'Khalid', 'Fahad', 'Ali', 'Omar', 'Ibrahim',
'Saleh', 'Saad', 'Nasser', 'Abdulaziz', 'Faisal', 'Yousef', 'Saud', 'Bandar',
'Turki', 'Majid', 'Waleed', 'Nawaf', 'Mishaal', 'Sultan', 'Talal', 'Meshari',
'Bader', 'Rayan', 'Hamad', 'Naif', 'Mansour', 'Mutlaq', 'Adel', 'Ziyad'
]
first_names_female = [
'Fatima', 'Aisha', 'Nora', 'Maha', 'Sara', 'Hessa', 'Latifa', 'Layla',
'Reema', 'Nouf', 'Mona', 'Abeer', 'Reem', 'Mariam', 'Asma', 'Amira',
'Mashael', 'Haifa', 'Najla', 'Munira', 'Samira', 'Dalal', 'Joud', 'Lamia',
'Ghadah', 'Eman', 'Nada', 'Noof', 'Shaikha', 'Hind', 'Alaa', 'Ghada'
]
last_names = [
'Al-Saud', 'Al-Qahtani', 'Al-Ghamdi', 'Al-Otaibi', 'Al-Harbi', 'Al-Shammari',
'Al-Dossari', 'Al-Zahrani', 'Al-Mutairi', 'Al-Anazi', 'Al-Shamrani', 'Al-Qurashi',
'Al-Juhani', 'Al-Maliki', 'Al-Ruwaili', 'Al-Subaie', 'Al-Khaldi', 'Al-Najjar',
'Al-Balawi', 'Al-Rashidi', 'Al-Yami', 'Al-Asiri', 'Al-Dawsari', 'Al-Mohsen',
'Al-Enezi', 'Al-Faifi', 'Al-Subhi', 'Al-Ahmari', 'Al-Hamad', 'Al-Marri',
'Al-Hajri', 'Al-Ghamidi', 'Al-Zaidi', 'Al-Buqami', 'Al-Hawawi', 'Al-Harthy'
]
# Nationalities for international diversity
nationalities = [
'Saudi', 'Saudi', 'Saudi', 'Saudi', 'Saudi', # More weight to Saudi
'Emirati', 'Egyptian', 'Jordanian', 'Lebanese', 'Kuwaiti',
'Bahraini', 'Qatari', 'Omani', 'Pakistani', 'Indian',
'Filipino', 'Bangladeshi', 'American', 'British', 'French'
]
# Email domains
email_domains = ['gmail.com', 'hotmail.com', 'yahoo.com', 'outlook.com', 'icloud.com']
# Meal codes
special_meals = ['', '', '', '', '', # More weight to no special meal
'VGML', 'KSML', 'MOML', 'DBML', 'GFML', 'PFML', 'AVML', 'SFML', 'LCML']
# Special assistance types
special_assistance_types = ['', '', '', '', '', # More weight to no special assistance
'Wheelchair', 'Unaccompanied minor', 'Blind passenger',
'Deaf passenger', 'Medical oxygen', 'Service animal']
# Frequent flyer tiers
ff_tiers = ['', '', '', '', '', # More weight to no tier
'Blue', 'Silver', 'Gold', 'Platinum', 'Diamond']
# Assign a random admin user as the creator
admin_user = random.choice(users) if users else None
# Process each flight
for flight in flights:
# Skip cancelled flights
if flight.status == 'cancelled':
continue
# Only create passengers for flights that are within 2 days before/after now
flight_time = flight.scheduled_departure
now = timezone.now()
if abs((flight_time - now).total_seconds()) > 172800: # 48 hours in seconds
# For flights outside our window, only create a few passengers (10% chance)
if random.random() > 0.1:
continue
# Determine passenger load factor (how full is the flight)
if flight.status in ['departed', 'arrived']:
# Departed/arrived flights tend to have higher load factors
load_factor = random.uniform(0.7, 0.95)
else:
# Future flights have more variable load factors
load_factor = random.uniform(0.4, 0.9)
# Calculate number of passengers to create
if flight.passenger_capacity:
num_passengers = int(flight.passenger_capacity * load_factor)
else:
# Default if capacity not set
num_passengers = random.randint(50, 150)
# Create passengers
for _ in range(num_passengers):
# Generate basic info
gender = random.choice(['M', 'F'])
first_name = random.choice(first_names_male if gender == 'M' else first_names_female)
last_name = random.choice(last_names)
# Sometimes add a middle name
if random.random() < 0.3:
middle_name = random.choice(first_names_male if gender == 'M' else first_names_female)
else:
middle_name = ''
# Generate date of birth (age distribution)
age_group = random.choices(['adult', 'child', 'infant', 'senior'],
weights=[0.75, 0.15, 0.05, 0.05], k=1)[0]
today = date.today()
if age_group == 'adult':
age = random.randint(18, 65)
elif age_group == 'child':
age = random.randint(2, 17)
elif age_group == 'infant':
age = random.randint(0, 1)
else: # senior
age = random.randint(66, 85)
birth_year = today.year - age
birth_month = random.randint(1, 12)
# Make sure February dates are valid
max_day = 28 if birth_month == 2 else 30 if birth_month in [4, 6, 9, 11] else 31
birth_day = random.randint(1, max_day)
try:
date_of_birth = date(birth_year, birth_month, birth_day)
except ValueError:
# If invalid date, use safe defaults
date_of_birth = date(birth_year, 1, 1)
# Nationality
nationality = random.choice(nationalities)
# Contact information
if random.random() < 0.7: # 70% have email
email = f"{first_name.lower()}.{last_name.lower()}{random.randint(1, 999)}@{random.choice(email_domains)}"
else:
email = ''
if random.random() < 0.8: # 80% have phone
if nationality == 'Saudi':
phone = f"+966 5{random.randint(10000000, 99999999)}"
else:
phone = f"+{random.randint(1, 999)} {random.randint(1000000, 9999999)}"
else:
phone = ''
# Travel documents
passport_number = f"{random.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ')}{random.randint(10000000, 99999999)}"
passport_expiry = today + timedelta(days=random.randint(30, 3650)) # 1 month to 10 years
# Visa number (for some passengers)
if random.random() < 0.3:
visa_number = f"V{random.randint(1000000, 9999999)}"
else:
visa_number = ''
# Generate ticket number
ticket_number = f"{flight.airline.code}{random.randint(1000000000, 9999999999)}"
# Generate booking reference (PNR)
booking_reference = ''.join(random.choices('ABCDEFGHJKLMNPQRSTUVWXYZ23456789', k=6))
# Seat assignment
if flight.status in ['boarding', 'departed', 'arrived']:
# Assign seats for boarding/departed flights
row = random.randint(1, 50)
seat_letter = random.choice('ABCDEFGHJK')
seat_number = f"{row}{seat_letter}"
else:
# Some passengers don't have seat assignments yet
seat_number = '' if random.random() < 0.3 else f"{random.randint(1, 50)}{random.choice('ABCDEFGHJK')}"
# Passenger type
if age <= 1:
passenger_type = 'infant'
elif age <= 17:
passenger_type = 'child'
elif age >= 65:
passenger_type = 'senior'
else:
passenger_type = 'adult'
# Travel class with weighting
travel_class_weights = {'economy': 0.85, 'business': 0.12, 'first': 0.03}
travel_class = random.choices(
list(travel_class_weights.keys()),
weights=list(travel_class_weights.values()),
k=1
)[0]
# Passenger status
if flight.status == 'scheduled':
# Future flight - most are just checked in
status_weights = {'checked_in': 0.97, 'cancelled': 0.03}
elif flight.status == 'boarding':
# Boarding flight - mix of checked in and boarded
status_weights = {'checked_in': 0.4, 'boarded': 0.6}
elif flight.status in ['departed', 'arrived']:
# Flight has left - most are boarded, some no-shows
status_weights = {'boarded': 0.97, 'no_show': 0.03}
else:
# Default/delayed flight
status_weights = {'checked_in': 0.95, 'cancelled': 0.05}
status = random.choices(
list(status_weights.keys()),
weights=list(status_weights.values()),
k=1
)[0]
# Baggage information
if travel_class == 'economy':
checked_bags_count = random.choices([0, 1, 2], weights=[0.2, 0.7, 0.1], k=1)[0]
elif travel_class == 'business':
checked_bags_count = random.choices([0, 1, 2, 3], weights=[0.1, 0.3, 0.5, 0.1], k=1)[0]
else: # first class
checked_bags_count = random.choices([0, 1, 2, 3], weights=[0.05, 0.25, 0.5, 0.2], k=1)[0]
# Calculate baggage weight
if checked_bags_count == 0:
checked_bags_weight_kg = Decimal('0.00')
else:
# Weight per bag
weight_per_bag = Decimal(str(random.uniform(15.0, 25.0)))
checked_bags_weight_kg = round(weight_per_bag * Decimal(str(checked_bags_count)), 2)
# Carry-on bags
carry_on_bags_count = random.choices([0, 1, 2], weights=[0.05, 0.85, 0.1], k=1)[0]
# Special requirements
special_meal = random.choice(special_meals)
special_assistance = random.choice(special_assistance_types)
# Medical conditions (rarely populated)
if random.random() < 0.05:
medical_conditions_list = [
"Diabetes", "Hypertension", "Asthma", "Heart condition",
"Mobility issues", "Pregnancy", "Allergies"
]
medical_conditions = random.choice(medical_conditions_list)
else:
medical_conditions = ""
# Check-in information
if status in ['checked_in', 'boarded', 'no_show']:
# Check-in happens 24-4 hours before flight
checkin_offset = timedelta(hours=random.randint(4, 24))
check_in_time = flight.scheduled_departure - checkin_offset
check_in_counter = f"{random.randint(1, 50)}"
else:
check_in_time = None
check_in_counter = ""
# Boarding information
if status == 'boarded':
# Boarding happens 90-30 minutes before flight
boarding_offset = timedelta(minutes=random.randint(30, 90))
boarding_time = flight.scheduled_departure - boarding_offset
boarding_gate = flight.departure_gate
else:
boarding_time = None
boarding_gate = ""
# Frequent flyer information
if random.random() < 0.4: # 40% have frequent flyer numbers
frequent_flyer_number = f"{flight.airline.code}{random.randint(10000000, 99999999)}"
frequent_flyer_tier = random.choice(ff_tiers)
else:
frequent_flyer_number = ""
frequent_flyer_tier = ""
# Create the passenger
passenger, _ = Passenger.objects.get_or_create(
first_name=first_name,
last_name=last_name,
middle_name=middle_name,
date_of_birth=date_of_birth,
nationality=nationality,
gender=gender,
passport_number=passport_number,
passport_expiry=passport_expiry,
visa_number=visa_number,
email=email,
phone=phone,
flight=flight,
ticket_number=ticket_number,
booking_reference=booking_reference,
seat_number=seat_number,
passenger_type=passenger_type,
travel_class=travel_class,
status=status,
checked_bags_count=checked_bags_count,
checked_bags_weight_kg=checked_bags_weight_kg,
carry_on_bags_count=carry_on_bags_count,
special_meal=special_meal,
special_assistance=special_assistance,
medical_conditions=medical_conditions,
check_in_time=check_in_time,
boarding_time=boarding_time,
check_in_counter=check_in_counter,
boarding_gate=boarding_gate,
frequent_flyer_number=frequent_flyer_number,
frequent_flyer_tier=frequent_flyer_tier,
created_by=admin_user
)
passengers.append(passenger)
return passengers
def create_ebt_transactions(airlines, shifts, devices):
"""Create EBT transactions"""
transactions = []
# Saudi and Arab passenger names
saudi_first_names = [
'Mohammed', 'Abdullah', 'Ahmed', 'Khalid', 'Fahad', 'Ali', 'Omar', 'Ibrahim',
'Saleh', 'Saad', 'Nasser', 'Abdulaziz', 'Faisal', 'Yousef', 'Saud', 'Bandar',
'Fatima', 'Aisha', 'Nora', 'Maha', 'Sara', 'Hessa', 'Latifa', 'Layla',
'Reema', 'Nouf', 'Mona', 'Abeer', 'Reem', 'Mariam', 'Asma', 'Amira'
]
saudi_last_names = [
'Al-Saud', 'Al-Qahtani', 'Al-Ghamdi', 'Al-Otaibi', 'Al-Harbi', 'Al-Shammari',
'Al-Dossari', 'Al-Zahrani', 'Al-Mutairi', 'Al-Anazi', 'Al-Shamrani', 'Al-Qurashi',
'Al-Juhani', 'Al-Maliki', 'Al-Ruwaili', 'Al-Subaie', 'Al-Khaldi', 'Al-Najjar',
'Al-Balawi', 'Al-Rashidi', 'Al-Yami', 'Al-Asiri', 'Al-Dawsari', 'Al-Mohsen'
]
# Flight numbers for airlines
flight_patterns = {
'SV': 'SV{0}', # Saudia
'XY': 'XY{0}', # flynas
'F3': 'F3{0}', # flyadeal
'EK': 'EK{0}', # Emirates
'EY': 'EY{0}', # Etihad
'QR': 'QR{0}', # Qatar
'GF': 'GF{0}', # Gulf Air
'KU': 'KU{0}', # Kuwait
'ME': 'ME{0}', # MEA
'RJ': 'RJ{0}', # Royal Jordanian
'TK': 'TK{0}', # Turkish
'BA': 'BA{0}', # British Airways
'LH': 'LH{0}', # Lufthansa
'AF': 'AF{0}', # Air France
'MS': 'MS{0}', # Egyptair
}
# Common destinations from Saudi airports
destinations = {
'SV': ['CAI', 'DXB', 'KHI', 'ISL', 'AMM', 'BEY', 'KWI', 'BAH', 'DOH', 'IST', 'LHR', 'CDG', 'FCO', 'JFK', 'KUL',
'CGK'],
'XY': ['CAI', 'DXB', 'AMM', 'BAH', 'KWI', 'DOH', 'IST', 'HRG', 'SSH'],
'F3': ['CAI', 'DXB', 'AMM', 'KWI', 'BAH', 'DOH'],
'EK': ['DXB'],
'EY': ['AUH'],
'QR': ['DOH'],
'GF': ['BAH'],
'KU': ['KWI'],
'ME': ['BEY'],
'RJ': ['AMM'],
'TK': ['IST'],
'BA': ['LHR'],
'LH': ['FRA', 'MUC'],
'AF': ['CDG'],
'MS': ['CAI'],
}
# Popular Saudi domestic routes
domestic_routes = {
'SV': ['RUH', 'JED', 'DMM', 'MED', 'AHB', 'TIF', 'GIZ', 'TUU', 'YNB', 'ELQ'],
'XY': ['RUH', 'JED', 'DMM', 'MED', 'AHB', 'TIF', 'GIZ'],
'F3': ['RUH', 'JED', 'DMM', 'MED'],
}
for shift in shifts:
# Skip some shifts to make data more realistic
if random.random() > 0.8:
continue
# Determine number of transactions in this shift
num_transactions = random.randint(5, 25)
for _ in range(num_transactions):
# Select a random airline with more weight to Saudi airlines
airline_weights = [3 if a.code in ['SV', 'XY', 'F3'] else 1 for a in airlines]
airline = random.choices(airlines, weights=airline_weights, k=1)[0]
# Generate flight number
flight_num = random.randint(100, 1999)
if airline.code in domestic_routes and random.random() < 0.6:
# Domestic flight
origin = shift.cashier.airport.code
destination = random.choice([d for d in domestic_routes[airline.code] if d != origin])
flight_number = flight_patterns[airline.code].format(flight_num)
else:
# International flight
if airline.code in destinations:
destination = random.choice(destinations[airline.code])
else:
destination = random.choice(['LHR', 'CDG', 'FRA', 'IST', 'DXB', 'DOH', 'CAI'])
flight_number = flight_patterns[airline.code].format(flight_num)
# Generate passenger name
first_name = random.choice(saudi_first_names)
last_name = random.choice(saudi_last_names)
passenger_name = f"{first_name} {last_name}"
# Generate ticket number
ticket_number = f"{airline.code}{random.randint(1000000000, 9999999999)}"
# Generate EMD serial (sometimes blank for cash transactions)
if random.random() < 0.8:
emd_serial = f"{airline.code}{shift.cashier.airport.code}{random.randint(100000, 999999)}"
else:
emd_serial = ""
# Generate baggage weight and rate
weight_kg = Decimal(str(random.randint(5, 40)))
# Rates vary by airline and destination
if airline.code in ['SV', 'XY', 'F3']: # Saudi airlines
if destination in domestic_routes.get(airline.code, []): # Domestic
rate_per_kg = Decimal(str(random.randint(40, 60)))
else: # International
rate_per_kg = Decimal(str(random.randint(70, 120)))
else: # Foreign airlines
rate_per_kg = Decimal(str(random.randint(80, 150)))
# Calculate total
total_amount = weight_kg * rate_per_kg
# Payment method (MADA is most common in KSA)
payment_method_weights = {'cash': 0.3, 'mada': 0.5, 'visa': 0.1, 'mastercard': 0.07, 'amex': 0.03}
payment_method = random.choices(
list(payment_method_weights.keys()),
weights=list(payment_method_weights.values()),
k=1
)[0]
# POS device for card payments
pos_device = None
pos_reference = ""
if payment_method != 'cash':
# Get POS device at the same airport
airport_devices = [d for d in devices if d.airport == shift.cashier.airport and d.status == 'active']
if airport_devices:
pos_device = random.choice(airport_devices)
pos_reference = f"MADA{random.randint(1000000, 9999999)}"
# Transaction status (mostly completed)
status_weights = {'completed': 0.94, 'refunded': 0.03, 'cancelled': 0.02, 'pending': 0.01}
status = random.choices(
list(status_weights.keys()),
weights=list(status_weights.values()),
k=1
)[0]
# Transaction date within shift timeframe
if shift.shift_end:
transaction_date = shift.shift_start + timedelta(
minutes=random.randint(0, int((shift.shift_end - shift.shift_start).total_seconds() / 60)))
else:
transaction_date = shift.shift_start + timedelta(minutes=random.randint(0, 480)) # within 8 hours
# Refund data if applicable
refund_date = None
refund_type = "full"
refund_method = "original"
refunded_by = None
if status == 'refunded':
refund_date = transaction_date + timedelta(hours=random.randint(1, 24))
refund_types = ['full', 'partial', 'fees']
refund_type = random.choices(refund_types, weights=[0.7, 0.2, 0.1], k=1)[0]
refund_methods = ['original', 'cash', 'bank']
refund_method = random.choices(refund_methods, weights=[0.6, 0.3, 0.1], k=1)[0]
refunded_by = shift.cashier.user
# Notes
notes_options = [
"",
"Hajj/Umrah passenger",
"VIP passenger",
"Sports equipment",
"Medical equipment",
"Special handling required",
"Fragile items"
]
notes = random.choice(notes_options)
transaction, _ = EBTTransaction.objects.get_or_create(
transaction_id=uuid.uuid4(),
airline=airline,
flight_number=flight_number,
passenger_name=passenger_name,
ticket_number=ticket_number,
emd_serial=emd_serial,
weight_kg=weight_kg,
rate_per_kg=rate_per_kg,
total_amount=total_amount,
payment_method=payment_method,
pos_device=pos_device,
pos_reference=pos_reference,
cashier=shift.cashier,
cash_shift=shift,
status=status,
transaction_date=transaction_date,
refund_date=refund_date,
refund_type=refund_type,
refund_method=refund_method,
refunded_by=refunded_by,
notes=notes
)
transactions.append(transaction)
return transactions
def create_daily_reconciliations(airports, transactions):
"""Create daily reconciliation records"""
reconciliations = []
# Get unique dates from transactions
transaction_dates = set()
for transaction in transactions:
# Extract just the date part
transaction_date = transaction.transaction_date.date()
transaction_dates.add(transaction_date)
# Get admin users who might reconcile
from django.contrib.auth.models import User
admin_users = User.objects.filter(is_staff=True)
admin_user = admin_users.first() if admin_users.exists() else None
# For each airport and each date, create a reconciliation
for airport in airports:
for date in transaction_dates:
# Only create reconciliations for some dates
if random.random() > 0.7:
continue
# Get transactions for this airport and date
day_transactions = [
t for t in transactions
if t.cashier.airport == airport and t.transaction_date.date() == date
]
if not day_transactions:
continue
# Calculate reconciliation data
total_transactions = len([t for t in day_transactions if t.status == 'completed'])
# Calculate totals
total_sales = sum(t.total_amount for t in day_transactions if t.status == 'completed')
cash_sales = sum(
t.total_amount for t in day_transactions
if t.status == 'completed' and t.payment_method == 'cash'
)
pos_sales = sum(
t.total_amount for t in day_transactions
if t.status == 'completed' and t.payment_method != 'cash'
)
# Bank deposits (might have slight variances)
cash_variance_factor = random.uniform(0.98, 1.02) # +/- 2%
pos_variance_factor = random.uniform(0.99, 1.01) # +/- 1%
cash_deposited = cash_sales * Decimal(str(cash_variance_factor))
pos_settled = pos_sales * Decimal(str(pos_variance_factor))
# Calculate variances
cash_variance = cash_deposited - cash_sales
pos_variance = pos_settled - pos_sales
# Determine status based on variance
if abs(cash_variance) > 100 or abs(pos_variance) > 50:
status = 'discrepancy'
else:
status = 'completed'
# Create reconciliation record
reconciliation, _ = DailyReconciliation.objects.get_or_create(
date=date,
airport=airport,
total_transactions=total_transactions,
total_sales=total_sales,
cash_sales=cash_sales,
pos_sales=pos_sales,
cash_deposited=cash_deposited,
pos_settled=pos_settled,
cash_variance=cash_variance,
pos_variance=pos_variance,
status=status,
reconciled_by=admin_user,
reconciled_at=timezone.now() if status != 'pending' else None,
notes=f"Automatic reconciliation for {date.strftime('%Y-%m-%d')}" if status != 'pending' else ""
)
reconciliations.append(reconciliation)
return reconciliations
def main():
"""Main function to generate all data"""
# Create users
print("Creating users...")
users = create_users()
# Create airlines
print("Creating airlines...")
airlines = create_airlines()
# Create airports
print("Creating airports...")
airports = create_airports()
# Create POS devices
print("Creating POS devices...")
devices = create_pos_devices(airports)
# Create ticket inventory
print("Creating ticket inventory...")
inventory = create_ticket_inventory(airlines, airports)
# Create cashiers
print("Creating cashiers...")
cashiers = create_cashiers(users, airports)
# Create cash shifts
print("Creating cash shifts...")
shifts = create_cash_shifts(cashiers)
# Create flights
print("Creating flights...")
flights = create_flights(airlines, airports)
# Create passengers
print("Creating passengers...")
passengers = create_passengers(flights, users)
# Create EBT transactions
print("Creating EBT transactions...")
transactions = create_ebt_transactions(airlines, shifts, devices)
# Create daily reconciliations
print("Creating daily reconciliations...")
reconciliations = create_daily_reconciliations(airports, transactions)
# Update cash shift totals based on transactions
print("Updating cash shift totals...")
for shift in CashShift.objects.all():
shift.update_sales_totals()
print("Data generation complete!")
print(f"Created {len(users)} users")
print(f"Created {len(airlines)} airlines")
print(f"Created {len(airports)} airports")
print(f"Created {len(devices)} POS devices")
print(f"Created {len(inventory)} ticket inventory records")
print(f"Created {len(cashiers)} cashiers")
print(f"Created {len(shifts)} cash shifts")
print(f"Created {len(flights)} flights")
print(f"Created {len(passengers)} passengers")
print(f"Created {len(transactions)} transactions")
print(f"Created {len(reconciliations)} reconciliations")
# If running as a script
if __name__ == "__main__":
main()