459 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			459 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python3
 | |
| """
 | |
| Script to create comprehensive test data for the Product Tracker application.
 | |
| This includes shops, products, and shopping events with realistic data.
 | |
| """
 | |
| 
 | |
| import requests
 | |
| import json
 | |
| import random
 | |
| import argparse
 | |
| import sys
 | |
| from datetime import datetime, timedelta
 | |
| from typing import List, Dict, Any
 | |
| 
 | |
| BASE_URL = "http://localhost:8000"
 | |
| 
 | |
| # Test data definitions
 | |
| SHOPS_DATA = [
 | |
|     {"name": "Whole Foods Market", "city": "San Francisco", "address": "1765 California St"},
 | |
|     {"name": "Safeway", "city": "San Francisco", "address": "2020 Market St"},
 | |
|     {"name": "Trader Joe's", "city": "Berkeley", "address": "1885 University Ave"},
 | |
|     {"name": "Berkeley Bowl", "city": "Berkeley", "address": "2020 Oregon St"},
 | |
|     {"name": "Rainbow Product", "city": "San Francisco", "address": "1745 Folsom St"},
 | |
|     {"name": "Mollie Stone's Market", "city": "Palo Alto", "address": "164 S California Ave"},
 | |
|     {"name": "Costco Wholesale", "city": "San Mateo", "address": "2300 S Norfolk St"},
 | |
|     {"name": "Target", "city": "Mountain View", "address": "1200 El Camino Real"},
 | |
|     {"name": "Sprouts Farmers Market", "city": "Sunnyvale", "address": "1077 E El Camino Real"},
 | |
|     {"name": "Lucky Supermarket", "city": "San Jose", "address": "1717 Tully Rd"},
 | |
| ]
 | |
| 
 | |
