This commit is contained in:
Iliyan Angelov
2025-11-21 01:20:51 +02:00
parent a38ab4fa82
commit 6f85b8cf17
242 changed files with 7154 additions and 14492 deletions

View File

@@ -1,15 +1,7 @@
#!/usr/bin/env python3
"""
Seed script to delete all existing rooms and create 50 sample luxury hotel rooms
"""
import sys
import os
from pathlib import Path
# Add the parent directory to the path so we can import from src
sys.path.insert(0, str(Path(__file__).parent))
from sqlalchemy.orm import Session
from src.config.database import SessionLocal, engine
from src.models.room import Room, RoomStatus
@@ -19,7 +11,6 @@ import json
import random
def get_db():
"""Get database session"""
db = SessionLocal()
try:
return db
@@ -27,169 +18,60 @@ def get_db():
pass
def seed_rooms(db: Session):
"""Delete all existing rooms and create 50 sample luxury rooms"""
print("=" * 80)
print("SEEDING ROOMS - DELETING EXISTING AND CREATING 50 NEW LUXURY ROOMS")
print("=" * 80)
# Get all room types
print('=' * 80)
print('SEEDING ROOMS - DELETING EXISTING AND CREATING 50 NEW LUXURY ROOMS')
print('=' * 80)
room_types = db.query(RoomType).all()
if not room_types:
print("❌ No room types found! Please create room types first.")
print('❌ No room types found! Please create room types first.')
return
print(f"\n✓ Found {len(room_types)} room type(s)")
print(f'\n✓ Found {len(room_types)} room type(s)')
for rt in room_types:
print(f" - {rt.name} (ID: {rt.id}, Base Price: {rt.base_price})")
# Delete all existing rooms
# First, we need to handle related records that reference these rooms
print(f' - {rt.name} (ID: {rt.id}, Base Price: {rt.base_price})')
from src.models.booking import Booking
from src.models.review import Review
from src.models.favorite import Favorite
existing_rooms = db.query(Room).all()
if existing_rooms:
print(f"\n🗑️ Deleting {len(existing_rooms)} existing room(s)...")
# Get all room IDs
print(f'\n🗑️ Deleting {len(existing_rooms)} existing room(s)...')
room_ids = [room.id for room in existing_rooms]
# Delete bookings that reference these rooms
bookings_with_rooms = db.query(Booking).filter(Booking.room_id.in_(room_ids)).all()
if bookings_with_rooms:
print(f" ⚠️ Found {len(bookings_with_rooms)} booking(s) referencing these rooms")
print(f' ⚠️ Found {len(bookings_with_rooms)} booking(s) referencing these rooms')
for booking in bookings_with_rooms:
db.delete(booking)
print(f" ✓ Deleted {len(bookings_with_rooms)} booking(s)")
# Delete reviews that reference these rooms
print(f' ✓ Deleted {len(bookings_with_rooms)} booking(s)')
reviews_with_rooms = db.query(Review).filter(Review.room_id.in_(room_ids)).all()
if reviews_with_rooms:
print(f" ⚠️ Found {len(reviews_with_rooms)} review(s) referencing these rooms")
print(f' ⚠️ Found {len(reviews_with_rooms)} review(s) referencing these rooms')
for review in reviews_with_rooms:
db.delete(review)
print(f" ✓ Deleted {len(reviews_with_rooms)} review(s)")
# Delete favorites that reference these rooms
print(f' ✓ Deleted {len(reviews_with_rooms)} review(s)')
favorites_with_rooms = db.query(Favorite).filter(Favorite.room_id.in_(room_ids)).all()
if favorites_with_rooms:
print(f" ⚠️ Found {len(favorites_with_rooms)} favorite(s) referencing these rooms")
print(f' ⚠️ Found {len(favorites_with_rooms)} favorite(s) referencing these rooms')
for favorite in favorites_with_rooms:
db.delete(favorite)
print(f" ✓ Deleted {len(favorites_with_rooms)} favorite(s)")
# Now delete the rooms
print(f' ✓ Deleted {len(favorites_with_rooms)} favorite(s)')
for room in existing_rooms:
db.delete(room)
db.commit()
print(f"✓ Deleted {len(existing_rooms)} room(s)")
# Luxury room configurations
views = [
"Ocean View", "City View", "Garden View", "Mountain View",
"Pool View", "Beach View", "Panoramic View", "Sea View"
]
room_sizes = [
"35 sqm", "40 sqm", "45 sqm", "50 sqm", "55 sqm",
"60 sqm", "70 sqm", "80 sqm", "90 sqm", "100 sqm",
"120 sqm", "150 sqm", "180 sqm", "200 sqm", "250 sqm"
]
# Real luxury hotel room images from Unsplash (defined once, used for all rooms)
luxury_room_images = [
# Luxury hotel rooms
"https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1618221195710-dd6b41faaea8?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop",
# Suite images
"https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1582719508461-905c673771fd?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1595576508898-0ad5c879a061?w=1200&h=800&fit=crop",
# Additional luxury rooms
"https://images.unsplash.com/photo-1571003123894-1f0594d2b5d9?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1618221195710-dd6b41faaea8?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1582719508461-905c673771fd?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1595576508898-0ad5c879a061?w=1200&h=800&fit=crop",
"https://images.unsplash.com/photo-1571003123894-1f0594d2b5d9?w=1200&h=800&fit=crop",
]
# Comprehensive luxury amenities
all_amenities = [
"Free WiFi", "High-Speed Internet", "Smart TV", "Netflix",
"Air Conditioning", "Climate Control", "Private Balcony",
"Ocean View", "City View", "Minibar", "Coffee Maker",
"Espresso Machine", "Refrigerator", "Safe", "Iron & Ironing Board",
"Hair Dryer", "Premium Toiletries", "Bathrobes", "Slippers",
"Work Desk", "Ergonomic Chair", "USB Charging Ports",
"Bluetooth Speaker", "Sound System", "Blackout Curtains",
"Pillow Menu", "Turndown Service", "Room Service", "24/7 Concierge"
]
premium_amenities = [
"Jacuzzi Bathtub", "Steam Shower", "Rain Shower", "Bidet",
"Private Pool", "Outdoor Terrace", "Fireplace", "Wine Cellar",
"Private Bar", "Butler Service", "Private Elevator", "Helipad Access"
]
# Room configurations: (floor_range, room_numbers_per_floor, view, size_range, amenities_count, featured)
room_configs = [
# Standard Rooms (Floors 1-3)
((1, 3), 8, "Garden View", (35, 45), 8, False),
((1, 3), 8, "City View", (40, 50), 9, False),
# Superior Rooms (Floors 4-6)
((4, 6), 6, "City View", (45, 55), 10, False),
((4, 6), 6, "Pool View", (50, 60), 11, True),
# Deluxe Rooms (Floors 7-9)
((7, 9), 5, "Ocean View", (55, 70), 12, True),
((7, 9), 5, "Mountain View", (60, 75), 12, False),
# Executive Suites (Floors 10-12)
((10, 12), 4, "Panoramic View", (80, 100), 14, True),
((10, 12), 4, "Sea View", (90, 110), 15, True),
# Luxury Suites (Floors 13-15)
((13, 15), 3, "Ocean View", (120, 150), 16, True),
((13, 15), 3, "Beach View", (130, 160), 17, True),
# Presidential Suites (Floor 16)
((16, 16), 2, "Panoramic View", (200, 250), 20, True),
]
print(f'✓ Deleted {len(existing_rooms)} room(s)')
views = ['Ocean View', 'City View', 'Garden View', 'Mountain View', 'Pool View', 'Beach View', 'Panoramic View', 'Sea View']
room_sizes = ['35 sqm', '40 sqm', '45 sqm', '50 sqm', '55 sqm', '60 sqm', '70 sqm', '80 sqm', '90 sqm', '100 sqm', '120 sqm', '150 sqm', '180 sqm', '200 sqm', '250 sqm']
luxury_room_images = ['https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1618221195710-dd6b41faaea8?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1582719508461-905c673771fd?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1595576508898-0ad5c879a061?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1571003123894-1f0594d2b5d9?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1618221195710-dd6b41faaea8?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1566665797739-1674de7a421a?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1582719508461-905c673771fd?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1595576508898-0ad5c879a061?w=1200&h=800&fit=crop', 'https://images.unsplash.com/photo-1571003123894-1f0594d2b5d9?w=1200&h=800&fit=crop']
all_amenities = ['Free WiFi', 'High-Speed Internet', 'Smart TV', 'Netflix', 'Air Conditioning', 'Climate Control', 'Private Balcony', 'Ocean View', 'City View', 'Minibar', 'Coffee Maker', 'Espresso Machine', 'Refrigerator', 'Safe', 'Iron & Ironing Board', 'Hair Dryer', 'Premium Toiletries', 'Bathrobes', 'Slippers', 'Work Desk', 'Ergonomic Chair', 'USB Charging Ports', 'Bluetooth Speaker', 'Sound System', 'Blackout Curtains', 'Pillow Menu', 'Turndown Service', 'Room Service', '24/7 Concierge']
premium_amenities = ['Jacuzzi Bathtub', 'Steam Shower', 'Rain Shower', 'Bidet', 'Private Pool', 'Outdoor Terrace', 'Fireplace', 'Wine Cellar', 'Private Bar', 'Butler Service', 'Private Elevator', 'Helipad Access']
room_configs = [((1, 3), 8, 'Garden View', (35, 45), 8, False), ((1, 3), 8, 'City View', (40, 50), 9, False), ((4, 6), 6, 'City View', (45, 55), 10, False), ((4, 6), 6, 'Pool View', (50, 60), 11, True), ((7, 9), 5, 'Ocean View', (55, 70), 12, True), ((7, 9), 5, 'Mountain View', (60, 75), 12, False), ((10, 12), 4, 'Panoramic View', (80, 100), 14, True), ((10, 12), 4, 'Sea View', (90, 110), 15, True), ((13, 15), 3, 'Ocean View', (120, 150), 16, True), ((13, 15), 3, 'Beach View', (130, 160), 17, True), ((16, 16), 2, 'Panoramic View', (200, 250), 20, True)]
rooms_created = []
room_counter = 101 # Starting room number
print(f"\n🏨 Creating 50 luxury rooms...\n")
room_counter = 101
print(f'\n🏨 Creating 50 luxury rooms...\n')
for config in room_configs:
floor_range, rooms_per_floor, view_type, size_range, amenities_count, featured = config
for floor in range(floor_range[0], floor_range[1] + 1):
for _ in range(rooms_per_floor):
if len(rooms_created) >= 50:
break
# Select random room type based on floor
if floor <= 3:
room_type = random.choice([rt for rt in room_types if 'standard' in rt.name.lower() or 'superior' in rt.name.lower()] or room_types)
elif floor <= 6:
@@ -200,118 +82,58 @@ def seed_rooms(db: Session):
room_type = random.choice([rt for rt in room_types if 'executive' in rt.name.lower() or 'suite' in rt.name.lower()] or room_types)
else:
room_type = random.choice([rt for rt in room_types if 'suite' in rt.name.lower() or 'presidential' in rt.name.lower()] or room_types)
# If no matching room type, use random
if not room_type:
room_type = random.choice(room_types)
# Calculate price (base price + floor premium + view premium + random variation)
base_price = float(room_type.base_price)
floor_premium = (floor - 1) * 5 # +5 per floor
view_premium = 20 if "Ocean" in view_type or "Sea" in view_type or "Beach" in view_type else 0
view_premium += 15 if "Panoramic" in view_type else 0
view_premium += 10 if "Mountain" in view_type else 0
view_premium += 5 if "Pool" in view_type else 0
# Add random variation (-5% to +10% of base price)
random_variation = base_price * random.uniform(-0.05, 0.10)
# Size premium (larger rooms cost more)
floor_premium = (floor - 1) * 5
view_premium = 20 if 'Ocean' in view_type or 'Sea' in view_type or 'Beach' in view_type else 0
view_premium += 15 if 'Panoramic' in view_type else 0
view_premium += 10 if 'Mountain' in view_type else 0
view_premium += 5 if 'Pool' in view_type else 0
random_variation = base_price * random.uniform(-0.05, 0.1)
size_min, size_max = size_range
size_premium = (size_min + size_max) / 2 * 0.5 # ~0.5 per sqm
size_premium = (size_min + size_max) / 2 * 0.5
price = base_price + floor_premium + view_premium + random_variation + size_premium
# Ensure minimum price and round to 2 decimal places
price = max(base_price * 0.95, price)
price = round(price, 2)
# Select amenities
selected_amenities = random.sample(all_amenities, min(amenities_count, len(all_amenities)))
if floor >= 13: # Add premium amenities for luxury suites
if floor >= 13:
premium_count = min(2, len(premium_amenities))
selected_amenities.extend(random.sample(premium_amenities, premium_count))
# Room size
size_min, size_max = size_range
room_size = f"{random.randint(size_min, size_max)} sqm"
# Capacity (based on room type, with some variation)
room_size = f'{random.randint(size_min, size_max)} sqm'
capacity = room_type.capacity
if random.random() > 0.7: # 30% chance to have different capacity
if random.random() > 0.7:
capacity = max(1, capacity + random.randint(-1, 1))
# Room number
room_number = f"{floor}{room_counter % 100:02d}"
room_number = f'{floor}{room_counter % 100:02d}'
room_counter += 1
# Select 3 unique images for each room (ensure we always have images)
# Shuffle the list each time to get different combinations
shuffled_images = luxury_room_images.copy()
random.shuffle(shuffled_images)
image_urls = shuffled_images[:3] # Always take first 3 after shuffle
# Description
descriptions = [
f"Elegantly designed {view_type.lower()} room with modern luxury amenities and breathtaking views.",
f"Spacious {view_type.lower()} accommodation featuring premium furnishings and world-class comfort.",
f"Luxurious {view_type.lower()} room with sophisticated decor and exceptional attention to detail.",
f"Exquisite {view_type.lower()} suite offering unparalleled elegance and personalized service.",
f"Opulent {view_type.lower()} accommodation with bespoke interiors and premium amenities.",
]
image_urls = shuffled_images[:3]
descriptions = [f'Elegantly designed {view_type.lower()} room with modern luxury amenities and breathtaking views.', f'Spacious {view_type.lower()} accommodation featuring premium furnishings and world-class comfort.', f'Luxurious {view_type.lower()} room with sophisticated decor and exceptional attention to detail.', f'Exquisite {view_type.lower()} suite offering unparalleled elegance and personalized service.', f'Opulent {view_type.lower()} accommodation with bespoke interiors and premium amenities.']
description = random.choice(descriptions)
# Status (mostly available, some in maintenance/cleaning)
status_weights = [0.85, 0.05, 0.05, 0.05] # available, occupied, maintenance, cleaning
status = random.choices(
[RoomStatus.available, RoomStatus.occupied, RoomStatus.maintenance, RoomStatus.cleaning],
weights=status_weights
)[0]
# Create room
room = Room(
room_type_id=room_type.id,
room_number=room_number,
floor=floor,
status=status,
price=price,
featured=featured,
capacity=capacity,
room_size=room_size,
view=view_type,
images=json.dumps(image_urls),
amenities=json.dumps(selected_amenities),
description=description
)
status_weights = [0.85, 0.05, 0.05, 0.05]
status = random.choices([RoomStatus.available, RoomStatus.occupied, RoomStatus.maintenance, RoomStatus.cleaning], weights=status_weights)[0]
room = Room(room_type_id=room_type.id, room_number=room_number, floor=floor, status=status, price=price, featured=featured, capacity=capacity, room_size=room_size, view=view_type, images=json.dumps(image_urls), amenities=json.dumps(selected_amenities), description=description)
db.add(room)
rooms_created.append({
'number': room_number,
'floor': floor,
'type': room_type.name,
'view': view_type,
'price': price
})
print(f" ✓ Created Room {room_number} - Floor {floor}, {room_type.name}, {view_type}, {room_size}, €{price:.2f}")
rooms_created.append({'number': room_number, 'floor': floor, 'type': room_type.name, 'view': view_type, 'price': price})
print(f' ✓ Created Room {room_number} - Floor {floor}, {room_type.name}, {view_type}, {room_size}, €{price:.2f}')
db.commit()
print(f"\n✅ Successfully created {len(rooms_created)} luxury rooms!")
print(f"\n📊 Summary:")
featured_count = sum(1 for r in rooms_created if any(
config[5] and r['floor'] >= config[0][0] and r['floor'] <= config[0][1]
for config in room_configs
))
print(f" - Featured rooms: {featured_count}")
print(f" - Floors: {min(r['floor'] for r in rooms_created)} - {max(r['floor'] for r in rooms_created)}")
print(f" - Price range: €{min(r['price'] for r in rooms_created):.2f} - €{max(r['price'] for r in rooms_created):.2f}")
print("=" * 80)
if __name__ == "__main__":
print(f'\n✅ Successfully created {len(rooms_created)} luxury rooms!')
print(f'\n📊 Summary:')
featured_count = sum((1 for r in rooms_created if any((config[5] and r['floor'] >= config[0][0] and (r['floor'] <= config[0][1]) for config in room_configs))))
print(f' - Featured rooms: {featured_count}')
print(f' - Floors: {min((r['floor'] for r in rooms_created))} - {max((r['floor'] for r in rooms_created))}')
print(f' - Price range: €{min((r['price'] for r in rooms_created)):.2f} - €{max((r['price'] for r in rooms_created)):.2f}')
print('=' * 80)
if __name__ == '__main__':
db = get_db()
try:
seed_rooms(db)
except Exception as e:
print(f"\n❌ Error: {e}")
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
db.close()