318 lines
15 KiB
Python
318 lines
15 KiB
Python
#!/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
|
|
from src.models.room_type import RoomType
|
|
from datetime import datetime
|
|
import json
|
|
import random
|
|
|
|
def get_db():
|
|
"""Get database session"""
|
|
db = SessionLocal()
|
|
try:
|
|
return db
|
|
finally:
|
|
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
|
|
room_types = db.query(RoomType).all()
|
|
if not room_types:
|
|
print("❌ No room types found! Please create room types first.")
|
|
return
|
|
|
|
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
|
|
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
|
|
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")
|
|
for booking in bookings_with_rooms:
|
|
db.delete(booking)
|
|
print(f" ✓ Deleted {len(bookings_with_rooms)} booking(s)")
|
|
|
|
# Delete reviews that reference these rooms
|
|
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")
|
|
for review in reviews_with_rooms:
|
|
db.delete(review)
|
|
print(f" ✓ Deleted {len(reviews_with_rooms)} review(s)")
|
|
|
|
# Delete favorites that reference these rooms
|
|
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")
|
|
for favorite in favorites_with_rooms:
|
|
db.delete(favorite)
|
|
print(f" ✓ Deleted {len(favorites_with_rooms)} favorite(s)")
|
|
|
|
# Now delete the rooms
|
|
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),
|
|
]
|
|
|
|
rooms_created = []
|
|
room_counter = 101 # Starting room number
|
|
|
|
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:
|
|
room_type = random.choice([rt for rt in room_types if 'superior' in rt.name.lower() or 'deluxe' in rt.name.lower()] or room_types)
|
|
elif floor <= 9:
|
|
room_type = random.choice([rt for rt in room_types if 'deluxe' in rt.name.lower() or 'executive' in rt.name.lower()] or room_types)
|
|
elif floor <= 12:
|
|
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)
|
|
size_min, size_max = size_range
|
|
size_premium = (size_min + size_max) / 2 * 0.5 # ~0.5 per sqm
|
|
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
|
|
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)
|
|
capacity = room_type.capacity
|
|
if random.random() > 0.7: # 30% chance to have different capacity
|
|
capacity = max(1, capacity + random.randint(-1, 1))
|
|
|
|
# Room number
|
|
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.",
|
|
]
|
|
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
|
|
)
|
|
|
|
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}")
|
|
|
|
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__":
|
|
db = get_db()
|
|
try:
|
|
seed_rooms(db)
|
|
except Exception as e:
|
|
print(f"\n❌ Error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
db.rollback()
|
|
finally:
|
|
db.close()
|
|
|