| GROCERIES_DATA = [
 | |
|     # Fruits
 | |
|     {"name": "Organic Bananas", "category": "Fruits", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Gala Apples", "category": "Fruits", "organic": False, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Organic Strawberries", "category": "Fruits", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Avocados", "category": "Fruits", "organic": False, "weight": None, "weight_unit": "piece"},
 | |
|     {"name": "Organic Blueberries", "category": "Fruits", "organic": True, "weight": 0.5, "weight_unit": "lb"},
 | |
|     {"name": "Lemons", "category": "Fruits", "organic": False, "weight": None, "weight_unit": "piece"},
 | |
|     {"name": "Organic Oranges", "category": "Fruits", "organic": True, "weight": 3.0, "weight_unit": "lb"},
 | |
|     {"name": "Grapes", "category": "Fruits", "organic": False, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Organic Pears", "category": "Fruits", "organic": True, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Pineapple", "category": "Fruits", "organic": False, "weight": None, "weight_unit": "piece"},
 | |
|     
 | |
|     # Vegetables
 | |
|     {"name": "Organic Spinach", "category": "Vegetables", "organic": True, "weight": 5.0, "weight_unit": "oz"},
 | |
|     {"name": "Carrots", "category": "Vegetables", "organic": False, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Organic Broccoli", "category": "Vegetables", "organic": True, "weight": None, "weight_unit": "piece"},
 | |
|     {"name": "Red Bell Peppers", "category": "Vegetables", "organic": False, "weight": None, "weight_unit": "piece"},
 | |
|     {"name": "Organic Kale", "category": "Vegetables", "organic": True, "weight": 1.0, "weight_unit": "bunch"},
 | |
|     {"name": "Tomatoes", "category": "Vegetables", "organic": False, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Organic Sweet Potatoes", "category": "Vegetables", "organic": True, "weight": 3.0, "weight_unit": "lb"},
 | |
|     {"name": "Cucumbers", "category": "Vegetables", "organic": False, "weight": None, "weight_unit": "piece"},
 | |
|     {"name": "Organic Lettuce", "category": "Vegetables", "organic": True, "weight": None, "weight_unit": "head"},
 | |
|     {"name": "Onions", "category": "Vegetables", "organic": False, "weight": 3.0, "weight_unit": "lb"},
 | |
|     
 | |
|     # Dairy
 | |
|     {"name": "Organic Whole Milk", "category": "Dairy", "organic": True, "weight": 1.0, "weight_unit": "gallon"},
 | |
|     {"name": "Greek Yogurt", "category": "Dairy", "organic": False, "weight": 32.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Eggs", "category": "Dairy", "organic": True, "weight": None, "weight_unit": "dozen"},
 | |
|     {"name": "Cheddar Cheese", "category": "Dairy", "organic": False, "weight": 8.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Butter", "category": "Dairy", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Cream Cheese", "category": "Dairy", "organic": False, "weight": 8.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Yogurt", "category": "Dairy", "organic": True, "weight": 6.0, "weight_unit": "oz"},
 | |
|     
 | |
|     # Meat & Seafood
 | |
|     {"name": "Organic Chicken Breast", "category": "Meat & Seafood", "organic": True, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Ground Beef", "category": "Meat & Seafood", "organic": False, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Wild Salmon Fillet", "category": "Meat & Seafood", "organic": False, "weight": 1.5, "weight_unit": "lb"},
 | |
|     {"name": "Organic Ground Turkey", "category": "Meat & Seafood", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Shrimp", "category": "Meat & Seafood", "organic": False, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Organic Chicken Thighs", "category": "Meat & Seafood", "organic": True, "weight": 2.0, "weight_unit": "lb"},
 | |
|     
 | |
|     # Pantry
 | |
|     {"name": "Organic Brown Rice", "category": "Pantry", "organic": True, "weight": 2.0, "weight_unit": "lb"},
 | |
|     {"name": "Whole Wheat Bread", "category": "Pantry", "organic": False, "weight": 24.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Quinoa", "category": "Pantry", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Olive Oil", "category": "Pantry", "organic": False, "weight": 500.0, "weight_unit": "ml"},
 | |
|     {"name": "Organic Pasta", "category": "Pantry", "organic": True, "weight": 1.0, "weight_unit": "lb"},
 | |
|     {"name": "Black Beans", "category": "Pantry", "organic": False, "weight": 15.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Oats", "category": "Pantry", "organic": True, "weight": 18.0, "weight_unit": "oz"},
 | |
|     {"name": "Peanut Butter", "category": "Pantry", "organic": False, "weight": 18.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Honey", "category": "Pantry", "organic": True, "weight": 12.0, "weight_unit": "oz"},
 | |
|     {"name": "Canned Tomatoes", "category": "Pantry", "organic": False, "weight": 14.5, "weight_unit": "oz"},
 | |
|     
 | |
|     # Beverages
 | |
|     {"name": "Organic Orange Juice", "category": "Beverages", "organic": True, "weight": 64.0, "weight_unit": "oz"},
 | |
|     {"name": "Sparkling Water", "category": "Beverages", "organic": False, "weight": 1.0, "weight_unit": "l"},
 | |
|     {"name": "Organic Green Tea", "category": "Beverages", "organic": True, "weight": None, "weight_unit": "box"},
 | |
|     {"name": "Coffee Beans", "category": "Beverages", "organic": False, "weight": 12.0, "weight_unit": "oz"},
 | |
|     {"name": "Almond Milk", "category": "Beverages", "organic": False, "weight": 32.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Apple Juice", "category": "Beverages", "organic": True, "weight": 64.0, "weight_unit": "oz"},
 | |
|     
 | |
|     # Frozen
 | |
|     {"name": "Organic Frozen Berries", "category": "Frozen", "organic": True, "weight": 10.0, "weight_unit": "oz"},
 | |
|     {"name": "Frozen Pizza", "category": "Frozen", "organic": False, "weight": 12.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Frozen Vegetables", "category": "Frozen", "organic": True, "weight": 16.0, "weight_unit": "oz"},
 | |
|     {"name": "Ice Cream", "category": "Frozen", "organic": False, "weight": 48.0, "weight_unit": "oz"},
 | |
|     {"name": "Frozen Fish Fillets", "category": "Frozen", "organic": False, "weight": 1.0, "weight_unit": "lb"},
 | |
|     
 | |
|     # Snacks
 | |
|     {"name": "Organic Granola Bars", "category": "Snacks", "organic": True, "weight": 8.0, "weight_unit": "oz"},
 | |
|     {"name": "Potato Chips", "category": "Snacks", "organic": False, "weight": 5.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Nuts", "category": "Snacks", "organic": True, "weight": 6.0, "weight_unit": "oz"},
 | |
|     {"name": "Crackers", "category": "Snacks", "organic": False, "weight": 7.0, "weight_unit": "oz"},
 | |
|     {"name": "Organic Popcorn", "category": "Snacks", "organic": True, "weight": 3.0, "weight_unit": "oz"},
 | |
| ]
 | |
| 
 | |
| # Price ranges for different categories (min, max)
 | |
| PRICE_RANGES = {
 | |
|     "Fruits": (1.99, 8.99),
 | |
|     "Vegetables": (0.99, 6.99),
 | |
|     "Dairy": (2.49, 12.99),
 | |
|     "Meat & Seafood": (4.99, 24.99),
 | |
|     "Pantry": (1.99, 15.99),
 | |
|     "Beverages": (1.99, 8.99),
 | |
|     "Frozen": (2.99, 9.99),
 | |
|     "Snacks": (1.49, 7.99),
 | |
| }
 | |
| 
 | |
| def parse_arguments():
 | |
|     """Parse command line arguments."""
 | |
|     parser = argparse.ArgumentParser(description='Create test data for Product Tracker')
 | |
|     parser.add_argument('--events', type=int, default=30, help='Number of shopping events to create (default: 30)')
 | |
|     parser.add_argument('--days', type=int, default=90, help='Number of days back to generate events (default: 90)')
 | |
|     parser.add_argument('--url', type=str, default=BASE_URL, help='API base URL (default: http://localhost:8000)')
 | |
|     parser.add_argument('--shops-only', action='store_true', help='Create only shops')
 | |
|     parser.add_argument('--products-only', action='store_true', help='Create only products')
 | |
|     parser.add_argument('--events-only', action='store_true', help='Create only shopping events (requires existing shops and products)')
 | |
|     parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
 | |
|     parser.add_argument('--dry-run', action='store_true', help='Show what would be created without actually creating it')
 | |
|     return parser.parse_args()
 | |
| 
 | |
| def check_api_connection(base_url: str) -> bool:
 | |
|     """Check if the API server is accessible."""
 | |
|     try:
 | |
|         response = requests.get(f"{base_url}/", timeout=5)
 | |
|         return response.status_code == 200
 | |
|     except requests.exceptions.RequestException:
 | |
|         return False
 | |
| 
 | |
| def create_shops(base_url: str, verbose: bool = False, dry_run: bool = False) -> List[Dict[str, Any]]:
 | |
|     """Create shops and return the created shop objects."""
 | |
|     print("🏪 Creating shops...")
 | |
|     created_shops = []
 | |
|     
 | |
|     if dry_run:
 | |
|         print("   [DRY RUN] Would create the following shops:")
 | |
|         for shop_data in SHOPS_DATA:
 | |
|             print(f"   📋 {shop_data['name']} in {shop_data['city']}")
 | |
|         return []
 | |
|     
 | |
|     for shop_data in SHOPS_DATA:
 | |
|         try:
 | |
|             if verbose:
 | |
|                 print(f"   🔄 Creating shop: {shop_data['name']}...")
 | |
|             
 | |
|             response = requests.post(f"{base_url}/shops/", json=shop_data, timeout=10)
 | |
|             if response.status_code == 200:
 | |
|                 shop = response.json()
 | |
|                 created_shops.append(shop)
 | |
|                 print(f"   ✅ Created shop: {shop['name']} in {shop['city']}")
 | |
|             else:
 | |
|                 print(f"   ❌ Failed to create shop {shop_data['name']}: {response.status_code}")
 | |
|                 if verbose:
 | |
|                     print(f"      Response: {response.text}")
 | |
|         except requests.exceptions.RequestException as e:
 | |
|             print(f"   ❌ Network error creating shop {shop_data['name']}: {e}")
 | |
|         except Exception as e:
 | |
|             print(f"   ❌ Error creating shop {shop_data['name']}: {e}")
 | |
|     
 | |
|     print(f"   📊 Created {len(created_shops)} shops total\n")
 | |
|     return created_shops
 | |
| 
 | |
| def create_products(base_url: str, verbose: bool = False, dry_run: bool = False) -> List[Dict[str, Any]]:
 | |
|     """Create products and return the created product objects."""
 | |
|     print("🥬 Creating products...")
 | |
|     created_products = []
 | |
|     
 | |
|     if dry_run:
 | |
|         print("   [DRY RUN] Would create the following products:")
 | |
|         for product_data in GROCERIES_DATA:
 | |
|             organic_label = "🌱" if product_data['organic'] else "🌾"
 | |
|             print(f"   📋 {organic_label} {product_data['name']} ({product_data['category']})")
 | |
|         return []
 | |
|     
 | |
|     for product_data in GROCERIES_DATA:
 | |
|         try:
 | |
|             if verbose:
 | |
|                 print(f"   🔄 Creating product: {product_data['name']}...")
 | |
|             
 | |
|             response = requests.post(f"{base_url}/products/", json=product_data, timeout=10)
 | |
|             if response.status_code == 200:
 | |
|                 product = response.json()
 | |
|                 created_products.append(product)
 | |
|                 organic_label = "🌱" if product['organic'] else "🌾"
 | |
|                 print(f"   ✅ Created product: {organic_label} {product['name']} ({product['category']})")
 | |
|             else:
 | |
|                 print(f"   ❌ Failed to create product {product_data['name']}: {response.status_code}")
 | |
|                 if verbose:
 | |
|                     print(f"      Response: {response.text}")
 | |
|         except requests.exceptions.RequestException as e:
 | |
|             print(f"   ❌ Network error creating product {product_data['name']}: {e}")
 | |
|         except Exception as e:
 | |
|             print(f"   ❌ Error creating product {product_data['name']}: {e}")
 | |
|     
 | |
|     print(f"   📊 Created {len(created_products)} products total\n")
 | |
|     return created_products
 | |
| 
 | |
| def generate_random_price(category: str, organic: bool = False) -> float:
 | |
|     """Generate a random price for a product item based on category and organic status."""
 | |
|     min_price, max_price = PRICE_RANGES.get(category, (1.99, 9.99))
 | |
|     
 | |
|     # Organic items are typically 20-50% more expensive
 | |
|     if organic:
 | |
|         min_price *= 1.2
 | |
|         max_price *= 1.5
 | |
|     
 | |
|     # Generate random price and round to nearest cent
 | |
|     price = random.uniform(min_price, max_price)
 | |
|     return round(price, 2)
 | |
| 
 | |
| def get_existing_data(base_url: str) -> tuple[List[Dict], List[Dict]]:
 | |
|     """Get existing shops and products from the API."""
 | |
|     try:
 | |
|         shops_response = requests.get(f"{base_url}/shops/", timeout=10)
 | |
|         products_response = requests.get(f"{base_url}/products/", timeout=10)
 | |
|         
 | |
|         shops = shops_response.json() if shops_response.status_code == 200 else []
 | |
|         products = products_response.json() if products_response.status_code == 200 else []
 | |
|         
 | |
|         return shops, products
 | |
|     except requests.exceptions.RequestException as e:
 | |
|         print(f"   ❌ Error fetching existing data: {e}")
 | |
|         return [], []
 | |
| 
 | |
| def create_shopping_events(shops: List[Dict], products: List[Dict], base_url: str, 
 | |
|                          num_events: int = 25, days_back: int = 90, 
 | |
|                          verbose: bool = False, dry_run: bool = False) -> List[Dict[str, Any]]:
 | |
|     """Create shopping events with random products and realistic data."""
 | |
|     print(f"🛒 Creating {num_events} shopping events...")
 | |
|     created_events = []
 | |
|     
 | |
|     if not shops:
 | |
|         print("   ❌ No shops available. Cannot create shopping events.")
 | |
|         return []
 | |
|     
 | |
|     if not products:
 | |
|         print("   ❌ No products available. Cannot create shopping events.")
 | |
|         return []
 | |
|     
 | |
|     # Generate events over the specified time period
 | |
|     end_date = datetime.now()
 | |
|     start_date = end_date - timedelta(days=days_back)
 | |
|     
 | |
|     if dry_run:
 | |
|         print(f"   [DRY RUN] Would create {num_events} shopping events over {days_back} days")
 | |
|         print(f"   📋 Date range: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')}")
 | |
|         print(f"   📋 Available shops: {len(shops)}")
 | |
|         print(f"   📋 Available products: {len(products)}")
 | |
|         return []
 | |
|     
 | |
|     for i in range(num_events):
 | |
|         try:
 | |
|             if verbose:
 | |
|                 print(f"   🔄 Creating shopping event {i+1}/{num_events}...")
 | |
|             
 | |
|             # Random shop and date
 | |
|             shop = random.choice(shops)
 | |
|             event_date = start_date + timedelta(
 | |
|                 days=random.randint(0, days_back),
 | |
|                 hours=random.randint(8, 20),
 | |
|                 minutes=random.randint(0, 59)
 | |
|             )
 | |
|             
 | |
|             # Random number of products (2-8 items per shopping trip)
 | |
|             num_products = random.randint(2, 8)
 | |
|             selected_products = random.sample(products, min(num_products, len(products)))
 | |
|             
 | |
|             # Create product items for this event
 | |
|             event_products = []
 | |
|             total_amount = 0.0
 | |
|             
 | |
|             for product in selected_products:
 | |
|                 # Random amount based on item type
 | |
|                 if product['weight_unit'] == 'piece':
 | |
|                     amount = random.randint(1, 4)
 | |
|                 elif product['weight_unit'] == 'dozen':
 | |
|                     amount = 1
 | |
|                 elif product['weight_unit'] in ['box', 'head', 'bunch']:
 | |
|                     amount = random.randint(1, 2)
 | |
|                 elif product['weight_unit'] in ['gallon', 'l']:
 | |
|                     amount = 1
 | |
|                 else:
 | |
|                     amount = round(random.uniform(0.5, 3.0), 2)
 | |
|                 
 | |
|                 # Generate price based on category and organic status
 | |
|                 price = generate_random_price(product['category'], product['organic'])
 | |
|                 
 | |
|                 event_products.append({
 | |
|                     "product_id": product['id'],
 | |
|                     "amount": amount,
 | |
|                     "price": price
 | |
|                 })
 | |
|                 
 | |
|                 total_amount += amount * price
 | |
|             
 | |
|             # Round total amount
 | |
|             total_amount = round(total_amount, 2)
 | |
|             
 | |
|             # Random notes (30% chance of having notes)
 | |
|             notes = None
 | |
|             if random.random() < 0.3:
 | |
|                 note_options = [
 | |
|                     "Weekly product shopping",
 | |
|                     "Quick lunch ingredients",
 | |
|                     "Dinner party prep",
 | |
|                     "Meal prep for the week",
 | |
|                     "Emergency product run",
 | |
|                     "Organic produce haul",
 | |
|                     "Bulk shopping trip",
 | |
|                     "Special occasion shopping",
 | |
|                     "Holiday meal preparation",
 | |
|                     "Healthy eating restart",
 | |
|                     "Stocking up on essentials",
 | |
|                     "Trying new recipes",
 | |
|                 ]
 | |
|                 notes = random.choice(note_options)
 | |
|             
 | |
|             # Create the shopping event
 | |
|             event_data = {
 | |
|                 "shop_id": shop['id'],
 | |
|                 "date": event_date.isoformat(),
 | |
|                 "total_amount": total_amount,
 | |
|                 "notes": notes,
 | |
|                 "products": event_products
 | |
|             }
 | |
|             
 | |
|             response = requests.post(f"{base_url}/shopping-events/", json=event_data, timeout=15)
 | |
|             if response.status_code == 200:
 | |
|                 event = response.json()
 | |
|                 created_events.append(event)
 | |
|                 print(f"   ✅ Created event #{event['id']}: {shop['name']} - ${total_amount:.2f} ({len(event_products)} items)")
 | |
|             else:
 | |
|                 print(f"   ❌ Failed to create shopping event: {response.status_code}")
 | |
|                 if verbose:
 | |
|                     print(f"      Response: {response.text}")
 | |
|         except requests.exceptions.RequestException as e:
 | |
|             print(f"   ❌ Network error creating shopping event {i+1}: {e}")
 | |
|         except Exception as e:
 | |
|             print(f"   ❌ Error creating shopping event {i+1}: {e}")
 | |
|     
 | |
|     print(f"   📊 Created {len(created_events)} shopping events total\n")
 | |
|     return created_events
 | |
| 
 | |
| def print_summary(shops: List[Dict], products: List[Dict], events: List[Dict]):
 | |
|     """Print a summary of the created test data."""
 | |
|     print("📋 TEST DATA SUMMARY")
 | |
|     print("=" * 50)
 | |
|     
 | |
|     print(f"🏪 Shops: {len(shops)}")
 | |
|     for shop in shops:
 | |
|         print(f"   • {shop['name']} ({shop['city']})")
 | |
|     
 | |
|     print(f"\n🥬 Products: {len(products)}")
 | |
|     categories = {}
 | |
|     for product in products:
 | |
|         category = product['category']
 | |
|         if category not in categories:
 | |
|             categories[category] = []
 | |
|         categories[category].append(product)
 | |
|     
 | |
|     for category, items in categories.items():
 | |
|         organic_count = sum(1 for item in items if item['organic'])
 | |
|         print(f"   • {category}: {len(items)} items ({organic_count} organic)")
 | |
|     
 | |
|     print(f"\n🛒 Shopping Events: {len(events)}")
 | |
|     if events:
 | |
|         total_spent = sum(event.get('total_amount', 0) for event in events)
 | |
|         avg_spent = total_spent / len(events) if events else 0
 | |
|         print(f"   • Total spent: ${total_spent:.2f}")
 | |
|         print(f"   • Average per trip: ${avg_spent:.2f}")
 | |
|         
 | |
|         # Shop distribution
 | |
|         shop_counts = {}
 | |
|         for event in events:
 | |
|             shop_name = event['shop']['name']
 | |
|             shop_counts[shop_name] = shop_counts.get(shop_name, 0) + 1
 | |
|         
 | |
|         print("   • Events per shop:")
 | |
|         for shop_name, count in sorted(shop_counts.items(), key=lambda x: x[1], reverse=True):
 | |
|             print(f"     - {shop_name}: {count} events")
 | |
| 
 | |
| def main():
 | |
|     """Main function to create all test data."""
 | |
|     args = parse_arguments()
 | |
|     
 | |
|     print("🚀 PRODUCT TRACKER TEST DATA GENERATOR")
 | |
|     print("=" * 50)
 | |
|     
 | |
|     if args.dry_run:
 | |
|         print("🔍 DRY RUN MODE - No data will be created")
 | |
|     
 | |
|     print(f"API URL: {args.url}")
 | |
|     print(f"Shopping events: {args.events}")
 | |
|     print(f"Date range: {args.days} days back")
 | |
|     print()
 | |
|     
 | |
|     try:
 | |
|         # Test connection
 | |
|         if not check_api_connection(args.url):
 | |
|             print(f"❌ Cannot connect to the API server at {args.url}")
 | |
|             print("   Make sure the backend server is running!")
 | |
|             sys.exit(1)
 | |
|         
 | |
|         print("✅ Connected to API server\n")
 | |
|         
 | |
|         shops = []
 | |
|         products = []
 | |
|         events = []
 | |
|         
 | |
|         # Create data based on arguments
 | |
|         if args.shops_only:
 | |
|             shops = create_shops(args.url, args.verbose, args.dry_run)
 | |
|         elif args.products_only:
 | |
|             products = create_products(args.url, args.verbose, args.dry_run)
 | |
|         elif args.events_only:
 | |
|             # Get existing data for events
 | |
|             shops, products = get_existing_data(args.url)
 | |
|             events = create_shopping_events(shops, products, args.url, args.events, args.days, args.verbose, args.dry_run)
 | |
|         else:
 | |
|             # Create all data
 | |
|             shops = create_shops(args.url, args.verbose, args.dry_run)
 | |
|             products = create_products(args.url, args.verbose, args.dry_run)
 | |
|             if shops and products:
 | |
|                 events = create_shopping_events(shops, products, args.url, args.events, args.days, args.verbose, args.dry_run)
 | |
|         
 | |
|         # Print summary
 | |
|         if not args.dry_run:
 | |
|             print_summary(shops, products, events)
 | |
|         
 | |
|         if args.dry_run:
 | |
|             print("\n🔍 Dry run completed. Use without --dry-run to actually create the data.")
 | |
|         else:
 | |
|             print("\n🎉 Test data creation completed successfully!")
 | |
|             print("You can now explore the application with realistic data.")
 | |
|         
 | |
|     except KeyboardInterrupt:
 | |
|         print("\n❌ Operation cancelled by user.")
 | |
|         sys.exit(1)
 | |
|     except requests.exceptions.ConnectionError:
 | |
|         print(f"❌ Could not connect to the API server at {args.url}")
 | |
|         print("   Make sure the backend server is running!")
 | |
|         sys.exit(1)
 | |
|     except Exception as e:
 | |
|         print(f"❌ Unexpected error: {e}")
 | |
|         sys.exit(1)
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()  |