This commit is contained in:
Iliyan Angelov
2025-12-06 03:27:35 +02:00
parent 7667eb5eda
commit 5a8ca3c475
2211 changed files with 28086 additions and 37066 deletions

5
.env Normal file
View File

@@ -0,0 +1,5 @@
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASS=StrongPassword!@DB
DB_NAME=luxury_hotel_db

View File

@@ -1,5 +1,5 @@
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import create_engine
from sqlalchemy import pool
from alembic import context
import os
@@ -15,17 +15,19 @@ config = context.config
if config.config_file_name is not None:
fileConfig(config.config_file_name)
database_url = settings.database_url
config.set_main_option('sqlalchemy.url', database_url)
target_metadata = Base.metadata
def run_migrations_offline() -> None:
url = config.get_main_option('sqlalchemy.url')
"""Run migrations in 'offline' mode."""
url = database_url
context.configure(url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={'paramstyle': 'named'})
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
connectable = engine_from_config(config.get_section(config.config_ini_section, {}), prefix='sqlalchemy.', poolclass=pool.NullPool)
"""Run migrations in 'online' mode."""
# Create engine directly from URL to avoid ConfigParser interpolation issues
connectable = create_engine(database_url, poolclass=pool.NullPool)
with connectable.connect() as connection:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():

View File

@@ -0,0 +1,92 @@
"""create_user_sessions_table
Revision ID: 54e4d0db31a3
Revises: d709b14aa24a
Create Date: 2025-12-06 01:12:15.123456
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '54e4d0db31a3'
down_revision = 'd709b14aa24a'
branch_labels = None
depends_on = None
def upgrade() -> None:
# Check if table exists before creating
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
if 'user_sessions' not in tables:
# Create user sessions table
op.create_table(
'user_sessions',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('session_token', sa.String(length=255), nullable=False),
sa.Column('refresh_token', sa.String(length=255), nullable=True),
sa.Column('ip_address', sa.String(length=45), nullable=True),
sa.Column('user_agent', sa.String(length=500), nullable=True),
sa.Column('device_info', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False, server_default='1'),
sa.Column('last_activity', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('expires_at', sa.DateTime(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
# Create indexes
op.create_index(op.f('ix_user_sessions_id'), 'user_sessions', ['id'], unique=False)
op.create_index(op.f('ix_user_sessions_user_id'), 'user_sessions', ['user_id'], unique=False)
op.create_index(op.f('ix_user_sessions_session_token'), 'user_sessions', ['session_token'], unique=True)
op.create_index(op.f('ix_user_sessions_refresh_token'), 'user_sessions', ['refresh_token'], unique=True)
op.create_index(op.f('ix_user_sessions_is_active'), 'user_sessions', ['is_active'], unique=False)
op.create_index(op.f('ix_user_sessions_last_activity'), 'user_sessions', ['last_activity'], unique=False)
op.create_index(op.f('ix_user_sessions_expires_at'), 'user_sessions', ['expires_at'], unique=False)
def downgrade() -> None:
# Drop indexes
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
if 'user_sessions' in tables:
try:
op.drop_index(op.f('ix_user_sessions_expires_at'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_last_activity'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_is_active'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_refresh_token'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_session_token'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_user_id'), table_name='user_sessions')
except Exception:
pass
try:
op.drop_index(op.f('ix_user_sessions_id'), table_name='user_sessions')
except Exception:
pass
# Drop table
op.drop_table('user_sessions')

View File

@@ -0,0 +1,114 @@
"""create_gdpr_requests_table
Revision ID: d709b14aa24a
Revises: b1c4d7c154ec
Create Date: 2025-12-06 01:10:15.233886
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'd709b14aa24a'
down_revision = 'b1c4d7c154ec'
branch_labels = None
depends_on = None
def upgrade() -> None:
# Check if table exists before creating
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
if 'gdpr_requests' not in tables:
# Create GDPR requests table
op.create_table(
'gdpr_requests',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('request_type', sa.Enum('data_export', 'data_deletion', 'data_rectification', 'consent_withdrawal', name='gdprrequesttype'), nullable=False),
sa.Column('status', sa.Enum('pending', 'processing', 'completed', 'rejected', 'cancelled', name='gdprrequeststatus'), nullable=False, server_default='pending'),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('user_email', sa.String(length=255), nullable=False),
sa.Column('is_anonymous', sa.Boolean(), nullable=False, server_default='0'),
sa.Column('request_data', sa.JSON(), nullable=True),
sa.Column('verification_token', sa.String(length=255), nullable=True),
sa.Column('verified_at', sa.DateTime(), nullable=True),
sa.Column('processed_by', sa.Integer(), nullable=True),
sa.Column('processed_at', sa.DateTime(), nullable=True),
sa.Column('processing_notes', sa.Text(), nullable=True),
sa.Column('export_file_path', sa.String(length=500), nullable=True),
sa.Column('deletion_log', sa.JSON(), nullable=True),
sa.Column('ip_address', sa.String(length=45), nullable=True),
sa.Column('user_agent', sa.String(length=255), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('updated_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')),
sa.Column('expires_at', sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['processed_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
# Create indexes
op.create_index(op.f('ix_gdpr_requests_id'), 'gdpr_requests', ['id'], unique=False)
op.create_index(op.f('ix_gdpr_requests_request_type'), 'gdpr_requests', ['request_type'], unique=False)
op.create_index(op.f('ix_gdpr_requests_status'), 'gdpr_requests', ['status'], unique=False)
op.create_index(op.f('ix_gdpr_requests_user_id'), 'gdpr_requests', ['user_id'], unique=False)
op.create_index(op.f('ix_gdpr_requests_is_anonymous'), 'gdpr_requests', ['is_anonymous'], unique=False)
op.create_index(op.f('ix_gdpr_requests_created_at'), 'gdpr_requests', ['created_at'], unique=False)
op.create_index(op.f('ix_gdpr_requests_verification_token'), 'gdpr_requests', ['verification_token'], unique=True)
else:
# Table already exists, ensure it has the is_anonymous column if missing
columns = [col['name'] for col in inspector.get_columns('gdpr_requests')]
if 'is_anonymous' not in columns:
op.add_column('gdpr_requests', sa.Column('is_anonymous', sa.Boolean(), nullable=False, server_default='0'))
op.create_index(op.f('ix_gdpr_requests_is_anonymous'), 'gdpr_requests', ['is_anonymous'], unique=False)
# Ensure user_id is nullable
# Note: This might fail if there are existing non-null values, but for a new table it should be fine
try:
op.alter_column('gdpr_requests', 'user_id', existing_type=sa.Integer(), nullable=True)
except Exception:
pass # Column might already be nullable
def downgrade() -> None:
# Drop indexes
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
if 'gdpr_requests' in tables:
try:
op.drop_index(op.f('ix_gdpr_requests_verification_token'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_created_at'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_is_anonymous'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_user_id'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_status'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_request_type'), table_name='gdpr_requests')
except Exception:
pass
try:
op.drop_index(op.f('ix_gdpr_requests_id'), table_name='gdpr_requests')
except Exception:
pass
# Drop table
op.drop_table('gdpr_requests')

View File

@@ -0,0 +1,110 @@
"""add_email_verification_and_enhance_user_security
Revision ID: fe519abcefe7
Revises: 54e4d0db31a3
Create Date: 2025-12-06 01:53:10.797944
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = 'fe519abcefe7'
down_revision = '54e4d0db31a3'
branch_labels = None
depends_on = None
def upgrade() -> None:
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
# Add email_verified column to users table
if 'users' in tables:
columns = [col['name'] for col in inspector.get_columns('users')]
if 'email_verified' not in columns:
# Use MySQL-compatible boolean default
op.add_column('users', sa.Column('email_verified', sa.Boolean(), nullable=False, server_default=sa.text('0')))
# Check if index exists before creating
try:
op.create_index('ix_users_email_verified', 'users', ['email_verified'], unique=False)
except Exception:
pass # Index might already exist
# Add password expiry fields
if 'password_changed_at' not in columns:
op.add_column('users', sa.Column('password_changed_at', sa.DateTime(), nullable=True))
# Check if index exists before creating
try:
op.create_index('ix_users_password_changed_at', 'users', ['password_changed_at'], unique=False)
except Exception:
pass # Index might already exist
# Create password_history table
if 'password_history' not in tables:
op.create_table(
'password_history',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('password_hash', sa.String(length=255), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_password_history_id'), 'password_history', ['id'], unique=False)
op.create_index(op.f('ix_password_history_user_id'), 'password_history', ['user_id'], unique=False)
op.create_index(op.f('ix_password_history_created_at'), 'password_history', ['created_at'], unique=False)
# Create email_verification_tokens table
if 'email_verification_tokens' not in tables:
op.create_table(
'email_verification_tokens',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('token', sa.String(length=255), nullable=False),
sa.Column('email', sa.String(length=100), nullable=False),
sa.Column('expires_at', sa.DateTime(), nullable=False),
sa.Column('used', sa.Boolean(), nullable=False, server_default=sa.text('0')),
sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')),
sa.Column('updated_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_email_verification_tokens_id'), 'email_verification_tokens', ['id'], unique=False)
op.create_index(op.f('ix_email_verification_tokens_user_id'), 'email_verification_tokens', ['user_id'], unique=False)
op.create_index(op.f('ix_email_verification_tokens_token'), 'email_verification_tokens', ['token'], unique=True)
op.create_index(op.f('ix_email_verification_tokens_expires_at'), 'email_verification_tokens', ['expires_at'], unique=False)
def downgrade() -> None:
bind = op.get_bind()
inspector = sa.inspect(bind)
tables = inspector.get_table_names()
# Drop email_verification_tokens table
if 'email_verification_tokens' in tables:
op.drop_index(op.f('ix_email_verification_tokens_expires_at'), table_name='email_verification_tokens')
op.drop_index(op.f('ix_email_verification_tokens_token'), table_name='email_verification_tokens')
op.drop_index(op.f('ix_email_verification_tokens_user_id'), table_name='email_verification_tokens')
op.drop_index(op.f('ix_email_verification_tokens_id'), table_name='email_verification_tokens')
op.drop_table('email_verification_tokens')
# Remove password_history table
if 'password_history' in tables:
op.drop_index(op.f('ix_password_history_created_at'), table_name='password_history')
op.drop_index(op.f('ix_password_history_user_id'), table_name='password_history')
op.drop_index(op.f('ix_password_history_id'), table_name='password_history')
op.drop_table('password_history')
# Remove email_verified and password_changed_at columns from users table
if 'users' in tables:
columns = [col['name'] for col in inspector.get_columns('users')]
if 'password_changed_at' in columns:
op.drop_index('ix_users_password_changed_at', table_name='users')
op.drop_column('users', 'password_changed_at')
if 'email_verified' in columns:
op.drop_index('ix_users_email_verified', table_name='users')
op.drop_column('users', 'email_verified')

View File

@@ -0,0 +1,2 @@
# Seeders package

Binary file not shown.

View File

@@ -0,0 +1,318 @@
"""
About Page Seeder
Seeds the database with comprehensive about page content
All images are from Unsplash (free stock photos)
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_about_page_data():
"""Generate comprehensive about page data with Unsplash images"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.ABOUT,
'title': 'About Our Hotel',
'subtitle': 'A Legacy of Luxury and Exceptional Service',
'description': 'Discover our rich heritage spanning three decades. We have been crafting exceptional experiences for discerning travelers worldwide, blending timeless elegance with modern amenities.',
'content': '<p>For over three decades, we have been at the forefront of luxury hospitality, creating unforgettable experiences for our guests. Our commitment to excellence, attention to detail, and passion for service has made us a destination of choice for travelers seeking the finest in accommodation, dining, and personalized service.</p>',
'meta_title': 'About Us | Luxury Hotel & Resort - Our Story, Mission & Vision',
'meta_description': 'Learn about our luxury hotel\'s rich heritage, mission, vision, and commitment to exceptional hospitality. Discover our story spanning three decades of excellence.',
'meta_keywords': 'about us, hotel history, luxury hospitality, hotel mission, hotel vision, hotel story, luxury hotel',
'og_title': 'About Our Luxury Hotel - A Legacy of Excellence',
'og_description': 'Discover our rich heritage spanning three decades. We have been crafting exceptional experiences for discerning travelers worldwide.',
'og_image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/about',
'hero_title': 'Our Story',
'hero_subtitle': 'Three Decades of Excellence in Luxury Hospitality',
'hero_image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1920&h=1080&fit=crop',
'hero_video_url': None,
'hero_video_poster': None,
'about_hero_image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1400&h=900&fit=crop',
'story_content': '<p>Founded in 1993, our hotel began as a vision to create a sanctuary of luxury and sophistication in the heart of the city. What started as a small boutique property has grown into an internationally recognized destination, consistently ranked among the world\'s finest hotels.</p><p>Over the years, we have welcomed countless guests, from world leaders and celebrities to families celebrating special moments. Each guest has contributed to our story, and we are honored to have been part of their journeys.</p><p>Our commitment to excellence has never wavered. We continuously invest in our facilities, train our staff to the highest standards, and innovate to exceed expectations. Today, we stand as a testament to what is possible when passion meets dedication.</p>',
'mission': '<p>Our mission is to provide unparalleled luxury experiences that exceed expectations. We are committed to creating memorable moments for every guest through exceptional service, world-class amenities, and attention to every detail. We strive to be the benchmark of excellence in hospitality, where every interaction reflects our dedication to perfection.</p>',
'vision': '<p>Our vision is to be the world\'s most respected luxury hotel brand, recognized for our unwavering commitment to excellence, innovation, and sustainable luxury. We envision a future where our guests feel truly at home, where our team members are proud ambassadors of our values, and where our community benefits from our presence and commitment to responsible hospitality.</p>',
'values': json.dumps([
{
'icon': 'heart',
'title': 'Excellence',
'description': 'We strive for perfection in every detail, ensuring your experience exceeds expectations. Excellence is not a goal but a standard we maintain in everything we do.'
},
{
'icon': 'users',
'title': 'Hospitality',
'description': 'Our dedicated team provides warm, personalized service to make you feel at home. We believe true hospitality comes from the heart and is reflected in every interaction.'
},
{
'icon': 'leaf',
'title': 'Sustainability',
'description': 'Committed to eco-friendly practices for a better future and a delightful stay. We balance luxury with responsibility, ensuring our operations protect the environment for future generations.'
},
{
'icon': 'award',
'title': 'Quality',
'description': 'We maintain the highest standards in service, amenities, and guest satisfaction. Quality is embedded in our culture and evident in every aspect of your stay.'
},
{
'icon': 'handshake',
'title': 'Integrity',
'description': 'We conduct our business with honesty, transparency, and ethical practices. Trust is the foundation of our relationships with guests, partners, and our community.'
},
{
'icon': 'lightbulb',
'title': 'Innovation',
'description': 'We embrace new technologies and creative solutions to enhance your experience. Innovation drives us to continuously improve and stay ahead of industry trends.'
}
]),
'team': json.dumps([
{
'name': 'Sarah Johnson',
'position': 'General Manager',
'bio': 'With over 20 years of experience in luxury hospitality, Sarah leads our team with passion and dedication. Her commitment to excellence has been instrumental in our success.',
'image': 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop&crop=face',
'social': {
'linkedin': 'https://linkedin.com/in/sarahjohnson',
'twitter': 'https://twitter.com/sarahjohnson'
}
},
{
'name': 'Michael Chen',
'position': 'Executive Chef',
'bio': 'Award-winning chef with a passion for creating culinary masterpieces. Michael brings innovative flavors and techniques to our restaurants, delighting guests with every dish.',
'image': 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=400&fit=crop&crop=face',
'social': {
'linkedin': 'https://linkedin.com/in/michaelchen',
'instagram': 'https://instagram.com/chefmichael'
}
},
{
'name': 'Emily Rodriguez',
'position': 'Director of Guest Services',
'bio': 'Emily ensures every guest receives personalized attention and exceptional service. Her warm personality and attention to detail make her a favorite among our guests.',
'image': 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&h=400&fit=crop&crop=face',
'social': {
'linkedin': 'https://linkedin.com/in/emilyrodriguez'
}
},
{
'name': 'David Thompson',
'position': 'Spa Director',
'bio': 'With expertise in wellness and holistic healing, David has created a world-class spa experience. His innovative treatments and serene environment provide guests with ultimate relaxation.',
'image': 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=400&h=400&fit=crop&crop=face',
'social': {
'linkedin': 'https://linkedin.com/in/davidthompson'
}
}
]),
'timeline': json.dumps([
{
'year': '1993',
'title': 'Foundation',
'description': 'Hotel founded with a vision to create a luxury destination. Opened with 50 rooms and a commitment to exceptional service.',
'image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=800&h=600&fit=crop'
},
{
'year': '2000',
'title': 'First Expansion',
'description': 'Expanded to 150 rooms and added our first fine dining restaurant. Received our first five-star rating from international travel guides.',
'image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&h=600&fit=crop'
},
{
'year': '2008',
'title': 'Spa & Wellness Center',
'description': 'Opened our world-class spa and wellness center, introducing holistic wellness programs and luxury treatments.',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=800&h=600&fit=crop'
},
{
'year': '2015',
'title': 'Major Renovation',
'description': 'Completed a comprehensive renovation, modernizing all rooms and public spaces while preserving our classic elegance.',
'image': 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=800&h=600&fit=crop'
},
{
'year': '2020',
'title': 'Sustainability Initiative',
'description': 'Launched our comprehensive sustainability program, achieving carbon neutrality and implementing eco-friendly practices throughout the property.',
'image': 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=800&h=600&fit=crop'
},
{
'year': '2023',
'title': 'Award Recognition',
'description': 'Received "Best Luxury Hotel" award and maintained our five-star rating. Celebrated 30 years of excellence in hospitality.',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=800&h=600&fit=crop'
}
]),
'achievements': json.dumps([
{
'icon': 'trophy',
'title': 'Best Luxury Hotel 2023',
'description': 'Awarded by International Hospitality Association',
'year': '2023',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=400&h=400&fit=crop'
},
{
'icon': 'star',
'title': 'Five-Star Rating',
'description': 'Consistently rated five-star by global travel guides',
'year': '2020-2023',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=400&h=400&fit=crop'
},
{
'icon': 'medal',
'title': 'Excellence in Service',
'description': 'Recognized for outstanding customer service and guest satisfaction',
'year': '2022',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=400&h=400&fit=crop'
},
{
'icon': 'leaf',
'title': 'Green Hotel Certification',
'description': 'Certified for sustainable practices and environmental responsibility',
'year': '2021',
'image': 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=400&h=400&fit=crop'
},
{
'icon': 'users',
'title': 'Guest Choice Award',
'description': 'Voted favorite luxury hotel by guests worldwide',
'year': '2023',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=400&h=400&fit=crop'
},
{
'icon': 'award',
'title': 'Culinary Excellence',
'description': 'Restaurant awarded Michelin star for exceptional cuisine',
'year': '2022',
'image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=400&h=400&fit=crop'
}
]),
'stats': json.dumps([
{'number': '50000+', 'label': 'Happy Guests', 'icon': 'users'},
{'number': '30+', 'label': 'Years of Excellence', 'icon': 'calendar'},
{'number': '150+', 'label': 'Awards Won', 'icon': 'award'},
{'number': '98%', 'label': 'Guest Satisfaction', 'icon': 'star'},
{'number': '200+', 'label': 'Team Members', 'icon': 'users'},
{'number': '115', 'label': 'Luxury Rooms', 'icon': 'home'}
]),
'stats_section_title': 'Our Achievements in Numbers',
'stats_section_subtitle': 'A legacy built on excellence and guest satisfaction',
'testimonials': json.dumps([
{
'name': 'James Wilson',
'title': 'VIP Guest',
'quote': 'The level of luxury and attention to detail is simply extraordinary. This hotel understands what true hospitality means.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Sophia Lee',
'title': 'Travel Blogger',
'quote': 'Every aspect of my stay was flawless. The service, the amenities, the ambiance - truly a five-star experience.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'David Chen',
'title': 'CEO, Global Corp',
'quote': 'An impeccable hotel with outstanding service. This is what luxury hospitality should be - perfect in every way.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Maria Garcia',
'title': 'Frequent Guest',
'quote': 'I\'ve stayed at many luxury hotels, but this one stands out. The personal attention and genuine care for guests is remarkable.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=200&h=200&fit=crop&crop=face'
}
]),
'testimonials_section_title': 'What Our Guests Say',
'testimonials_section_subtitle': 'Stories from our valued guests',
'gallery_images': json.dumps([
'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?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-1544161515-4ab6ce6db874?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=1200&h=800&fit=crop'
]),
'gallery_section_title': 'Our Photo Gallery',
'gallery_section_subtitle': 'A glimpse into our world of luxury',
'contact_info': json.dumps({
'phone': '+1 (555) 123-4567',
'email': 'info@luxuryhotel.com',
'address': '123 Luxury Avenue, Premium City, PC 12345'
}),
'social_links': json.dumps({
'facebook': 'https://facebook.com/luxuryhotel',
'twitter': 'https://twitter.com/luxuryhotel',
'instagram': 'https://instagram.com/luxuryhotel',
'linkedin': 'https://linkedin.com/company/luxuryhotel',
'youtube': 'https://youtube.com/luxuryhotel'
}),
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_about_page(db: Session):
"""Seed about page content into the database"""
try:
about_data = get_about_page_data()
# Check if about page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.ABOUT).first()
if existing_content:
logger.info('Updating existing about page content...')
for key, value in about_data.items():
if key not in ['id', 'page_type', 'created_at']: # Don't update primary key or creation date
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new about page content...')
about_page = PageContent(**about_data)
db.add(about_page)
db.commit()
logger.info('About page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding about page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_about_page(db)
except Exception as e:
logger.error(f'Failed to seed about page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,200 @@
"""
Accessibility Page Seeder
Seeds the database with comprehensive accessibility information
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_accessibility_page_data():
"""Generate comprehensive accessibility page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.ACCESSIBILITY,
'title': 'Accessibility',
'subtitle': 'Committed to Accessibility for All',
'description': 'We are committed to providing accessible facilities and services for all our guests. Learn about our accessibility features and accommodations.',
'content': """
<h2>Our Commitment to Accessibility</h2>
<p>At Luxury Hotel & Resort, we are committed to ensuring that our facilities and services are accessible to all guests, including those with disabilities. We strive to comply with the Americans with Disabilities Act (ADA) and continuously work to improve accessibility throughout our property.</p>
<h2>Accessible Accommodations</h2>
<h3>Accessible Guest Rooms</h3>
<p>We offer several accessible guest rooms designed to meet ADA requirements, featuring:</p>
<ul>
<li>Wider doorways (minimum 32 inches)</li>
<li>Roll-in showers or accessible bathtubs with grab bars</li>
<li>Lowered light switches and thermostats</li>
<li>Visual door knockers and phone alerts</li>
<li>Accessible vanities and bathroom fixtures</li>
<li>Closed-captioned televisions</li>
<li>Accessible closet rods and shelves</li>
</ul>
<h3>Room Features</h3>
<ul>
<li>Hearing-impaired kits available upon request</li>
<li>Visual smoke detectors</li>
<li>TTY/TDD devices available</li>
<li>Accessible furniture and seating</li>
</ul>
<h2>Public Areas & Facilities</h2>
<h3>Entrance & Lobby</h3>
<ul>
<li>Wheelchair-accessible main entrance</li>
<li>Automatic doors at main entrance</li>
<li>Accessible front desk with lowered counter</li>
<li>Accessible seating areas in lobby</li>
</ul>
<h3>Dining Facilities</h3>
<ul>
<li>Accessible dining areas in all restaurants</li>
<li>Accessible tables and seating</li>
<li>Menus available in large print or braille upon request</li>
<li>Staff trained to assist guests with disabilities</li>
</ul>
<h3>Recreation & Fitness</h3>
<ul>
<li>Accessible fitness center with adaptive equipment</li>
<li>Accessible pool area with pool lift (available upon request)</li>
<li>Accessible spa facilities</li>
</ul>
<h3>Meeting & Event Spaces</h3>
<ul>
<li>Accessible meeting rooms</li>
<li>Accessible restrooms in meeting areas</li>
<li>Assistive listening devices available</li>
<li>Sign language interpreters available with advance notice</li>
</ul>
<h2>Parking & Transportation</h2>
<ul>
<li>Accessible parking spaces near main entrance</li>
<li>Van-accessible parking spaces</li>
<li>Accessible valet service</li>
<li>Accessible transportation available upon request</li>
</ul>
<h2>Service Animals</h2>
<p>Service animals are welcome throughout our property. We comply with all applicable laws regarding service animals and do not charge additional fees for service animals.</p>
<h2>Assistive Devices & Services</h2>
<h3>Available Upon Request</h3>
<ul>
<li>TTY/TDD devices</li>
<li>Visual door knockers</li>
<li>Hearing-impaired kits</li>
<li>Closed-captioned televisions</li>
<li>Large print menus and materials</li>
<li>Braille materials (available for select items)</li>
<li>Assistive listening devices for meetings</li>
<li>Sign language interpreters (with advance notice)</li>
</ul>
<h2>Website Accessibility</h2>
<p>We are committed to making our website accessible to all users. Our website is designed to comply with WCAG 2.1 Level AA standards. If you encounter any accessibility barriers on our website, please contact us so we can address the issue.</p>
<h2>Communication</h2>
<p>Our staff is trained to communicate effectively with guests who have disabilities. We can provide information in alternative formats upon request, including:</p>
<ul>
<li>Large print materials</li>
<li>Written materials</li>
<li>Assistance with reading menus or other materials</li>
</ul>
<h2>Accessibility Concerns & Feedback</h2>
<p>We welcome feedback from our guests regarding accessibility. If you have any concerns or suggestions for improvement, please contact us:</p>
<ul>
<li><strong>Email:</strong> accessibility@luxuryhotel.com</li>
<li><strong>Phone:</strong> +1 (555) 123-4567</li>
<li><strong>TTY/TDD:</strong> +1 (555) 123-4568</li>
<li><strong>Address:</strong> 123 Luxury Avenue, Premium City, PC 12345, United States</li>
</ul>
<h2>Reservations</h2>
<p>When making a reservation, please inform us of any specific accessibility needs so we can ensure your room and services meet your requirements. Our reservations team is available 24/7 to assist you.</p>
<ul>
<li><strong>Reservations Phone:</strong> +1 (555) 123-4567</li>
<li><strong>Reservations Email:</strong> reservations@luxuryhotel.com</li>
</ul>
<h2>Ongoing Improvements</h2>
<p>We are continuously working to improve accessibility throughout our property. We regularly review and update our facilities and services to better serve all our guests. If you have suggestions for improvements, we would love to hear from you.</p>
<p><em>Last Updated: {}</em></p>
""".format(now.strftime('%B %d, %Y')),
'meta_title': 'Accessibility | Luxury Hotel & Resort - Accessible Facilities',
'meta_description': 'Learn about our accessible facilities and services. We are committed to providing accessible accommodations for all guests.',
'meta_keywords': 'accessibility, ADA, accessible hotel, wheelchair accessible, disability accommodations, accessible rooms',
'og_title': 'Accessibility - Luxury Hotel & Resort',
'og_description': 'Committed to accessibility for all. Learn about our accessible facilities and services.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/accessibility',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_accessibility_page(db: Session):
"""Seed accessibility page content into the database"""
try:
accessibility_data = get_accessibility_page_data()
# Check if accessibility page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.ACCESSIBILITY).first()
if existing_content:
logger.info('Updating existing accessibility page content...')
for key, value in accessibility_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new accessibility page content...')
accessibility_page = PageContent(**accessibility_data)
db.add(accessibility_page)
db.commit()
logger.info('Accessibility page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding accessibility page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_accessibility_page(db)
except Exception as e:
logger.error(f'Failed to seed accessibility page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,315 @@
"""
Banner Seeder
Seeds the database with comprehensive banners for different positions
All images are from Unsplash (free stock photos)
"""
import sys
from pathlib import Path
from datetime import datetime, timezone, timedelta
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.content.models.banner import Banner
from src.shared.config.logging_config import get_logger
logger = get_logger(__name__)
def get_banner_data():
"""Generate comprehensive banner data with Unsplash images"""
now = datetime.now(timezone.utc)
future_date = now + timedelta(days=365) # Banners active for 1 year
banners = [
# Home Page Banners
{
'title': 'Welcome to Luxury',
'description': 'Experience unparalleled elegance and world-class service at our award-winning hotel. Discover sophisticated rooms, exceptional dining, and modern amenities.',
'image_url': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1920&h=1080&fit=crop',
'link_url': '/rooms',
'position': 'home',
'display_order': 1,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Special Summer Offer',
'description': 'Book now and save up to 30% on your summer getaway! Perfect for families, couples, and solo travelers. Limited time offer.',
'image_url': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=1920&h=1080&fit=crop',
'link_url': '/book',
'position': 'home',
'display_order': 2,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Fine Dining Experience',
'description': 'Savor exquisite cuisine at our Michelin-starred restaurants. Enjoy international flavors, local specialties, and expertly curated wine pairings.',
'image_url': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1920&h=1080&fit=crop',
'link_url': '/services',
'position': 'home',
'display_order': 3,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Luxury Spa & Wellness',
'description': 'Rejuvenate at our world-class spa with personalized treatments, therapeutic massages, steam rooms, saunas, and yoga classes.',
'image_url': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1920&h=1080&fit=crop',
'link_url': '/services',
'position': 'home',
'display_order': 4,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Business Events & Conferences',
'description': 'Host your corporate event in our state-of-the-art facilities. Versatile spaces for intimate meetings to large conferences with cutting-edge technology.',
'image_url': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1920&h=1080&fit=crop',
'link_url': '/contact',
'position': 'home',
'display_order': 5,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# Rooms Page Banners
{
'title': 'Luxurious Suites',
'description': 'Elegantly designed suites with spacious layouts, separate living areas, marble bathrooms, and private balconies with panoramic views. Smart room controls and premium amenities included.',
'image_url': 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1920&h=1080&fit=crop',
'link_url': '/rooms',
'position': 'rooms',
'display_order': 1,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Presidential Suite',
'description': 'Ultimate luxury in our exclusive 2,000+ sq ft suite. Features grand living room, formal dining, fully equipped kitchen, private terrace, and personal butler service. Perfect for VIP guests.',
'image_url': 'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1920&h=1080&fit=crop',
'link_url': '/rooms',
'position': 'rooms',
'display_order': 2,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Ocean View Rooms',
'description': 'Breathtaking ocean views from private balconies. Spacious rooms with floor-to-ceiling windows, coastal decor, and premium furnishings. Perfect for romantic getaways.',
'image_url': 'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1920&h=1080&fit=crop',
'link_url': '/rooms',
'position': 'rooms',
'display_order': 3,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# About Page Banners
{
'title': 'Our Story',
'description': 'Discover our rich heritage spanning three decades. Founded to redefine luxury hospitality, we\'ve grown into an internationally recognized destination with timeless elegance.',
'image_url': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1920&h=1080&fit=crop',
'link_url': '/about',
'position': 'about',
'display_order': 1,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Award-Winning Service',
'description': 'Recognized globally for exceptional hospitality with prestigious awards including five-star ratings and "Best Luxury Hotel" honors. Our trained team delivers service beyond expectations.',
'image_url': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=1920&h=1080&fit=crop',
'link_url': '/about',
'position': 'about',
'display_order': 2,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# Contact Page Banner
{
'title': 'Get in Touch',
'description': 'Our friendly team is available 24/7 for reservations, inquiries, and special requests. Reach us by phone, email, or visit our front desk. Concierge assistance available.',
'image_url': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1920&h=1080&fit=crop',
'link_url': '/contact',
'position': 'contact',
'display_order': 1,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# Services Page Banners
{
'title': 'Premium Services',
'description': 'Enjoy personalized butler service, private airport transfers, VIP lounge access, and priority reservations. Business center, city tours, and special occasion planning available.',
'image_url': 'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=1920&h=1080&fit=crop',
'link_url': '/services',
'position': 'services',
'display_order': 1,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': '24/7 Concierge Service',
'description': 'Our dedicated concierge team is available around the clock. We assist with restaurant reservations, event tickets, transportation, exclusive experiences, and special occasions.',
'image_url': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1920&h=1080&fit=crop',
'link_url': '/services',
'position': 'services',
'display_order': 2,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# Promotional Banners (can be used across pages)
{
'title': 'Early Bird Special',
'description': 'Book 30 days in advance and save 20%! Perfect for travelers who plan ahead. Applies to all room types. Terms and conditions apply.',
'image_url': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1920&h=1080&fit=crop',
'link_url': '/book',
'position': 'home',
'display_order': 6,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Weekend Getaway Package',
'description': 'All-inclusive weekend package with luxurious accommodation, daily breakfast, and full spa access. Late checkout included. Available Friday through Sunday.',
'image_url': 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1920&h=1080&fit=crop',
'link_url': '/book',
'position': 'home',
'display_order': 7,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Honeymoon Package',
'description': 'Romantic honeymoon package includes luxurious suite, breakfast in bed, candlelit dinner with champagne, couples spa treatments, and special amenities.',
'image_url': 'https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1920&h=1080&fit=crop',
'link_url': '/book',
'position': 'home',
'display_order': 8,
'is_active': True,
'start_date': now,
'end_date': future_date
},
# Footer/General Banners
{
'title': 'Join Our Loyalty Program',
'description': 'Earn points with every stay. Redeem for free nights, upgrades, dining credits, and spa treatments. Multiple tier levels from Silver to Platinum. Join free today!',
'image_url': 'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=1920&h=1080&fit=crop',
'link_url': '/loyalty',
'position': 'home',
'display_order': 9,
'is_active': True,
'start_date': now,
'end_date': future_date
},
{
'title': 'Gift Cards Available',
'description': 'Give the gift of luxury with our hotel gift cards. Perfect for any occasion. Usable for accommodations, dining, spa, and all services. Never expire. Purchase online or at front desk.',
'image_url': 'https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=1920&h=1080&fit=crop',
'link_url': '/gift-cards',
'position': 'home',
'display_order': 10,
'is_active': True,
'start_date': now,
'end_date': future_date
}
]
return banners
def seed_banners(db: Session, clear_existing: bool = False):
"""Seed banners into the database"""
try:
if clear_existing:
logger.info('Clearing existing banners...')
db.query(Banner).delete()
db.commit()
banners_data = get_banner_data()
created_count = 0
updated_count = 0
for banner_data in banners_data:
# Check if banner with same title and position already exists
existing = db.query(Banner).filter(
Banner.title == banner_data['title'],
Banner.position == banner_data['position']
).first()
if existing:
logger.info(f'Updating existing banner: {banner_data["title"]} ({banner_data["position"]})')
# Update existing banner
for key, value in banner_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.now(timezone.utc)
updated_count += 1
else:
logger.info(f'Creating new banner: {banner_data["title"]} ({banner_data["position"]})')
# Create new banner
banner = Banner(**banner_data)
db.add(banner)
created_count += 1
db.commit()
logger.info(f'Banner seeding completed! Created: {created_count}, Updated: {updated_count}')
return created_count, updated_count
except Exception as e:
logger.error(f'Error seeding banners: {str(e)}', exc_info=True)
db.rollback()
raise
def main():
"""Main function to run the seeder"""
import argparse
parser = argparse.ArgumentParser(description='Seed banners into the database')
parser.add_argument(
'--clear',
action='store_true',
help='Clear existing banners before seeding'
)
args = parser.parse_args()
logger.info('Starting banner seeder...')
db = SessionLocal()
try:
created, updated = seed_banners(db, clear_existing=args.clear)
logger.info(f'Banner seeder completed successfully! Created: {created}, Updated: {updated}')
except Exception as e:
logger.error(f'Failed to seed banners: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,320 @@
"""
Blog Seeder
Seeds the database with blog posts
All images are from Unsplash (free stock photos)
"""
import json
import sys
import re
from pathlib import Path
from datetime import datetime, timezone, timedelta
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.blog import BlogPost
from src.auth.models.user import User
# Import all models to ensure relationships are loaded correctly
from src.models import *
logger = get_logger(__name__)
def slugify(text):
"""Convert text to URL-friendly slug"""
text = text.lower()
text = re.sub(r'[^\w\s-]', '', text)
text = re.sub(r'[-\s]+', '-', text)
return text.strip('-')
def get_blog_posts_data(author_id: int):
"""Generate comprehensive blog posts data with Unsplash images"""
now = datetime.now(timezone.utc)
posts = [
{
'title': '10 Tips for Planning the Perfect Luxury Hotel Stay',
'slug': '10-tips-planning-perfect-luxury-hotel-stay',
'excerpt': 'Discover expert tips to make your luxury hotel experience unforgettable. From booking strategies to maximizing amenities, we share insider secrets.',
'content': '''<p>Planning a luxury hotel stay requires attention to detail and insider knowledge. Whether you're celebrating a special occasion or simply treating yourself, these tips will help you make the most of your experience.</p>
<h2>1. Book in Advance</h2>
<p>Luxury hotels often offer early bird discounts and better room availability when you book well in advance. Planning ahead also gives you access to special packages and upgrades.</p>
<h2>2. Communicate Your Preferences</h2>
<p>Don't hesitate to communicate your preferences when booking. Whether you prefer a high floor, specific room amenities, or have dietary restrictions, hotels are happy to accommodate.</p>
<h2>3. Join Loyalty Programs</h2>
<p>Most luxury hotels offer loyalty programs with exclusive benefits. Join before your stay to earn points, receive member rates, and enjoy perks like late checkout.</p>
<h2>4. Explore Hotel Amenities</h2>
<p>Take advantage of all the hotel has to offer - from spa treatments to fine dining. Many luxury hotels have world-class facilities that are worth experiencing.</p>
<h2>5. Use Concierge Services</h2>
<p>The concierge team is your gateway to the best local experiences. They can secure restaurant reservations, arrange transportation, and provide insider recommendations.</p>
<h2>6. Check for Special Packages</h2>
<p>Look for special packages that bundle accommodations with dining, spa, or local experiences. These often provide better value than booking separately.</p>
<h2>7. Review Cancellation Policies</h2>
<p>Understand the cancellation and modification policies before booking. Flexible rates may cost more but provide peace of mind.</p>
<h2>8. Pack Appropriately</h2>
<p>While luxury hotels provide many amenities, bringing appropriate attire for dining and activities ensures you're prepared for all experiences.</p>
<h2>9. Arrive Early or Late</h2>
<p>If possible, arrive early or late to avoid peak check-in times. This often results in better service and sometimes room upgrades if available.</p>
<h2>10. Leave Reviews</h2>
<p>Share your experience through reviews. Hotels value feedback and often reward guests who provide detailed, constructive reviews.</p>
<p>Remember, a luxury hotel stay is about creating memories. Take your time, enjoy every moment, and don't hesitate to ask for what will make your stay perfect.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=5),
'is_published': True,
'tags': json.dumps(['travel tips', 'luxury travel', 'hotel guide', 'vacation planning']),
'meta_title': '10 Tips for Planning the Perfect Luxury Hotel Stay | Travel Guide',
'meta_description': 'Expert tips for planning an unforgettable luxury hotel stay. Learn booking strategies, how to maximize amenities, and insider secrets.',
'meta_keywords': 'luxury hotel tips, hotel booking guide, travel planning, luxury travel advice',
'sections': None
},
{
'title': 'The Art of Fine Dining: A Culinary Journey at Our Hotel',
'slug': 'art-fine-dining-culinary-journey',
'excerpt': 'Explore our award-winning restaurants and discover the culinary philosophy behind our Michelin-starred dining experiences.',
'content': '''<p>Fine dining is an art form that combines exceptional ingredients, masterful technique, and impeccable service. At our hotel, we've created culinary experiences that celebrate both tradition and innovation.</p>
<h2>Our Culinary Philosophy</h2>
<p>Our chefs believe in using the finest locally sourced ingredients, supporting sustainable practices, and creating dishes that tell a story. Each plate is a masterpiece, carefully crafted to delight all senses.</p>
<h2>Signature Dishes</h2>
<p>From our signature truffle risotto to our perfectly aged wagyu beef, every dish on our menu has been thoughtfully created. Our tasting menus offer a journey through flavors, textures, and culinary traditions.</p>
<h2>Wine Pairing Excellence</h2>
<p>Our sommeliers curate wine pairings that enhance every dish. With an extensive cellar featuring rare vintages and hidden gems, we ensure the perfect complement to your meal.</p>
<h2>Private Dining Experiences</h2>
<p>For special occasions, our private dining rooms offer intimate settings with personalized menus. Our chefs work closely with guests to create unforgettable culinary experiences.</p>
<p>Join us for a culinary journey that celebrates the art of fine dining and creates memories that last a lifetime.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=10),
'is_published': True,
'tags': json.dumps(['fine dining', 'culinary', 'restaurant', 'gourmet']),
'meta_title': 'The Art of Fine Dining | Culinary Excellence',
'meta_description': 'Discover our award-winning restaurants and Michelin-starred dining experiences. Explore our culinary philosophy and signature dishes.',
'meta_keywords': 'fine dining, Michelin restaurant, gourmet cuisine, culinary experience',
'sections': None
},
{
'title': 'Wellness and Relaxation: Your Guide to Our Spa & Wellness Center',
'slug': 'wellness-relaxation-spa-wellness-center-guide',
'excerpt': 'Discover our world-class spa and wellness center. Learn about our treatments, wellness programs, and how to achieve ultimate relaxation.',
'content': '''<p>In today's fast-paced world, taking time for wellness and relaxation is essential. Our spa and wellness center offers a sanctuary where you can rejuvenate your mind, body, and spirit.</p>
<h2>Our Wellness Philosophy</h2>
<p>We believe in holistic wellness that addresses physical, mental, and emotional well-being. Our treatments combine traditional techniques with modern innovations to provide comprehensive care.</p>
<h2>Signature Treatments</h2>
<p>From our signature deep tissue massages to rejuvenating facials, each treatment is customized to your needs. Our expert therapists use premium products and time-tested techniques.</p>
<h2>Wellness Programs</h2>
<p>Beyond individual treatments, we offer comprehensive wellness programs including yoga classes, meditation sessions, and personalized fitness consultations.</p>
<h2>The Spa Environment</h2>
<p>Our spa facilities include steam rooms, saunas, relaxation lounges, and private treatment rooms. Every detail is designed to create a serene, peaceful atmosphere.</p>
<h2>Couples Experiences</h2>
<p>Share the relaxation experience with our couples treatments. Perfect for romantic getaways or celebrating special moments together.</p>
<p>Whether you're seeking stress relief, muscle recovery, or simply a moment of tranquility, our spa and wellness center provides the perfect escape.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=15),
'is_published': True,
'tags': json.dumps(['spa', 'wellness', 'relaxation', 'self-care']),
'meta_title': 'Wellness and Relaxation Guide | Spa & Wellness Center',
'meta_description': 'Discover our world-class spa and wellness center. Learn about treatments, wellness programs, and how to achieve ultimate relaxation.',
'meta_keywords': 'spa, wellness, relaxation, massage, hotel spa',
'sections': None
},
{
'title': 'Sustainable Luxury: Our Commitment to Environmental Responsibility',
'slug': 'sustainable-luxury-environmental-responsibility',
'excerpt': 'Learn about our sustainability initiatives and how we balance luxury with environmental responsibility. Discover our green practices and commitment to the planet.',
'content': '''<p>Luxury and sustainability are not mutually exclusive. At our hotel, we've proven that you can enjoy world-class amenities while protecting the environment for future generations.</p>
<h2>Our Sustainability Mission</h2>
<p>We're committed to reducing our environmental footprint through innovative practices, renewable energy, and responsible sourcing. Our goal is carbon neutrality while maintaining the highest standards of luxury.</p>
<h2>Green Building Practices</h2>
<p>Our facilities incorporate energy-efficient systems, water conservation measures, and sustainable materials. We continuously invest in technologies that reduce our environmental impact.</p>
<h2>Local and Sustainable Sourcing</h2>
<p>We prioritize local suppliers and sustainable ingredients in our restaurants. This not only reduces our carbon footprint but also supports local communities and ensures the freshest quality.</p>
<h2>Waste Reduction</h2>
<p>Through comprehensive recycling programs, composting, and waste reduction initiatives, we've significantly decreased our waste output. Single-use plastics have been eliminated throughout the property.</p>
<h2>Guest Participation</h2>
<p>We invite guests to join us in our sustainability efforts through optional programs like towel reuse, energy conservation, and supporting local conservation projects.</p>
<p>Together, we can enjoy luxury experiences while protecting our planet. Every small action contributes to a more sustainable future.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=20),
'is_published': True,
'tags': json.dumps(['sustainability', 'environment', 'green hotel', 'eco-friendly']),
'meta_title': 'Sustainable Luxury | Environmental Responsibility',
'meta_description': 'Learn about our sustainability initiatives and how we balance luxury with environmental responsibility. Discover our green practices.',
'meta_keywords': 'sustainable luxury, green hotel, environmental responsibility, eco-friendly',
'sections': None
},
{
'title': 'Celebrating 30 Years of Excellence in Hospitality',
'slug': 'celebrating-30-years-excellence-hospitality',
'excerpt': 'Join us as we celebrate three decades of providing exceptional hospitality. Learn about our journey, milestones, and vision for the future.',
'content': '''<p>This year marks a significant milestone - 30 years of excellence in hospitality. From our humble beginnings to becoming an internationally recognized destination, our journey has been remarkable.</p>
<h2>Our Beginnings</h2>
<p>Founded in 1993, we started with a simple vision: to create a sanctuary of luxury and sophistication. What began as a small boutique property has grown into a world-class destination.</p>
<h2>Key Milestones</h2>
<p>Over three decades, we've achieved numerous milestones - from our first five-star rating to receiving international awards. Each achievement represents our commitment to excellence.</p>
<h2>Our Team</h2>
<p>None of this would be possible without our dedicated team. Their passion, professionalism, and commitment to service excellence have been the foundation of our success.</p>
<h2>Looking Forward</h2>
<p>As we celebrate this milestone, we're also looking to the future. We continue to innovate, invest in our facilities, and enhance our services to exceed guest expectations.</p>
<h2>Thank You</h2>
<p>To all our guests, partners, and team members - thank you for being part of our journey. Here's to the next 30 years of creating unforgettable experiences.</p>
<p>Join us in celebrating this special anniversary with special packages and events throughout the year.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=25),
'is_published': True,
'tags': json.dumps(['anniversary', 'hotel history', 'milestone', 'celebration']),
'meta_title': 'Celebrating 30 Years of Excellence | Hotel Anniversary',
'meta_description': 'Join us as we celebrate three decades of providing exceptional hospitality. Learn about our journey, milestones, and vision for the future.',
'meta_keywords': 'hotel anniversary, 30 years, hospitality excellence, milestone',
'sections': None
},
{
'title': 'The Ultimate Business Traveler\'s Guide to Our Hotel',
'slug': 'ultimate-business-traveler-guide',
'excerpt': 'Discover how our hotel caters to business travelers with state-of-the-art facilities, convenient services, and amenities designed for productivity and comfort.',
'content': '''<p>Business travel doesn't have to mean sacrificing comfort or productivity. Our hotel is designed specifically to meet the needs of modern business travelers.</p>
<h2>Business Facilities</h2>
<p>Our fully equipped business center provides everything you need - from high-speed internet to meeting rooms with state-of-the-art AV equipment. Work seamlessly from anywhere in the hotel.</p>
<h2>Convenient Services</h2>
<p>Express check-in and checkout, 24/7 concierge service, and flexible meeting arrangements ensure your business needs are met efficiently. We understand that time is valuable.</p>
<h2>Comfortable Accommodations</h2>
<p>Our rooms feature dedicated workspaces, ergonomic furniture, and premium amenities. After a long day of meetings, relax in comfort and recharge for tomorrow.</p>
<h2>Networking Opportunities</h2>
<p>Our restaurants and lounges provide perfect settings for business networking. Whether hosting clients or connecting with colleagues, we provide the ideal atmosphere.</p>
<h2>Wellness for Business Travelers</h2>
<p>Maintain your wellness routine with our fitness center, spa services, and healthy dining options. We help you stay balanced even when traveling for business.</p>
<p>Experience business travel redefined - where productivity meets luxury, and comfort enhances performance.</p>''',
'featured_image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&h=800&fit=crop',
'author_id': author_id,
'published_at': now - timedelta(days=30),
'is_published': True,
'tags': json.dumps(['business travel', 'corporate', 'productivity', 'meetings']),
'meta_title': 'Business Traveler\'s Guide | Corporate Accommodation',
'meta_description': 'Discover how our hotel caters to business travelers with state-of-the-art facilities, convenient services, and productivity-focused amenities.',
'meta_keywords': 'business travel, corporate hotel, business facilities, meeting rooms',
'sections': None
}
]
return posts
def seed_blog_posts(db: Session, clear_existing: bool = False):
"""Seed blog posts into the database"""
try:
# Get admin user as author
admin_user = db.query(User).filter(User.email == 'admin@hotel.com').first()
if not admin_user:
logger.error('Admin user not found. Please run user seeder first.')
raise ValueError('Admin user not found. Please run user seeder first.')
if clear_existing:
logger.info('Clearing existing blog posts...')
db.query(BlogPost).delete()
db.commit()
logger.info('Existing blog posts cleared.')
posts_data = get_blog_posts_data(admin_user.id)
now = datetime.now(timezone.utc)
created_count = 0
updated_count = 0
for post_data in posts_data:
# Generate slug if not provided
if not post_data.get('slug'):
post_data['slug'] = slugify(post_data['title'])
existing = db.query(BlogPost).filter(BlogPost.slug == post_data['slug']).first()
if existing:
logger.debug(f"Blog post '{post_data['title']}' already exists. Updating...")
for key, value in post_data.items():
setattr(existing, key, value)
existing.updated_at = now
updated_count += 1
else:
logger.debug(f"Creating blog post: {post_data['title']}")
post = BlogPost(**post_data)
db.add(post)
created_count += 1
db.commit()
logger.info(f'Successfully seeded blog posts! Created: {created_count}, Updated: {updated_count}, Total: {len(posts_data)}')
except Exception as e:
db.rollback()
logger.error(f'Error seeding blog posts: {str(e)}', exc_info=True)
raise
def main():
import argparse
parser = argparse.ArgumentParser(description='Seed blog posts')
parser.add_argument(
'--clear',
action='store_true',
help='Clear existing blog posts before seeding'
)
args = parser.parse_args()
db = SessionLocal()
try:
seed_blog_posts(db, clear_existing=args.clear)
except Exception as e:
logger.error(f'Failed to seed blog posts: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,221 @@
"""
Cancellation Policy Page Seeder
Seeds the database with comprehensive cancellation policy content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_cancellation_page_data():
"""Generate comprehensive cancellation policy page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.CANCELLATION,
'title': 'Cancellation Policy',
'subtitle': 'Reservation Cancellation Terms and Conditions',
'description': 'Learn about our cancellation policy, including cancellation deadlines, fees, and procedures for different rate types.',
'content': """
<h2>1. Overview</h2>
<p>This Cancellation Policy outlines the terms and conditions for cancelling reservations at Luxury Hotel & Resort. Cancellation terms vary by rate type and are clearly stated at the time of booking. Please review this policy carefully before making a reservation.</p>
<h2>2. Standard Cancellation Policy</h2>
<h3>2.1 Flexible Rate</h3>
<p>For reservations made with our Flexible Rate:</p>
<ul>
<li><strong>Free Cancellation:</strong> Cancellations made 24-48 hours before the scheduled check-in date and time are free of charge</li>
<li><strong>Late Cancellation:</strong> Cancellations made less than 24 hours before check-in will incur a charge equal to one night's room rate plus taxes</li>
<li><strong>No-Show:</strong> Failure to arrive on the scheduled check-in date will result in a charge for the entire reservation</li>
</ul>
<h3>2.2 Non-Refundable Rate</h3>
<p>For reservations made with our Non-Refundable Rate:</p>
<ul>
<li>These rates offer the best value but are non-refundable</li>
<li>Cancellations or modifications are not permitted</li>
<li>In exceptional circumstances, we may offer a credit for future stays (subject to management approval)</li>
<li>No-shows will be charged the full reservation amount</li>
</ul>
<h3>2.3 Advance Purchase Rate</h3>
<p>For Advance Purchase rates:</p>
<ul>
<li>Full payment is required at the time of booking</li>
<li>Cancellations made 7 days or more before check-in: Full refund minus a processing fee</li>
<li>Cancellations made less than 7 days before check-in: No refund</li>
</ul>
<h2>3. Special Packages and Promotions</h2>
<p>Cancellation terms for special packages, promotions, and seasonal offers may differ from standard rates. Specific cancellation terms will be clearly stated at the time of booking and in your confirmation email.</p>
<h2>4. Group Bookings</h2>
<p>For group bookings (typically 10 or more rooms):</p>
<ul>
<li>Cancellation terms are specified in the group booking contract</li>
<li>Generally, cancellations must be made 30-60 days in advance to avoid penalties</li>
<li>Individual room cancellations within a group may be subject to different terms</li>
<li>Please refer to your group booking agreement for specific terms</li>
</ul>
<h2>5. Event and Meeting Bookings</h2>
<p>Cancellation policies for event and meeting space bookings are detailed in your event contract. Generally:</p>
<ul>
<li>Cancellations made 30+ days in advance: Full refund or credit</li>
<li>Cancellations made 14-30 days in advance: 50% refund or credit</li>
<li>Cancellations made less than 14 days in advance: No refund</li>
</ul>
<h2>6. How to Cancel</h2>
<h3>6.1 Online Cancellation</h3>
<p>You can cancel your reservation online through:</p>
<ul>
<li>Your booking confirmation email (click "Manage Reservation")</li>
<li>Our website's "Manage Booking" section</li>
<li>Your account dashboard (if you have an account)</li>
</ul>
<h3>6.2 Phone Cancellation</h3>
<p>Call our reservations team:</p>
<ul>
<li><strong>Phone:</strong> +1 (555) 123-4567</li>
<li><strong>Hours:</strong> 24/7</li>
<li>Please have your confirmation number ready</li>
</ul>
<h3>6.3 Email Cancellation</h3>
<p>Send an email to:</p>
<ul>
<li><strong>Email:</strong> reservations@luxuryhotel.com</li>
<li>Include your confirmation number and guest name</li>
<li>Allow 24-48 hours for email processing</li>
</ul>
<h2>7. Cancellation Confirmation</h2>
<p>Upon successful cancellation, you will receive a cancellation confirmation email. Please retain this confirmation for your records. If you do not receive a confirmation, please contact us to verify that your cancellation was processed.</p>
<h2>8. Refunds</h2>
<p>Refunds for eligible cancellations will be processed to the original payment method within 5-10 business days. The time it takes for the refund to appear in your account depends on your financial institution. For more information, please refer to our Refund Policy.</p>
<h2>9. Modifications vs. Cancellations</h2>
<h3>9.1 Date Changes</h3>
<p>Modifying your reservation dates may be treated as a cancellation and rebooking, subject to availability and current rates. Please contact us to discuss modification options.</p>
<h3>9.2 Room Type Changes</h3>
<p>Changes to room type are subject to availability and rate differences. Additional charges may apply if the new room type has a higher rate.</p>
<h2>10. Force Majeure</h2>
<p>In cases of force majeure events (natural disasters, pandemics, government restrictions, travel bans, etc.), we will work with you to provide flexible cancellation options, including:</p>
<ul>
<li>Full refunds</li>
<li>Rescheduling without penalty</li>
<li>Credit for future stays</li>
</ul>
<p>Each situation is evaluated individually. Please contact us as soon as possible if you are affected by a force majeure event.</p>
<h2>11. Third-Party Bookings</h2>
<p>If you made your reservation through a third-party booking site (such as Expedia, Booking.com, etc.), you must cancel through that third party according to their cancellation policies. We cannot directly cancel third-party bookings.</p>
<h2>12. No-Show Policy</h2>
<p>If you do not arrive on your scheduled check-in date and have not cancelled your reservation:</p>
<ul>
<li>Your reservation will be considered a "no-show"</li>
<li>You will be charged according to your rate's cancellation policy</li>
<li>Remaining nights may be released for resale</li>
<li>No refunds are provided for no-show reservations</li>
</ul>
<h2>13. Early Departure</h2>
<p>If you check out earlier than your scheduled departure date:</p>
<ul>
<li>You may be eligible for a partial refund for unused nights</li>
<li>Early departure refunds are not guaranteed and are evaluated on a case-by-case basis</li>
<li>Please notify the front desk at least 24 hours before your early departure</li>
<li>Refunds are subject to the terms of your original reservation</li>
</ul>
<h2>14. Special Circumstances</h2>
<p>We understand that unexpected circumstances may arise. In cases of medical emergencies, family emergencies, or other extenuating circumstances, please contact us immediately. We will review your situation and may offer flexible cancellation options on a case-by-case basis.</p>
<h2>15. Contact Information</h2>
<p>For cancellation requests or questions about our cancellation policy, please contact us:</p>
<ul>
<li><strong>Reservations Phone:</strong> +1 (555) 123-4567 (24/7)</li>
<li><strong>Reservations Email:</strong> reservations@luxuryhotel.com</li>
<li><strong>Address:</strong> 123 Luxury Avenue, Premium City, PC 12345, United States</li>
</ul>
<h2>16. Policy Updates</h2>
<p>We reserve the right to update this Cancellation Policy at any time. Changes will be posted on this page with an updated "Last Updated" date. The cancellation terms that apply to your reservation are those in effect at the time you made your booking.</p>
<p><em>Last Updated: {}</em></p>
""".format(now.strftime('%B %d, %Y')),
'meta_title': 'Cancellation Policy | Luxury Hotel & Resort',
'meta_description': 'Learn about our cancellation policy, including cancellation deadlines, fees, and procedures for different rate types.',
'meta_keywords': 'cancellation policy, hotel cancellation, booking cancellation, cancel reservation, cancellation terms',
'og_title': 'Cancellation Policy - Luxury Hotel & Resort',
'og_description': 'Reservation cancellation terms and conditions. Learn how to cancel your booking and applicable fees.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/cancellation',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_cancellation_page(db: Session):
"""Seed cancellation policy page content into the database"""
try:
cancellation_data = get_cancellation_page_data()
# Check if cancellation page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.CANCELLATION).first()
if existing_content:
logger.info('Updating existing cancellation policy page content...')
for key, value in cancellation_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new cancellation policy page content...')
cancellation_page = PageContent(**cancellation_data)
db.add(cancellation_page)
db.commit()
logger.info('Cancellation policy page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding cancellation policy page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_cancellation_page(db)
except Exception as e:
logger.error(f'Failed to seed cancellation policy page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,167 @@
"""
Contact Page Seeder
Seeds the database with comprehensive contact page content
All images are from Unsplash (free stock photos)
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_contact_page_data():
"""Generate comprehensive contact page data with Unsplash images"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.CONTACT,
'title': 'Contact Us',
'subtitle': 'We\'re Here to Help - Get in Touch',
'description': 'Have questions or need assistance? Our friendly team is available 24/7 to help with reservations, inquiries, and special requests. Reach out to us through any of the methods below.',
'content': '<p>We value your feedback and are here to assist you with any questions or requests. Whether you\'re planning a stay, have a question about our services, or need assistance during your visit, our team is ready to help.</p>',
'meta_title': 'Contact Us | Luxury Hotel & Resort - Get in Touch',
'meta_description': 'Contact our luxury hotel for reservations, inquiries, or assistance. Our friendly team is available 24/7. Phone, email, and location information.',
'meta_keywords': 'contact us, hotel contact, reservations, customer service, hotel phone number, hotel email',
'og_title': 'Contact Us - Luxury Hotel & Resort',
'og_description': 'Have questions or need assistance? Our friendly team is available 24/7 to help with reservations, inquiries, and special requests.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/contact',
'hero_title': 'Get in Touch',
'hero_subtitle': 'We\'re Here to Help You',
'hero_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1920&h=1080&fit=crop',
'hero_video_url': None,
'hero_video_poster': None,
'contact_info': json.dumps({
'phone': '+1 (555) 123-4567',
'toll_free': '+1 (800) 123-4567',
'email': 'info@luxuryhotel.com',
'reservations_email': 'reservations@luxuryhotel.com',
'address': '123 Luxury Avenue, Premium City, PC 12345',
'address_line2': 'United States',
'business_hours': {
'front_desk': '24/7',
'concierge': '24/7',
'reservations': 'Monday - Sunday: 8:00 AM - 10:00 PM',
'restaurant': 'Breakfast: 7:00 AM - 11:00 AM, Lunch: 12:00 PM - 3:00 PM, Dinner: 6:00 PM - 11:00 PM',
'spa': 'Monday - Sunday: 9:00 AM - 9:00 PM'
}
}),
'map_url': 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3022.184132576!2d-73.98811768459418!3d40.75889597932681!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c25855c6480299%3A0x55194ec5a1ae072e!2sTimes%20Square!5e0!3m2!1sen!2sus!4v1234567890123!5m2!1sen!2sus',
'social_links': json.dumps({
'facebook': 'https://facebook.com/luxuryhotel',
'twitter': 'https://twitter.com/luxuryhotel',
'instagram': 'https://instagram.com/luxuryhotel',
'linkedin': 'https://linkedin.com/company/luxuryhotel',
'youtube': 'https://youtube.com/luxuryhotel',
'pinterest': 'https://pinterest.com/luxuryhotel'
}),
'testimonials': json.dumps([
{
'name': 'Sarah Johnson',
'title': 'Guest',
'quote': 'The customer service team was incredibly helpful and responsive. They answered all my questions and made my booking process seamless.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Michael Chen',
'title': 'Business Traveler',
'quote': 'The concierge team went above and beyond to help with my business needs. Their attention to detail and professionalism is outstanding.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop&crop=face'
}
]),
'testimonials_section_title': 'What Our Guests Say About Our Service',
'testimonials_section_subtitle': 'Real feedback from our valued guests',
'features': json.dumps([
{
'icon': 'phone',
'title': '24/7 Support',
'description': 'Our team is available around the clock to assist you with any questions or requests.'
},
{
'icon': 'clock',
'title': 'Quick Response',
'description': 'We respond to all inquiries within 24 hours, often much sooner.'
},
{
'icon': 'users',
'title': 'Expert Team',
'description': 'Our knowledgeable staff is trained to provide exceptional service and assistance.'
},
{
'icon': 'globe',
'title': 'Multiple Languages',
'description': 'We speak your language. Our team is fluent in multiple languages to serve international guests.'
}
]),
'features_section_title': 'Why Contact Us',
'features_section_subtitle': 'We\'re committed to providing exceptional service',
'gallery_images': json.dumps([
'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1200&h=800&fit=crop'
]),
'gallery_section_title': 'Visit Our Hotel',
'gallery_section_subtitle': 'Experience our luxury facilities',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_contact_page(db: Session):
"""Seed contact page content into the database"""
try:
contact_data = get_contact_page_data()
# Check if contact page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.CONTACT).first()
if existing_content:
logger.info('Updating existing contact page content...')
for key, value in contact_data.items():
if key not in ['id', 'page_type', 'created_at']: # Don't update primary key or creation date
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new contact page content...')
contact_page = PageContent(**contact_data)
db.add(contact_page)
db.commit()
logger.info('Contact page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding contact page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_contact_page(db)
except Exception as e:
logger.error(f'Failed to seed contact page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,192 @@
"""
FAQ Page Seeder
Seeds the database with comprehensive FAQ content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_faq_page_data():
"""Generate comprehensive FAQ page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.FAQ,
'title': 'Frequently Asked Questions',
'subtitle': 'Find Answers to Common Questions',
'description': 'Get answers to the most frequently asked questions about our hotel, reservations, services, and policies.',
'content': """
<h2>General Questions</h2>
<h3>What are your check-in and check-out times?</h3>
<p>Check-in time is 3:00 PM, and check-out time is 11:00 AM. Early check-in and late check-out may be available upon request, subject to availability and additional charges.</p>
<h3>Do you offer airport transportation?</h3>
<p>Yes, we offer airport transfer services. Please contact our concierge team at least 24 hours in advance to arrange transportation. Additional charges may apply.</p>
<h3>Is parking available?</h3>
<p>Yes, we offer complimentary valet parking for all hotel guests. Self-parking is also available at an additional charge.</p>
<h3>Do you have a fitness center?</h3>
<p>Yes, our state-of-the-art fitness center is open 24/7 and is complimentary for all hotel guests. We also offer personal training sessions upon request.</p>
<h3>Is Wi-Fi available?</h3>
<p>Yes, complimentary high-speed Wi-Fi is available throughout the hotel, including all guest rooms and public areas.</p>
<h2>Reservations & Booking</h2>
<h3>How do I make a reservation?</h3>
<p>You can make a reservation through our website, by calling our reservations team at +1 (555) 123-4567, or by emailing reservations@luxuryhotel.com.</p>
<h3>Can I modify or cancel my reservation?</h3>
<p>Yes, you can modify or cancel your reservation through our website or by contacting our reservations team. Please refer to our cancellation policy for details on refunds and fees.</p>
<h3>What payment methods do you accept?</h3>
<p>We accept all major credit cards (Visa, MasterCard, American Express, Discover), debit cards, and bank transfers. Cash payments are also accepted at check-in.</p>
<h3>Do you require a deposit?</h3>
<p>A credit card is required to guarantee your reservation. A deposit may be required for certain room types or during peak seasons. Details will be provided at the time of booking.</p>
<h3>Can I book for someone else?</h3>
<p>Yes, you can make a reservation for another guest. Please provide the guest's name and contact information at the time of booking, and ensure they have a valid ID for check-in.</p>
<h2>Rooms & Accommodations</h2>
<h3>What amenities are included in the rooms?</h3>
<p>All rooms include complimentary Wi-Fi, flat-screen TV, minibar, coffee maker, in-room safe, air conditioning, and luxury toiletries. Suites include additional amenities such as separate living areas and premium services.</p>
<h3>Do you have connecting rooms?</h3>
<p>Yes, we have connecting rooms available. Please request connecting rooms at the time of booking, and we will do our best to accommodate your request based on availability.</p>
<h3>Are rooms accessible for guests with disabilities?</h3>
<p>Yes, we have accessible rooms designed to meet ADA requirements. Please inform us of any specific accessibility needs when making your reservation.</p>
<h3>Can I request a specific room or floor?</h3>
<p>Yes, you can request a specific room or floor preference. While we cannot guarantee specific rooms, we will do our best to honor your request based on availability.</p>
<h3>Do you allow pets?</h3>
<p>We welcome service animals. For pets, please contact us in advance as pet-friendly rooms are limited and additional charges may apply.</p>
<h2>Services & Amenities</h2>
<h3>Do you have a spa?</h3>
<p>Yes, we have a world-class spa offering a variety of treatments. Advance reservations are recommended. Please contact our spa directly to book treatments.</p>
<h3>Are there restaurants on-site?</h3>
<p>Yes, we have multiple dining options including fine dining, casual restaurants, and room service available 24/7. Our restaurants feature award-winning cuisine and extensive wine selections.</p>
<h3>Do you offer room service?</h3>
<p>Yes, room service is available 24 hours a day. Our extensive menu includes breakfast, lunch, dinner, and late-night options.</p>
<h3>Is there a business center?</h3>
<p>Yes, our business center is equipped with computers, printers, and meeting facilities. It is available 24/7 for all guests.</p>
<h3>Do you have meeting and event facilities?</h3>
<p>Yes, we have versatile meeting and event spaces suitable for conferences, weddings, and other special occasions. Please contact our events team for more information.</p>
<h2>Policies & Procedures</h2>
<h3>What is your cancellation policy?</h3>
<p>Cancellation policies vary by rate type and booking. Generally, cancellations made 24-48 hours before check-in are free. Please refer to your booking confirmation for specific cancellation terms.</p>
<h3>What is your smoking policy?</h3>
<p>Our hotel is 100% non-smoking. Smoking is not permitted in any guest rooms or indoor public areas. Designated outdoor smoking areas are available.</p>
<h3>What is the minimum age to check in?</h3>
<p>Guests must be at least 18 years old to check in. Guests under 18 must be accompanied by an adult.</p>
<h3>Do you have a lost and found?</h3>
<p>Yes, we maintain a lost and found department. If you have lost an item, please contact our front desk immediately. We will make every effort to locate and return your belongings.</p>
<h2>Special Requests</h2>
<h3>Can I request early check-in or late check-out?</h3>
<p>Early check-in and late check-out are subject to availability. Please contact us in advance, and we will do our best to accommodate your request. Additional charges may apply.</p>
<h3>Do you accommodate special dietary requirements?</h3>
<p>Yes, we can accommodate various dietary requirements including vegetarian, vegan, gluten-free, and allergies. Please inform us of any dietary restrictions when making your reservation or dining reservation.</p>
<h3>Can you help arrange special occasions?</h3>
<p>Absolutely! Our concierge team can help arrange special occasions such as anniversaries, birthdays, or proposals. Please contact us in advance to discuss your needs.</p>
<h2>Contact & Support</h2>
<h3>How can I contact the hotel?</h3>
<p>You can reach us by phone at +1 (555) 123-4567, email at info@luxuryhotel.com, or through our website's contact form. Our front desk is available 24/7.</p>
<h3>Do you have a loyalty program?</h3>
<p>Yes, we offer a loyalty program with exclusive benefits including room upgrades, late check-out, and special rates. Membership is free. Please visit our website or contact us for more information.</p>
<h3>Can I leave feedback about my stay?</h3>
<p>We value your feedback! You can leave a review on our website, through our post-stay survey, or by contacting our guest relations team directly.</p>
""",
'meta_title': 'FAQ | Frequently Asked Questions - Luxury Hotel & Resort',
'meta_description': 'Find answers to frequently asked questions about reservations, rooms, services, and policies at Luxury Hotel & Resort.',
'meta_keywords': 'FAQ, frequently asked questions, hotel questions, booking questions, hotel policies, hotel information',
'og_title': 'FAQ - Luxury Hotel & Resort',
'og_description': 'Find answers to common questions about our hotel, reservations, and services.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/faq',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_faq_page(db: Session):
"""Seed FAQ page content into the database"""
try:
faq_data = get_faq_page_data()
# Check if FAQ page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.FAQ).first()
if existing_content:
logger.info('Updating existing FAQ page content...')
for key, value in faq_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new FAQ page content...')
faq_page = PageContent(**faq_data)
db.add(faq_page)
db.commit()
logger.info('FAQ page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding FAQ page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_faq_page(db)
except Exception as e:
logger.error(f'Failed to seed FAQ page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,173 @@
"""
Footer Page Seeder
Seeds the database with comprehensive footer content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_footer_page_data():
"""Generate comprehensive footer page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.FOOTER,
'title': 'Luxury Hotel & Resort',
'subtitle': 'Experience Unparalleled Elegance and Comfort',
'description': 'Your premier destination for luxury hospitality. Experience world-class service, exquisite accommodations, and unforgettable moments.',
'content': '<p>For over three decades, we have been crafting exceptional experiences for discerning travelers worldwide. Our commitment to excellence and attention to detail sets us apart.</p>',
'social_links': json.dumps({
'facebook': 'https://facebook.com/luxuryhotel',
'twitter': 'https://twitter.com/luxuryhotel',
'instagram': 'https://instagram.com/luxuryhotel',
'linkedin': 'https://linkedin.com/company/luxuryhotel',
'youtube': 'https://youtube.com/luxuryhotel',
'pinterest': 'https://pinterest.com/luxuryhotel'
}),
'footer_links': json.dumps({
'quick_links': [
{'label': 'Home', 'url': '/'},
{'label': 'About Us', 'url': '/about'},
{'label': 'Rooms & Suites', 'url': '/rooms'},
{'label': 'Services', 'url': '/services'},
{'label': 'Contact', 'url': '/contact'},
{'label': 'Blog', 'url': '/blog'}
],
'accommodations': [
{'label': 'Standard Rooms', 'url': '/rooms?type=standard'},
{'label': 'Deluxe Rooms', 'url': '/rooms?type=deluxe'},
{'label': 'Executive Suites', 'url': '/rooms?type=executive'},
{'label': 'Presidential Suites', 'url': '/rooms?type=presidential'},
{'label': 'Ocean View Rooms', 'url': '/rooms?type=ocean-view'},
{'label': 'Family Rooms', 'url': '/rooms?type=family'}
],
'services': [
{'label': 'Spa & Wellness', 'url': '/services?category=spa'},
{'label': 'Fine Dining', 'url': '/services?category=dining'},
{'label': 'Concierge', 'url': '/services?category=concierge'},
{'label': 'Business Center', 'url': '/services?category=business'},
{'label': 'Event Planning', 'url': '/services?category=events'},
{'label': 'Transportation', 'url': '/services?category=transportation'}
],
'information': [
{'label': 'About Us', 'url': '/about'},
{'label': 'Our Story', 'url': '/about#story'},
{'label': 'Awards & Recognition', 'url': '/about#awards'},
{'label': 'Careers', 'url': '/careers'},
{'label': 'Press & Media', 'url': '/press'},
{'label': 'Blog', 'url': '/blog'}
],
'support_links': [
{'label': 'Contact Us', 'url': '/contact'},
{'label': 'FAQ', 'url': '/faq'},
{'label': 'Booking Help', 'url': '/help'},
{'label': 'Cancellation Policy', 'url': '/cancellation'},
{'label': 'Privacy Policy', 'url': '/privacy'},
{'label': 'Terms & Conditions', 'url': '/terms'},
{'label': 'Refund Policy', 'url': '/refunds'},
{'label': 'Accessibility', 'url': '/accessibility'}
]
}),
'badges': json.dumps([
{
'icon': 'award',
'text': '5-Star Rated',
'description': 'Consistently rated five-star by global travel guides'
},
{
'icon': 'trophy',
'text': 'Award Winning',
'description': 'Best Luxury Hotel 2023'
},
{
'icon': 'shield',
'text': 'Secure Booking',
'description': 'Your data and payments are protected'
},
{
'icon': 'star',
'text': '98% Satisfaction',
'description': 'Guest satisfaction rating'
},
{
'icon': 'leaf',
'text': 'Eco-Friendly',
'description': 'Certified green hotel'
},
{
'icon': 'check-circle',
'text': 'Best Price Guarantee',
'description': 'We guarantee the best rates'
}
]),
'copyright_text': f'© {datetime.now(timezone.utc).year} Luxury Hotel & Resort. All rights reserved.',
'contact_info': json.dumps({
'phone': '+1 (555) 123-4567',
'toll_free': '+1 (800) 123-4567',
'email': 'info@luxuryhotel.com',
'reservations_email': 'reservations@luxuryhotel.com',
'address': '123 Luxury Avenue, Premium City, PC 12345, United States'
}),
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_footer_page(db: Session):
"""Seed footer page content into the database"""
try:
footer_data = get_footer_page_data()
# Check if footer page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.FOOTER).first()
if existing_content:
logger.info('Updating existing footer page content...')
for key, value in footer_data.items():
if key not in ['id', 'page_type', 'created_at']: # Don't update primary key or creation date
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new footer page content...')
footer_page = PageContent(**footer_data)
db.add(footer_page)
db.commit()
logger.info('Footer page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding footer page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_footer_page(db)
except Exception as e:
logger.error(f'Failed to seed footer page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,596 @@
"""
Homepage Seeder
Seeds the homepage with comprehensive content including images from Unsplash
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal, engine
from src.content.models.page_content import PageContent, PageType
from src.shared.config.logging_config import get_logger
logger = get_logger(__name__)
def get_homepage_data():
"""Generate comprehensive homepage data with Unsplash images"""
# Using Unsplash Source API for images (free, no API key needed)
# Format: https://source.unsplash.com/{width}x{height}/?{keywords}
return {
'page_type': PageType.HOME,
'title': 'Luxury Hotel & Resort',
'subtitle': 'Experience Unparalleled Elegance and Comfort',
'description': 'Welcome to our world-class luxury hotel where exceptional service meets breathtaking elegance. Discover a sanctuary of sophistication and comfort.',
'content': '<p>Experience the pinnacle of luxury hospitality at our award-winning hotel. Nestled in a prime location, we offer world-class amenities, exquisite dining, and unparalleled service that creates unforgettable memories.</p>',
# SEO Meta Tags
'meta_title': 'Luxury Hotel & Resort | Premium Accommodation & World-Class Service',
'meta_description': 'Discover luxury accommodation with world-class amenities, fine dining, and exceptional service. Book your stay at our award-winning hotel today.',
'meta_keywords': 'luxury hotel, resort, premium accommodation, fine dining, spa, business hotel, vacation, travel',
'og_title': 'Luxury Hotel & Resort - Experience Unparalleled Elegance',
'og_description': 'Welcome to our world-class luxury hotel where exceptional service meets breathtaking elegance.',
'og_image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com',
# Hero Section
'hero_title': 'Welcome to Luxury Redefined',
'hero_subtitle': 'Where Every Moment Becomes a Memory',
'hero_image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1920&h=1080&fit=crop',
'hero_video_url': None,
'hero_video_poster': None,
# Story Content
'story_content': '<p>For over three decades, we have been crafting exceptional experiences for our guests. Our commitment to excellence, attention to detail, and passion for hospitality has made us a destination of choice for discerning travelers worldwide.</p>',
# Values Section
'values': json.dumps([
{
'icon': 'heart',
'title': 'Excellence',
'description': 'We strive for perfection in every detail, ensuring your experience exceeds expectations.'
},
{
'icon': 'shield',
'title': 'Trust',
'description': 'Your comfort and security are our top priorities, backed by years of trusted service.'
},
{
'icon': 'users',
'title': 'Hospitality',
'description': 'Our dedicated team is committed to making your stay memorable and delightful.'
},
{
'icon': 'award',
'title': 'Quality',
'description': 'We maintain the highest standards in service, amenities, and guest satisfaction.'
}
]),
# Features Section
'features_section_title': 'Why Choose Us',
'features_section_subtitle': 'Discover what makes us the perfect choice for your stay',
'features': json.dumps([
{
'icon': 'wifi',
'title': 'Free High-Speed WiFi',
'description': 'Stay connected with complimentary high-speed internet throughout the property.',
'image': 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=800&h=600&fit=crop'
},
{
'icon': 'utensils',
'title': 'Fine Dining',
'description': 'Savor exquisite cuisine at our award-winning restaurants and bars.',
'image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=800&h=600&fit=crop'
},
{
'icon': 'spa',
'title': 'Luxury Spa',
'description': 'Rejuvenate your mind and body at our world-class spa and wellness center.',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=800&h=600&fit=crop'
},
{
'icon': 'dumbbell',
'title': 'Fitness Center',
'description': 'Maintain your workout routine in our state-of-the-art fitness facility.',
'image': 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=800&h=600&fit=crop'
},
{
'icon': 'swimming-pool',
'title': 'Swimming Pool',
'description': 'Relax and unwind in our stunning outdoor and indoor pools.',
'image': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800&h=600&fit=crop'
},
{
'icon': 'car',
'title': 'Valet Parking',
'description': 'Complimentary valet parking service for all our guests.',
'image': 'https://images.unsplash.com/photo-1502877338535-766e1452684a?w=800&h=600&fit=crop'
}
]),
# About Preview Section
'about_preview_title': 'Our Story',
'about_preview_subtitle': 'A Legacy of Excellence',
'about_preview_content': '<p>Since our founding, we have been dedicated to providing exceptional hospitality experiences. Our commitment to excellence, combined with our passion for service, has established us as a leader in the luxury hospitality industry.</p>',
'about_preview_image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1200&h=800&fit=crop',
# Stats Section
'stats_section_title': 'Our Achievements',
'stats_section_subtitle': 'Numbers that speak for themselves',
'stats': json.dumps([
{
'number': '50000+',
'label': 'Happy Guests',
'icon': 'users'
},
{
'number': '30+',
'label': 'Years of Excellence',
'icon': 'calendar'
},
{
'number': '150+',
'label': 'Awards Won',
'icon': 'award'
},
{
'number': '98%',
'label': 'Guest Satisfaction',
'icon': 'star'
}
]),
# Rooms Section
'rooms_section_title': 'Luxurious Accommodations',
'rooms_section_subtitle': 'Elegant rooms and suites designed for your comfort',
'rooms_section_button_text': 'View All Rooms',
'rooms_section_button_link': '/rooms',
'rooms_section_enabled': True,
# Luxury Services Section
'luxury_services_section_title': 'Premium Services',
'luxury_services_section_subtitle': 'Indulge in our exclusive offerings',
'services_section_button_text': 'Explore Services',
'services_section_button_link': '/services',
'services_section_limit': 6,
'luxury_services': json.dumps([
{
'icon': 'concierge',
'title': '24/7 Concierge',
'description': 'Our dedicated concierge team is available around the clock to assist with any request.',
'image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=600&h=400&fit=crop'
},
{
'icon': 'plane',
'title': 'Airport Transfer',
'description': 'Complimentary airport transfer service for a seamless arrival experience.',
'image': 'https://images.unsplash.com/photo-1449824913935-59a10b8d2000?w=600&h=400&fit=crop'
},
{
'icon': 'briefcase',
'title': 'Business Center',
'description': 'Fully equipped business center with meeting rooms and conference facilities.',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=600&h=400&fit=crop'
},
{
'icon': 'wine',
'title': 'Wine Cellar',
'description': 'Explore our extensive collection of fine wines from around the world.',
'image': 'https://images.unsplash.com/photo-1510812431401-41d2bd2722f3?w=600&h=400&fit=crop'
},
{
'icon': 'music',
'title': 'Live Entertainment',
'description': 'Enjoy live music and entertainment in our elegant lounge areas.',
'image': 'https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=600&h=400&fit=crop'
},
{
'icon': 'gift',
'title': 'Gift Shop',
'description': 'Browse our curated selection of luxury gifts and souvenirs.',
'image': 'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=600&h=400&fit=crop'
}
]),
# Luxury Experiences Section
'luxury_experiences_section_title': 'Unique Experiences',
'luxury_experiences_section_subtitle': 'Create unforgettable memories with our curated experiences',
'luxury_experiences': json.dumps([
{
'icon': 'sunset',
'title': 'Sunset Rooftop Dining',
'description': 'Dine under the stars with panoramic city views and gourmet cuisine.',
'image': 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=800&h=600&fit=crop'
},
{
'icon': 'compass',
'title': 'City Tours',
'description': 'Explore the city with our guided tours showcasing local culture and landmarks.',
'image': 'https://images.unsplash.com/photo-1488646953014-85cb44e25828?w=800&h=600&fit=crop'
},
{
'icon': 'camera',
'title': 'Photography Sessions',
'description': 'Capture your special moments with our professional photography services.',
'image': 'https://images.unsplash.com/photo-1516035069371-29a1b244cc32?w=800&h=600&fit=crop'
}
]),
# Amenities Section
'amenities_section_title': 'World-Class Amenities',
'amenities_section_subtitle': 'Everything you need for a perfect stay',
'amenities': json.dumps([
{
'icon': 'wifi',
'title': 'Free WiFi',
'description': 'High-speed internet access throughout the property'
},
{
'icon': 'tv',
'title': 'Smart TV',
'description': 'Streaming services and premium channels in every room'
},
{
'icon': 'coffee',
'title': 'Coffee Maker',
'description': 'Premium coffee and tea making facilities'
},
{
'icon': 'snowflake',
'title': 'Climate Control',
'description': 'Individual temperature control in all rooms'
},
{
'icon': 'lock',
'title': 'Safe',
'description': 'In-room safe for your valuables'
},
{
'icon': 'shirt',
'title': 'Laundry Service',
'description': 'Professional laundry and dry cleaning services'
}
]),
# Testimonials Section
'testimonials_section_title': 'What Our Guests Say',
'testimonials_section_subtitle': 'Real experiences from real guests',
'testimonials': json.dumps([
{
'name': 'Sarah Johnson',
'title': 'Business Traveler',
'quote': 'The service was exceptional and the rooms were immaculate. This hotel exceeded all my expectations.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Michael Chen',
'title': 'Honeymooner',
'quote': 'Our honeymoon was made perfect by the attentive staff and beautiful accommodations. Truly unforgettable!',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Emily Rodriguez',
'title': 'Family Vacation',
'quote': 'Perfect for families! The kids loved the pool and the staff was so accommodating. We will definitely return.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'David Thompson',
'title': 'Luxury Traveler',
'quote': 'The attention to detail and level of service is unmatched. This is what luxury hospitality should be.',
'rating': 5,
'image': 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=200&h=200&fit=crop&crop=face'
}
]),
# Gallery Section
'gallery_section_title': 'Photo Gallery',
'gallery_section_subtitle': 'A glimpse into our world of luxury',
'gallery_images': json.dumps([
'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1542314831-068cd1dbfeeb?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1578683010236-d716f9a3f461?w=1200&h=800&fit=crop'
]),
# Luxury Section
'luxury_section_title': 'Luxury Redefined',
'luxury_section_subtitle': 'Experience the epitome of elegance and sophistication',
'luxury_section_image': 'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1400&h=900&fit=crop',
'luxury_features': json.dumps([
{
'icon': 'crown',
'title': 'Royal Treatment',
'description': 'Experience service fit for royalty with our personalized attention to every detail.'
},
{
'icon': 'gem',
'title': 'Premium Quality',
'description': 'Only the finest materials and furnishings grace our elegant spaces.'
},
{
'icon': 'sparkles',
'title': 'Exclusive Access',
'description': 'Enjoy exclusive access to private lounges and premium facilities.'
}
]),
# Luxury Gallery Section
'luxury_gallery_section_title': 'Luxury Gallery',
'luxury_gallery_section_subtitle': 'Discover our world of refined elegance',
'luxury_gallery': json.dumps([
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?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-1590490360182-c33d57733427?w=1200&h=800&fit=crop'
]),
# Luxury Testimonials Section
'luxury_testimonials_section_title': 'Guest Experiences',
'luxury_testimonials_section_subtitle': 'Stories from our valued guests',
'luxury_testimonials': json.dumps([
{
'name': 'James Wilson',
'title': 'VIP Guest',
'quote': 'The level of luxury and attention to detail is simply extraordinary. This is hospitality at its finest.',
'image': 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=200&h=200&fit=crop&crop=face'
},
{
'name': 'Maria Garcia',
'title': 'Celebrity Guest',
'quote': 'Privacy, elegance, and impeccable service. This hotel understands true luxury.',
'image': 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=200&h=200&fit=crop&crop=face'
}
]),
# Awards Section
'awards_section_title': 'Awards & Recognition',
'awards_section_subtitle': 'Recognized for excellence in hospitality',
'awards': json.dumps([
{
'icon': 'trophy',
'title': 'Best Luxury Hotel 2023',
'description': 'Awarded by International Hospitality Association',
'year': '2023',
'image': 'https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=400&h=400&fit=crop'
},
{
'icon': 'star',
'title': '5-Star Rating',
'description': 'Consistently rated 5 stars by leading travel organizations',
'year': '2023',
'image': 'https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=400&h=400&fit=crop'
},
{
'icon': 'award',
'title': 'Excellence in Service',
'description': 'Recognized for outstanding customer service and guest satisfaction',
'year': '2022',
'image': 'https://images.unsplash.com/photo-1579621970563-ebec7560ff3e?w=400&h=400&fit=crop'
}
]),
# Partners Section
'partners_section_title': 'Our Partners',
'partners_section_subtitle': 'Trusted by leading brands and organizations',
'partners': json.dumps([
{
'name': 'Travel Partner',
'logo': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=200&h=100&fit=crop',
'url': '#'
},
{
'name': 'Luxury Brand',
'logo': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=200&h=100&fit=crop',
'url': '#'
},
{
'name': 'Hospitality Group',
'logo': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=200&h=100&fit=crop',
'url': '#'
}
]),
# CTA Section
'cta_title': 'Ready to Experience Luxury?',
'cta_subtitle': 'Book your stay today and discover why we are the preferred choice for discerning travelers',
'cta_button_text': 'Book Now',
'cta_button_link': '/book',
'cta_image': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1400&h=700&fit=crop',
# Newsletter Section
'newsletter_section_title': 'Stay Connected',
'newsletter_section_subtitle': 'Subscribe to our newsletter for exclusive offers and updates',
'newsletter_placeholder': 'Enter your email address',
'newsletter_button_text': 'Subscribe',
'newsletter_enabled': True,
# Trust Badges Section
'trust_badges_section_title': 'Why Trust Us',
'trust_badges_section_subtitle': 'Your peace of mind is our priority',
'trust_badges_enabled': True,
'trust_badges': json.dumps([
{
'icon': 'shield-check',
'title': 'Secure Booking',
'description': 'Your data and payments are protected with industry-leading security'
},
{
'icon': 'clock',
'title': '24/7 Support',
'description': 'Round-the-clock customer support for all your needs'
},
{
'icon': 'undo',
'title': 'Flexible Cancellation',
'description': 'Free cancellation up to 24 hours before check-in'
},
{
'icon': 'check-circle',
'title': 'Best Price Guarantee',
'description': 'We guarantee the best rates for your stay'
}
]),
# Promotions Section
'promotions_section_title': 'Special Offers',
'promotions_section_subtitle': 'Exclusive deals and packages for our guests',
'promotions_enabled': True,
'promotions': json.dumps([
{
'title': 'Early Bird Special',
'description': 'Book 30 days in advance and save 20%',
'discount': '20% OFF',
'image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&h=600&fit=crop',
'link': '/promotions/early-bird'
},
{
'title': 'Weekend Getaway',
'description': 'Perfect weekend escape with complimentary breakfast',
'discount': '15% OFF',
'image': 'https://images.unsplash.com/photo-1520250497591-112f2f40a3f4?w=800&h=600&fit=crop',
'link': '/promotions/weekend'
},
{
'title': 'Honeymoon Package',
'description': 'Romantic getaway with special amenities and services',
'discount': '25% OFF',
'image': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800&h=600&fit=crop',
'link': '/promotions/honeymoon'
}
]),
# Blog Section
'blog_section_title': 'Latest News & Updates',
'blog_section_subtitle': 'Stay informed with our latest articles and hotel news',
'blog_posts_limit': 3,
'blog_enabled': True,
# Sections Enabled
'sections_enabled': json.dumps({
'hero': True,
'features': True,
'about_preview': True,
'stats': True,
'rooms': True,
'services': True,
'experiences': True,
'amenities': True,
'testimonials': True,
'gallery': True,
'luxury': True,
'awards': True,
'partners': True,
'cta': True,
'newsletter': True,
'trust_badges': True,
'promotions': True,
'blog': True
}),
# Badges
'badges': json.dumps([
{
'text': '5-Star Rated',
'icon': 'star'
},
{
'text': 'Award Winning',
'icon': 'award'
},
{
'text': 'Eco-Friendly',
'icon': 'leaf'
}
]),
# Social Links
'social_links': json.dumps({
'facebook': 'https://facebook.com/luxuryhotel',
'twitter': 'https://twitter.com/luxuryhotel',
'instagram': 'https://instagram.com/luxuryhotel',
'linkedin': 'https://linkedin.com/company/luxuryhotel',
'youtube': 'https://youtube.com/luxuryhotel'
}),
# Contact Info
'contact_info': json.dumps({
'phone': '+1 (555) 123-4567',
'email': 'info@luxuryhotel.com',
'address': '123 Luxury Avenue, Premium City, PC 12345'
}),
# Active Status
'is_active': True,
'created_at': datetime.now(timezone.utc),
'updated_at': datetime.now(timezone.utc)
}
def seed_homepage(db: Session):
"""Seed the homepage content"""
try:
# Check if homepage already exists
existing = db.query(PageContent).filter(PageContent.page_type == PageType.HOME).first()
if existing:
logger.info('Homepage content already exists. Updating...')
# Update existing content
data = get_homepage_data()
for key, value in data.items():
if key != 'page_type': # Don't update page_type
setattr(existing, key, value)
existing.updated_at = datetime.now(timezone.utc)
db.commit()
logger.info('Homepage content updated successfully!')
return existing
else:
logger.info('Creating new homepage content...')
# Create new content
data = get_homepage_data()
homepage = PageContent(**data)
db.add(homepage)
db.commit()
db.refresh(homepage)
logger.info('Homepage content created successfully!')
return homepage
except Exception as e:
logger.error(f'Error seeding homepage: {str(e)}', exc_info=True)
db.rollback()
raise
def main():
"""Main function to run the seeder"""
logger.info('Starting homepage seeder...')
db = SessionLocal()
try:
homepage = seed_homepage(db)
logger.info(f'Homepage seeder completed successfully! ID: {homepage.id}')
except Exception as e:
logger.error(f'Failed to seed homepage: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,172 @@
"""
Privacy Policy Page Seeder
Seeds the database with comprehensive privacy policy content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_privacy_page_data():
"""Generate comprehensive privacy policy page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.PRIVACY,
'title': 'Privacy Policy',
'subtitle': 'Your Privacy Matters to Us',
'description': 'Learn how we collect, use, and protect your personal information. We are committed to maintaining your privacy and ensuring the security of your data.',
'content': """
<h2>1. Introduction</h2>
<p>At Luxury Hotel & Resort, we are committed to protecting your privacy and ensuring the security of your personal information. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you visit our website, make a reservation, or use our services.</p>
<h2>2. Information We Collect</h2>
<h3>2.1 Personal Information</h3>
<p>We may collect personal information that you provide directly to us, including:</p>
<ul>
<li>Name, email address, phone number, and mailing address</li>
<li>Payment information (credit card details, billing address)</li>
<li>Reservation details and preferences</li>
<li>Identification documents (for check-in purposes)</li>
<li>Special requests or dietary requirements</li>
</ul>
<h3>2.2 Automatically Collected Information</h3>
<p>When you visit our website, we may automatically collect certain information, including:</p>
<ul>
<li>IP address and browser type</li>
<li>Device information and operating system</li>
<li>Pages visited and time spent on our site</li>
<li>Referring website addresses</li>
<li>Cookies and similar tracking technologies</li>
</ul>
<h2>3. How We Use Your Information</h2>
<p>We use the information we collect for various purposes, including:</p>
<ul>
<li>Processing and managing your reservations</li>
<li>Communicating with you about your stay</li>
<li>Providing customer service and support</li>
<li>Sending marketing communications (with your consent)</li>
<li>Improving our services and website experience</li>
<li>Complying with legal obligations</li>
<li>Preventing fraud and ensuring security</li>
</ul>
<h2>4. Information Sharing and Disclosure</h2>
<p>We do not sell your personal information. We may share your information in the following circumstances:</p>
<ul>
<li><strong>Service Providers:</strong> With trusted third-party service providers who assist us in operating our business</li>
<li><strong>Legal Requirements:</strong> When required by law or to protect our rights and safety</li>
<li><strong>Business Transfers:</strong> In connection with a merger, acquisition, or sale of assets</li>
<li><strong>With Your Consent:</strong> When you have given us explicit permission to share your information</li>
</ul>
<h2>5. Data Security</h2>
<p>We implement appropriate technical and organizational measures to protect your personal information against unauthorized access, alteration, disclosure, or destruction. However, no method of transmission over the Internet is 100% secure, and we cannot guarantee absolute security.</p>
<h2>6. Your Rights</h2>
<p>Depending on your location, you may have certain rights regarding your personal information, including:</p>
<ul>
<li>The right to access your personal information</li>
<li>The right to correct inaccurate information</li>
<li>The right to request deletion of your information</li>
<li>The right to object to processing of your information</li>
<li>The right to data portability</li>
<li>The right to withdraw consent</li>
</ul>
<h2>7. Cookies and Tracking Technologies</h2>
<p>We use cookies and similar tracking technologies to enhance your browsing experience, analyze website traffic, and personalize content. You can control cookie preferences through your browser settings.</p>
<h2>8. Third-Party Links</h2>
<p>Our website may contain links to third-party websites. We are not responsible for the privacy practices of these external sites. We encourage you to review their privacy policies.</p>
<h2>9. Children's Privacy</h2>
<p>Our services are not directed to individuals under the age of 18. We do not knowingly collect personal information from children. If you believe we have collected information from a child, please contact us immediately.</p>
<h2>10. International Data Transfers</h2>
<p>Your information may be transferred to and processed in countries other than your country of residence. We ensure appropriate safeguards are in place to protect your information in accordance with this Privacy Policy.</p>
<h2>11. Changes to This Privacy Policy</h2>
<p>We may update this Privacy Policy from time to time. We will notify you of any material changes by posting the new policy on this page and updating the "Last Updated" date.</p>
<h2>12. Contact Us</h2>
<p>If you have any questions or concerns about this Privacy Policy or our data practices, please contact us at:</p>
<p>
<strong>Email:</strong> privacy@luxuryhotel.com<br>
<strong>Phone:</strong> +1 (555) 123-4567<br>
<strong>Address:</strong> 123 Luxury Avenue, Premium City, PC 12345, United States
</p>
<p><em>Last Updated: {}</em></p>
""".format(now.strftime('%B %d, %Y')),
'meta_title': 'Privacy Policy | Luxury Hotel & Resort',
'meta_description': 'Learn how Luxury Hotel & Resort collects, uses, and protects your personal information. Read our comprehensive privacy policy.',
'meta_keywords': 'privacy policy, data protection, personal information, GDPR, privacy rights, hotel privacy',
'og_title': 'Privacy Policy - Luxury Hotel & Resort',
'og_description': 'Your privacy matters to us. Learn how we protect and use your personal information.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/privacy',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_privacy_page(db: Session):
"""Seed privacy policy page content into the database"""
try:
privacy_data = get_privacy_page_data()
# Check if privacy page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.PRIVACY).first()
if existing_content:
logger.info('Updating existing privacy policy page content...')
for key, value in privacy_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new privacy policy page content...')
privacy_page = PageContent(**privacy_data)
db.add(privacy_page)
db.commit()
logger.info('Privacy policy page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding privacy policy page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_privacy_page(db)
except Exception as e:
logger.error(f'Failed to seed privacy policy page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,193 @@
"""
Refund Policy Page Seeder
Seeds the database with comprehensive refund policy content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_refunds_page_data():
"""Generate comprehensive refund policy page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.REFUNDS,
'title': 'Refund Policy',
'subtitle': 'Our Refund Policy and Procedures',
'description': 'Learn about our refund policy, including eligibility, processing times, and how to request a refund for your reservation or services.',
'content': """
<h2>1. Overview</h2>
<p>At Luxury Hotel & Resort, we strive to provide exceptional service and ensure your satisfaction. This Refund Policy outlines the terms and conditions under which refunds may be issued for reservations, services, and other transactions.</p>
<h2>2. Reservation Refunds</h2>
<h3>2.1 Cancellation Refunds</h3>
<p>Refunds for cancelled reservations are subject to the cancellation policy associated with your booking:</p>
<ul>
<li><strong>Flexible Rate:</strong> Full refund if cancelled 24-48 hours before check-in (depending on rate terms)</li>
<li><strong>Non-Refundable Rate:</strong> No refund for cancellations, but may be eligible for credit or rescheduling (subject to terms)</li>
<li><strong>Special Packages:</strong> Refund terms vary by package - please refer to your booking confirmation</li>
</ul>
<h3>2.2 Early Departure</h3>
<p>If you check out earlier than your scheduled departure date, you may be eligible for a partial refund for unused nights, subject to the terms of your reservation and availability. Early departure refunds are not guaranteed and are evaluated on a case-by-case basis.</p>
<h3>2.3 No-Show</h3>
<p>If you do not arrive on your scheduled check-in date and have not cancelled your reservation, you will be charged for the first night. No refunds are provided for no-show reservations.</p>
<h2>3. Service Refunds</h2>
<h3>3.1 Spa Services</h3>
<p>Spa service refunds or rescheduling:</p>
<ul>
<li>Cancellations made 24 hours in advance: Full refund or rescheduling</li>
<li>Cancellations made less than 24 hours in advance: 50% refund or rescheduling</li>
<li>No-show: No refund</li>
</ul>
<h3>3.2 Dining Reservations</h3>
<p>Dining reservation refunds:</p>
<ul>
<li>Cancellations made 4 hours in advance: Full refund</li>
<li>Cancellations made less than 4 hours in advance: No refund, but may be rescheduled</li>
<li>Special event dining: Subject to specific event terms</li>
</ul>
<h3>3.3 Event & Meeting Bookings</h3>
<p>Refund policies for events and meetings vary based on the size and type of event. Please refer to your event contract for specific refund terms.</p>
<h2>4. Processing Refunds</h2>
<h3>4.1 Refund Processing Time</h3>
<p>Once approved, refunds are typically processed within 5-10 business days. The time it takes for the refund to appear in your account depends on your financial institution:</p>
<ul>
<li>Credit card refunds: 5-10 business days</li>
<li>Debit card refunds: 5-10 business days</li>
<li>Bank transfer refunds: 7-14 business days</li>
</ul>
<h3>4.2 Refund Method</h3>
<p>Refunds will be issued to the original payment method used for the transaction. If the original payment method is no longer valid, please contact us to arrange an alternative refund method.</p>
<h2>5. Requesting a Refund</h2>
<h3>5.1 How to Request</h3>
<p>To request a refund, please contact us:</p>
<ul>
<li><strong>Phone:</strong> +1 (555) 123-4567</li>
<li><strong>Email:</strong> refunds@luxuryhotel.com</li>
<li><strong>Online:</strong> Through your booking confirmation or account</li>
</ul>
<h3>5.2 Required Information</h3>
<p>When requesting a refund, please provide:</p>
<ul>
<li>Reservation or booking confirmation number</li>
<li>Guest name and contact information</li>
<li>Reason for refund request</li>
<li>Original payment method details</li>
</ul>
<h2>6. Non-Refundable Items</h2>
<p>The following items and services are generally non-refundable:</p>
<ul>
<li>Non-refundable rate bookings (unless otherwise specified)</li>
<li>Gift cards and vouchers (subject to terms and conditions)</li>
<li>Third-party bookings (subject to third-party policies)</li>
<li>Consumed services (meals, spa treatments already received)</li>
<li>No-show charges</li>
</ul>
<h2>7. Special Circumstances</h2>
<h3>7.1 Force Majeure</h3>
<p>In cases of force majeure events (natural disasters, pandemics, government restrictions, etc.), we will work with you to provide refunds, credits, or rescheduling options. Each situation is evaluated individually.</p>
<h3>7.2 Service Issues</h3>
<p>If you experience service issues during your stay, please bring them to our attention immediately so we can address them. We may offer partial refunds or credits for significant service failures, evaluated on a case-by-case basis.</p>
<h2>8. Disputes & Appeals</h2>
<p>If you are not satisfied with a refund decision, you may appeal by contacting our guest relations team. We will review your case and provide a response within 5-7 business days.</p>
<h2>9. Third-Party Bookings</h2>
<p>If you made your reservation through a third-party booking site (such as Expedia, Booking.com, etc.), refund requests must be processed through that third party according to their policies. We cannot directly process refunds for third-party bookings.</p>
<h2>10. Contact Information</h2>
<p>For refund inquiries or assistance, please contact us:</p>
<ul>
<li><strong>Refunds Department:</strong> refunds@luxuryhotel.com</li>
<li><strong>Phone:</strong> +1 (555) 123-4567</li>
<li><strong>Hours:</strong> Monday-Friday, 9:00 AM - 6:00 PM EST</li>
<li><strong>Address:</strong> 123 Luxury Avenue, Premium City, PC 12345, United States</li>
</ul>
<h2>11. Policy Updates</h2>
<p>We reserve the right to update this Refund Policy at any time. Changes will be posted on this page with an updated "Last Updated" date. Your continued use of our services after changes are posted constitutes acceptance of the updated policy.</p>
<p><em>Last Updated: {}</em></p>
""".format(now.strftime('%B %d, %Y')),
'meta_title': 'Refund Policy | Luxury Hotel & Resort',
'meta_description': 'Learn about our refund policy, including eligibility, processing times, and how to request refunds for reservations and services.',
'meta_keywords': 'refund policy, cancellation refund, hotel refund, booking refund, refund request',
'og_title': 'Refund Policy - Luxury Hotel & Resort',
'og_description': 'Our refund policy and procedures. Learn how to request refunds for reservations and services.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/refunds',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_refunds_page(db: Session):
"""Seed refunds policy page content into the database"""
try:
refunds_data = get_refunds_page_data()
# Check if refunds page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.REFUNDS).first()
if existing_content:
logger.info('Updating existing refunds policy page content...')
for key, value in refunds_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new refunds policy page content...')
refunds_page = PageContent(**refunds_data)
db.add(refunds_page)
db.commit()
logger.info('Refunds policy page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding refunds policy page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_refunds_page(db)
except Exception as e:
logger.error(f'Failed to seed refunds policy page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,473 @@
"""
Room Seeder
Seeds the database with room types and rooms
All images are from Unsplash (free stock photos)
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
from decimal import Decimal
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.rooms.models.room import Room, RoomStatus
from src.rooms.models.room_type import RoomType
# Import all models to ensure relationships are loaded correctly
from src.models import *
logger = get_logger(__name__)
def get_room_types_data():
"""Generate room types data"""
now = datetime.now(timezone.utc)
return [
{
'name': 'Standard Room',
'description': 'Comfortable and well-appointed standard rooms perfect for business travelers and couples. Features modern amenities and elegant decor.',
'base_price': Decimal('150.00'),
'capacity': 2,
'amenities': json.dumps([
'Free WiFi',
'Flat-screen TV',
'Air Conditioning',
'Mini Bar',
'Work Desk',
'In-room Safe',
'Coffee Maker',
'Hair Dryer'
])
},
{
'name': 'Deluxe Room',
'description': 'Spacious deluxe rooms with enhanced amenities and premium furnishings. Ideal for guests seeking extra comfort and space.',
'base_price': Decimal('220.00'),
'capacity': 2,
'amenities': json.dumps([
'Free WiFi',
'Smart TV',
'Air Conditioning',
'Premium Mini Bar',
'Work Desk',
'In-room Safe',
'Nespresso Machine',
'Hair Dryer',
'Bathrobe & Slippers',
'City View'
])
},
{
'name': 'Executive Suite',
'description': 'Luxurious suites with separate living areas, perfect for extended stays or guests who prefer extra space and privacy.',
'base_price': Decimal('350.00'),
'capacity': 3,
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Air Conditioning',
'Premium Mini Bar',
'Separate Living Area',
'In-room Safe',
'Nespresso Machine',
'Hair Dryer',
'Bathrobe & Slippers',
'Panoramic View',
'Premium Toiletries',
'Welcome Amenities'
])
},
{
'name': 'Presidential Suite',
'description': 'The ultimate in luxury accommodation. Spacious multi-room suite with premium amenities, private terrace, and personalized butler service.',
'base_price': Decimal('800.00'),
'capacity': 4,
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Air Conditioning',
'Premium Mini Bar',
'Separate Living & Dining Areas',
'In-room Safe',
'Nespresso Machine',
'Hair Dryer',
'Bathrobe & Slippers',
'Panoramic View',
'Premium Toiletries',
'Welcome Amenities',
'Private Terrace',
'Butler Service',
'Private Bar',
'Jacuzzi'
])
},
{
'name': 'Ocean View Room',
'description': 'Stunning ocean view rooms with floor-to-ceiling windows and private balconies. Perfect for romantic getaways and relaxation.',
'base_price': Decimal('280.00'),
'capacity': 2,
'amenities': json.dumps([
'Free WiFi',
'Smart TV',
'Air Conditioning',
'Premium Mini Bar',
'Work Desk',
'In-room Safe',
'Nespresso Machine',
'Hair Dryer',
'Bathrobe & Slippers',
'Ocean View',
'Private Balcony',
'Premium Toiletries'
])
},
{
'name': 'Family Room',
'description': 'Spacious family-friendly rooms designed to accommodate families with children. Features extra beds and family amenities.',
'base_price': Decimal('300.00'),
'capacity': 4,
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Air Conditioning',
'Mini Bar',
'Extra Beds',
'In-room Safe',
'Coffee Maker',
'Hair Dryer',
'Family Amenities',
'Game Console',
'Child Safety Features'
])
}
]
def get_rooms_data(room_type_map):
"""Generate rooms data based on room types"""
now = datetime.now(timezone.utc)
rooms = []
# Standard Rooms (Floors 1-3, Rooms 101-130)
standard_type = room_type_map.get('Standard Room')
if standard_type:
for floor in range(1, 4):
for room_num in range(1, 11):
room_number = f"{floor}{room_num:02d}"
rooms.append({
'room_type_id': standard_type.id,
'room_number': room_number,
'floor': floor,
'status': RoomStatus.available,
'price': Decimal('150.00'),
'featured': room_num <= 2, # First 2 rooms per floor are featured
'capacity': 2,
'room_size': '25 sqm',
'view': 'City View',
'images': json.dumps([
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Flat-screen TV',
'Air Conditioning',
'Mini Bar',
'Work Desk',
'In-room Safe'
]),
'description': f'Comfortable standard room on floor {floor} with modern amenities and city view. Perfect for business travelers and couples.'
})
# Deluxe Rooms (Floors 4-6, Rooms 401-430)
deluxe_type = room_type_map.get('Deluxe Room')
if deluxe_type:
for floor in range(4, 7):
for room_num in range(1, 11):
room_number = f"{floor}{room_num:02d}"
rooms.append({
'room_type_id': deluxe_type.id,
'room_number': room_number,
'floor': floor,
'status': RoomStatus.available,
'price': Decimal('220.00'),
'featured': room_num <= 2,
'capacity': 2,
'room_size': '35 sqm',
'view': 'City View',
'images': json.dumps([
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Smart TV',
'Air Conditioning',
'Premium Mini Bar',
'Work Desk',
'Nespresso Machine',
'Bathrobe & Slippers'
]),
'description': f'Spacious deluxe room on floor {floor} with premium amenities and enhanced comfort. Ideal for guests seeking extra space.'
})
# Executive Suites (Floors 7-8, Rooms 701-720)
executive_type = room_type_map.get('Executive Suite')
if executive_type:
for floor in range(7, 9):
for room_num in range(1, 11):
room_number = f"{floor}{room_num:02d}"
rooms.append({
'room_type_id': executive_type.id,
'room_number': room_number,
'floor': floor,
'status': RoomStatus.available,
'price': Decimal('350.00'),
'featured': room_num <= 3,
'capacity': 3,
'room_size': '55 sqm',
'view': 'Panoramic View',
'images': json.dumps([
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Separate Living Area',
'Premium Mini Bar',
'Nespresso Machine',
'Bathrobe & Slippers',
'Premium Toiletries',
'Welcome Amenities'
]),
'description': f'Luxurious executive suite on floor {floor} with separate living area and panoramic views. Perfect for extended stays.'
})
# Presidential Suites (Floor 9, Rooms 901-905)
presidential_type = room_type_map.get('Presidential Suite')
if presidential_type:
for room_num in range(1, 6):
room_number = f"9{room_num:02d}"
rooms.append({
'room_type_id': presidential_type.id,
'room_number': room_number,
'floor': 9,
'status': RoomStatus.available,
'price': Decimal('800.00'),
'featured': True, # All presidential suites are featured
'capacity': 4,
'room_size': '120 sqm',
'view': 'Panoramic View',
'images': json.dumps([
'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Separate Living & Dining Areas',
'Private Terrace',
'Butler Service',
'Premium Mini Bar',
'Private Bar',
'Jacuzzi',
'Premium Toiletries',
'Welcome Amenities'
]),
'description': f'Ultimate luxury in our exclusive presidential suite. Features grand living room, formal dining, private terrace, and personal butler service. Suite {room_num}.'
})
# Ocean View Rooms (Floor 10, Rooms 1001-1020)
ocean_type = room_type_map.get('Ocean View Room')
if ocean_type:
for room_num in range(1, 21):
room_number = f"10{room_num:02d}"
rooms.append({
'room_type_id': ocean_type.id,
'room_number': room_number,
'floor': 10,
'status': RoomStatus.available,
'price': Decimal('280.00'),
'featured': room_num <= 5,
'capacity': 2,
'room_size': '30 sqm',
'view': 'Ocean View',
'images': json.dumps([
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1587925358603-dc217c8a64f8?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Smart TV',
'Air Conditioning',
'Premium Mini Bar',
'Private Balcony',
'Nespresso Machine',
'Bathrobe & Slippers',
'Ocean View'
]),
'description': f'Stunning ocean view room with floor-to-ceiling windows and private balcony. Perfect for romantic getaways and relaxation.'
})
# Family Rooms (Floor 1, Rooms 111-120)
family_type = room_type_map.get('Family Room')
if family_type:
for room_num in range(11, 21):
room_number = f"1{room_num:02d}"
rooms.append({
'room_type_id': family_type.id,
'room_number': room_number,
'floor': 1,
'status': RoomStatus.available,
'price': Decimal('300.00'),
'featured': room_num <= 13,
'capacity': 4,
'room_size': '45 sqm',
'view': 'City View',
'images': json.dumps([
'https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&h=800&fit=crop',
'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&h=800&fit=crop'
]),
'amenities': json.dumps([
'Free WiFi',
'Smart TV (Multiple)',
'Air Conditioning',
'Mini Bar',
'Extra Beds',
'Game Console',
'Child Safety Features',
'Family Amenities'
]),
'description': f'Spacious family-friendly room on floor 1 designed to accommodate families with children. Features extra beds and family amenities.'
})
return rooms
def seed_room_types(db: Session):
"""Seed room types into the database"""
try:
room_types_data = get_room_types_data()
room_type_map = {}
now = datetime.now(timezone.utc)
for room_type_data in room_types_data:
existing = db.query(RoomType).filter(RoomType.name == room_type_data['name']).first()
if existing:
logger.info(f"Room type '{room_type_data['name']}' already exists. Updating...")
for key, value in room_type_data.items():
setattr(existing, key, value)
existing.updated_at = now
room_type_map[existing.name] = existing
else:
logger.info(f"Creating room type: {room_type_data['name']}")
room_type = RoomType(
**room_type_data,
created_at=now,
updated_at=now
)
db.add(room_type)
db.flush() # Flush to get the ID
room_type_map[room_type.name] = room_type
db.commit()
logger.info(f'Successfully seeded {len(room_type_map)} room types!')
return room_type_map
except Exception as e:
db.rollback()
logger.error(f'Error seeding room types: {str(e)}', exc_info=True)
raise
def seed_rooms(db: Session, room_type_map: dict, clear_existing: bool = False):
"""Seed rooms into the database"""
try:
if clear_existing:
logger.info('Clearing existing rooms...')
db.query(Room).delete()
db.commit()
logger.info('Existing rooms cleared.')
rooms_data = get_rooms_data(room_type_map)
now = datetime.now(timezone.utc)
created_count = 0
updated_count = 0
for room_data in rooms_data:
existing = db.query(Room).filter(Room.room_number == room_data['room_number']).first()
if existing:
logger.debug(f"Room '{room_data['room_number']}' already exists. Updating...")
for key, value in room_data.items():
setattr(existing, key, value)
existing.updated_at = now
updated_count += 1
else:
logger.debug(f"Creating room: {room_data['room_number']}")
room = Room(
**room_data,
created_at=now,
updated_at=now
)
db.add(room)
created_count += 1
db.commit()
logger.info(f'Successfully seeded rooms! Created: {created_count}, Updated: {updated_count}, Total: {len(rooms_data)}')
except Exception as e:
db.rollback()
logger.error(f'Error seeding rooms: {str(e)}', exc_info=True)
raise
def seed_rooms_and_types(db: Session, clear_existing: bool = False):
"""Seed both room types and rooms"""
room_type_map = seed_room_types(db)
seed_rooms(db, room_type_map, clear_existing=clear_existing)
return room_type_map
def main():
import argparse
parser = argparse.ArgumentParser(description='Seed room types and rooms')
parser.add_argument(
'--clear-rooms',
action='store_true',
help='Clear existing rooms before seeding (room types are updated, not cleared)'
)
args = parser.parse_args()
db = SessionLocal()
try:
seed_rooms_and_types(db, clear_existing=args.clear_rooms)
except Exception as e:
logger.error(f'Failed to seed rooms: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

184
Backend/seeders/run_seeder.py Executable file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env python3
"""
Seeder Runner
Run all seeders or specific seeders
"""
import sys
import argparse
from pathlib import Path
# Add parent directory to path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from homepage_seeder import seed_homepage
from about_seeder import seed_about_page
from contact_seeder import seed_contact_page
from privacy_seeder import seed_privacy_page
from faq_seeder import seed_faq_page
from accessibility_seeder import seed_accessibility_page
from refunds_seeder import seed_refunds_page
from terms_seeder import seed_terms_page
from cancellation_seeder import seed_cancellation_page
from footer_seeder import seed_footer_page
from banner_seeder import seed_banners
from user_seeder import seed_users_and_roles
from room_seeder import seed_rooms_and_types
from service_seeder import seed_services
from blog_seeder import seed_blog_posts
from settings_seeder import seed_settings
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
logger = get_logger(__name__)
def main():
parser = argparse.ArgumentParser(description='Run database seeders')
parser.add_argument(
'--seeder',
choices=['homepage', 'about', 'contact', 'privacy', 'faq', 'accessibility', 'refunds', 'terms', 'cancellation', 'footer', 'banners', 'users', 'rooms', 'services', 'blog', 'settings', 'all'],
default='all',
help='Which seeder to run (default: all)'
)
parser.add_argument(
'--clear-banners',
action='store_true',
help='Clear existing banners before seeding (only applies to banners seeder)'
)
parser.add_argument(
'--clear-rooms',
action='store_true',
help='Clear existing rooms before seeding (only applies to rooms seeder)'
)
parser.add_argument(
'--clear-services',
action='store_true',
help='Clear existing services before seeding (only applies to services seeder)'
)
parser.add_argument(
'--clear-blog',
action='store_true',
help='Clear existing blog posts before seeding (only applies to blog seeder)'
)
parser.add_argument(
'--clear-settings',
action='store_true',
help='Clear existing settings before seeding (only applies to settings seeder)'
)
parser.add_argument(
'--admin-email',
default='admin@hotel.com',
help='Admin user email (default: admin@hotel.com)'
)
parser.add_argument(
'--admin-password',
default='admin123',
help='Admin user password (default: admin123)'
)
parser.add_argument(
'--admin-name',
default='Admin User',
help='Admin user full name (default: Admin User)'
)
args = parser.parse_args()
db = SessionLocal()
try:
# Always seed users/roles first if running all or users seeder
if args.seeder == 'users' or args.seeder == 'all':
logger.info('Running user and role seeder...')
seed_users_and_roles(
db,
admin_email=args.admin_email,
admin_password=args.admin_password,
admin_name=args.admin_name
)
logger.info('User and role seeder completed!')
if args.seeder == 'homepage' or args.seeder == 'all':
logger.info('Running homepage seeder...')
seed_homepage(db)
logger.info('Homepage seeder completed!')
if args.seeder == 'about' or args.seeder == 'all':
logger.info('Running about page seeder...')
seed_about_page(db)
logger.info('About page seeder completed!')
if args.seeder == 'contact' or args.seeder == 'all':
logger.info('Running contact page seeder...')
seed_contact_page(db)
logger.info('Contact page seeder completed!')
if args.seeder == 'privacy' or args.seeder == 'all':
logger.info('Running privacy policy page seeder...')
seed_privacy_page(db)
logger.info('Privacy policy page seeder completed!')
if args.seeder == 'faq' or args.seeder == 'all':
logger.info('Running FAQ page seeder...')
seed_faq_page(db)
logger.info('FAQ page seeder completed!')
if args.seeder == 'accessibility' or args.seeder == 'all':
logger.info('Running accessibility page seeder...')
seed_accessibility_page(db)
logger.info('Accessibility page seeder completed!')
if args.seeder == 'refunds' or args.seeder == 'all':
logger.info('Running refunds policy page seeder...')
seed_refunds_page(db)
logger.info('Refunds policy page seeder completed!')
if args.seeder == 'terms' or args.seeder == 'all':
logger.info('Running terms of use page seeder...')
seed_terms_page(db)
logger.info('Terms of use page seeder completed!')
if args.seeder == 'cancellation' or args.seeder == 'all':
logger.info('Running cancellation policy page seeder...')
seed_cancellation_page(db)
logger.info('Cancellation policy page seeder completed!')
if args.seeder == 'footer' or args.seeder == 'all':
logger.info('Running footer page seeder...')
seed_footer_page(db)
logger.info('Footer page seeder completed!')
if args.seeder == 'banners' or args.seeder == 'all':
logger.info('Running banner seeder...')
seed_banners(db, clear_existing=args.clear_banners)
logger.info('Banner seeder completed!')
if args.seeder == 'rooms' or args.seeder == 'all':
logger.info('Running room seeder...')
seed_rooms_and_types(db, clear_existing=args.clear_rooms)
logger.info('Room seeder completed!')
if args.seeder == 'services' or args.seeder == 'all':
logger.info('Running service seeder...')
seed_services(db, clear_existing=args.clear_services)
logger.info('Service seeder completed!')
if args.seeder == 'blog' or args.seeder == 'all':
logger.info('Running blog seeder...')
seed_blog_posts(db, clear_existing=args.clear_blog)
logger.info('Blog seeder completed!')
if args.seeder == 'settings' or args.seeder == 'all':
logger.info('Running settings seeder...')
seed_settings(db, clear_existing=args.clear_settings)
logger.info('Settings seeder completed!')
logger.info('All seeders completed successfully!')
except Exception as e:
logger.error(f'Seeder failed: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,413 @@
"""
Service Seeder
Seeds the database with hotel services
All images are from Unsplash (free stock photos)
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
from decimal import Decimal
import re
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.hotel_services.models.service import Service
# Import all models to ensure relationships are loaded correctly
from src.models import *
logger = get_logger(__name__)
def slugify(text):
"""Convert text to URL-friendly slug"""
text = text.lower()
text = re.sub(r'[^\w\s-]', '', text)
text = re.sub(r'[-\s]+', '-', text)
return text.strip('-')
def get_services_data():
"""Generate comprehensive services data with Unsplash images"""
now = datetime.now(timezone.utc)
services = [
# Spa & Wellness Services
{
'name': 'Luxury Spa Treatment',
'description': 'Indulge in our signature spa treatments designed to rejuvenate your mind, body, and soul. Experience ultimate relaxation with our expert therapists.',
'price': Decimal('150.00'),
'category': 'Spa & Wellness',
'slug': 'luxury-spa-treatment',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1200&h=800&fit=crop',
'content': '<p>Our luxury spa treatments combine traditional techniques with modern wellness practices. Choose from a variety of massages, facials, and body treatments tailored to your needs.</p>',
'sections': json.dumps([
{
'type': 'features',
'title': 'Treatment Options',
'content': 'Swedish Massage, Deep Tissue, Hot Stone, Aromatherapy, Facial Treatments',
'alignment': 'left',
'is_visible': True
}
]),
'meta_title': 'Luxury Spa Treatment | Hotel Spa Services',
'meta_description': 'Experience ultimate relaxation with our luxury spa treatments. Expert therapists, premium products, and serene environment.',
'meta_keywords': 'spa, massage, wellness, relaxation, hotel spa, luxury treatment',
'is_active': True
},
{
'name': 'Couples Massage',
'description': 'Share a relaxing experience with your partner in our private couples massage room. Perfect for romantic getaways and special occasions.',
'price': Decimal('280.00'),
'category': 'Spa & Wellness',
'slug': 'couples-massage',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1200&h=800&fit=crop',
'content': '<p>Enjoy a synchronized massage experience with your loved one in our beautifully appointed couples suite. Includes champagne and chocolate-covered strawberries.</p>',
'sections': None,
'meta_title': 'Couples Massage | Romantic Spa Experience',
'meta_description': 'Share a romantic spa experience with couples massage. Private suite, synchronized treatments, and special amenities included.',
'meta_keywords': 'couples massage, romantic spa, couples treatment, hotel spa',
'is_active': True
},
{
'name': 'Facial Treatment',
'description': 'Rejuvenate your skin with our professional facial treatments using premium skincare products. Customized for your skin type.',
'price': Decimal('120.00'),
'category': 'Spa & Wellness',
'slug': 'facial-treatment',
'image': 'https://images.unsplash.com/photo-1570172619644-dfd03ed5d881?w=1200&h=800&fit=crop',
'content': '<p>Our expert estheticians provide personalized facial treatments to address your specific skin concerns. Includes deep cleansing, exfoliation, and hydration.</p>',
'sections': None,
'meta_title': 'Facial Treatment | Professional Skincare Services',
'meta_description': 'Professional facial treatments with premium products. Customized for your skin type by expert estheticians.',
'meta_keywords': 'facial, skincare, spa facial, beauty treatment',
'is_active': True
},
# Dining Services
{
'name': 'Fine Dining Experience',
'description': 'Savor exquisite cuisine at our award-winning restaurant. Chef-prepared meals with the finest ingredients and impeccable service.',
'price': Decimal('200.00'),
'category': 'Dining',
'slug': 'fine-dining-experience',
'image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&h=800&fit=crop',
'content': '<p>Experience culinary excellence at our Michelin-starred restaurant. Our talented chefs create innovative dishes using locally sourced, seasonal ingredients.</p>',
'sections': json.dumps([
{
'type': 'menu',
'title': 'Signature Dishes',
'content': 'Truffle Risotto, Wagyu Beef, Lobster Thermidor, Seasonal Tasting Menu',
'alignment': 'center',
'is_visible': True
}
]),
'meta_title': 'Fine Dining Restaurant | Award-Winning Cuisine',
'meta_description': 'Experience award-winning fine dining with chef-prepared meals, premium ingredients, and exceptional service.',
'meta_keywords': 'fine dining, restaurant, gourmet, Michelin, hotel restaurant',
'is_active': True
},
{
'name': 'Room Service',
'description': 'Enjoy delicious meals in the comfort of your room. Available 24/7 with an extensive menu of international and local cuisine.',
'price': Decimal('50.00'),
'category': 'Dining',
'slug': 'room-service',
'image': 'https://images.unsplash.com/photo-1551632811-5617803d319f?w=1200&h=800&fit=crop',
'content': '<p>Our room service menu features breakfast, lunch, dinner, and late-night options. All dishes are prepared fresh and delivered to your room with professional service.</p>',
'sections': None,
'meta_title': '24/7 Room Service | In-Room Dining',
'meta_description': 'Enjoy delicious meals in your room with our 24/7 room service. Extensive menu, fresh preparation, and professional delivery.',
'meta_keywords': 'room service, in-room dining, hotel food delivery',
'is_active': True
},
{
'name': 'Private Chef Service',
'description': 'Experience gourmet dining in the privacy of your suite with a personal chef. Customized menus and intimate dining experience.',
'price': Decimal('500.00'),
'category': 'Dining',
'slug': 'private-chef-service',
'image': 'https://images.unsplash.com/photo-1577219491135-ce391730fd43?w=1200&h=800&fit=crop',
'content': '<p>Our private chef service brings fine dining directly to your suite. Work with our chef to create a customized menu for your special occasion.</p>',
'sections': None,
'meta_title': 'Private Chef Service | In-Suite Dining',
'meta_description': 'Enjoy a private chef experience in your suite. Customized menus, intimate dining, and exceptional culinary expertise.',
'meta_keywords': 'private chef, in-suite dining, personal chef, luxury dining',
'is_active': True
},
# Concierge Services
{
'name': '24/7 Concierge Service',
'description': 'Our dedicated concierge team is available around the clock to assist with restaurant reservations, event tickets, transportation, and more.',
'price': Decimal('0.00'),
'category': 'Concierge',
'slug': 'concierge-service',
'image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=800&fit=crop',
'content': '<p>From restaurant reservations to exclusive experiences, our concierge team ensures your stay is seamless and memorable. Available 24/7 for all your needs.</p>',
'sections': json.dumps([
{
'type': 'services',
'title': 'Concierge Services',
'content': 'Restaurant Reservations, Event Tickets, Transportation, City Tours, Special Occasions',
'alignment': 'left',
'is_visible': True
}
]),
'meta_title': '24/7 Concierge Service | Personal Assistance',
'meta_description': 'Round-the-clock concierge service for restaurant reservations, tickets, transportation, and personalized assistance.',
'meta_keywords': 'concierge, personal assistant, hotel concierge, guest services',
'is_active': True
},
{
'name': 'Airport Transfer',
'description': 'Enjoy seamless airport transfers in our luxury vehicles. Professional drivers and comfortable transportation to and from the airport.',
'price': Decimal('80.00'),
'category': 'Transportation',
'slug': 'airport-transfer',
'image': 'https://images.unsplash.com/photo-1583485088076-494435075764?w=1200&h=800&fit=crop',
'content': '<p>Start and end your journey in comfort with our premium airport transfer service. Available for all major airports with luxury vehicles and professional drivers.</p>',
'sections': None,
'meta_title': 'Airport Transfer Service | Luxury Transportation',
'meta_description': 'Premium airport transfer service with luxury vehicles and professional drivers. Seamless transportation to and from the airport.',
'meta_keywords': 'airport transfer, transportation, airport shuttle, luxury car service',
'is_active': True
},
{
'name': 'City Tour Service',
'description': 'Discover the city with our guided tour service. Customized itineraries and expert local guides to show you the best attractions.',
'price': Decimal('150.00'),
'category': 'Concierge',
'slug': 'city-tour-service',
'image': 'https://images.unsplash.com/photo-1488646953014-85cb44e25828?w=1200&h=800&fit=crop',
'content': '<p>Explore the city with our professional tour guides. Choose from standard tours or customize your itinerary to visit your preferred attractions.</p>',
'sections': None,
'meta_title': 'City Tour Service | Guided Tours',
'meta_description': 'Discover the city with our guided tour service. Expert guides, customized itineraries, and memorable experiences.',
'meta_keywords': 'city tour, guided tour, sightseeing, local attractions',
'is_active': True
},
# Business Services
{
'name': 'Business Center Access',
'description': 'Access our fully equipped business center with computers, printers, meeting rooms, and high-speed internet. Perfect for business travelers.',
'price': Decimal('25.00'),
'category': 'Business',
'slug': 'business-center-access',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&h=800&fit=crop',
'content': '<p>Our business center provides all the facilities you need for productive work. Includes private workstations, printing services, and meeting spaces.</p>',
'sections': None,
'meta_title': 'Business Center | Professional Workspace',
'meta_description': 'Fully equipped business center with computers, printers, meeting rooms, and high-speed internet for business travelers.',
'meta_keywords': 'business center, workspace, meeting room, business facilities',
'is_active': True
},
{
'name': 'Meeting Room Rental',
'description': 'Host your business meetings in our state-of-the-art meeting rooms. Equipped with modern technology and professional amenities.',
'price': Decimal('300.00'),
'category': 'Business',
'slug': 'meeting-room-rental',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&h=800&fit=crop',
'content': '<p>Our meeting rooms accommodate various group sizes and are equipped with AV equipment, high-speed internet, and catering options.</p>',
'sections': None,
'meta_title': 'Meeting Room Rental | Business Facilities',
'meta_description': 'State-of-the-art meeting rooms with modern technology, AV equipment, and professional amenities for your business needs.',
'meta_keywords': 'meeting room, conference room, business meeting, event space',
'is_active': True
},
# Additional Services
{
'name': 'Laundry & Dry Cleaning',
'description': 'Professional laundry and dry cleaning services. Same-day service available for your convenience.',
'price': Decimal('30.00'),
'category': 'Housekeeping',
'slug': 'laundry-dry-cleaning',
'image': 'https://images.unsplash.com/photo-1582735689369-4fe89db7114c?w=1200&h=800&fit=crop',
'content': '<p>Keep your wardrobe fresh with our professional laundry and dry cleaning services. Same-day service available for urgent needs.</p>',
'sections': None,
'meta_title': 'Laundry & Dry Cleaning Service',
'meta_description': 'Professional laundry and dry cleaning services with same-day service available. Keep your wardrobe fresh during your stay.',
'meta_keywords': 'laundry, dry cleaning, clothing service, hotel laundry',
'is_active': True
},
{
'name': 'Fitness Center Access',
'description': 'Access our state-of-the-art fitness center with modern equipment, personal trainers, and group fitness classes.',
'price': Decimal('0.00'),
'category': 'Fitness',
'slug': 'fitness-center-access',
'image': 'https://images.unsplash.com/photo-1534438747741-0bf23ca35f0d?w=1200&h=800&fit=crop',
'content': '<p>Maintain your fitness routine in our fully equipped gym. Features cardio equipment, weight training, and personal training sessions available.</p>',
'sections': None,
'meta_title': 'Fitness Center | Hotel Gym Access',
'meta_description': 'State-of-the-art fitness center with modern equipment, personal trainers, and group fitness classes. Stay fit during your stay.',
'meta_keywords': 'fitness center, gym, workout, exercise, hotel gym',
'is_active': True
},
{
'name': 'Personal Shopper',
'description': 'Discover the city\'s best boutiques and shopping destinations with our expert personal shopper. Tailored shopping experiences.',
'price': Decimal('200.00'),
'category': 'Concierge',
'slug': 'personal-shopper',
'image': 'https://images.unsplash.com/photo-1528716321680-815a8cdb8bc7?w=1200&h=800&fit=crop',
'content': '<p>Let our personal shopper guide you to the best shopping destinations. From luxury boutiques to local markets, we\'ll help you find exactly what you\'re looking for.</p>',
'sections': None,
'meta_title': 'Personal Shopper Service | Shopping Assistance',
'meta_description': 'Expert personal shopper service to guide you to the best boutiques and shopping destinations. Tailored shopping experiences.',
'meta_keywords': 'personal shopper, shopping service, boutique shopping, shopping guide',
'is_active': True
},
{
'name': 'Valet Parking',
'description': 'Complimentary valet parking service for all hotel guests. Secure parking with professional valet attendants.',
'price': Decimal('0.00'),
'category': 'Transportation',
'slug': 'valet-parking',
'image': 'https://images.unsplash.com/photo-1502877338535-766e1452684a?w=1200&h=800&fit=crop',
'content': '<p>Enjoy the convenience of valet parking. Our professional attendants will safely park and retrieve your vehicle whenever needed.</p>',
'sections': None,
'meta_title': 'Valet Parking Service | Complimentary Parking',
'meta_description': 'Complimentary valet parking service with professional attendants. Secure and convenient parking for all hotel guests.',
'meta_keywords': 'valet parking, parking service, hotel parking',
'is_active': True
},
{
'name': 'Butler Service',
'description': 'Experience personalized butler service for suite guests. Available 24/7 to attend to your every need and ensure a flawless stay.',
'price': Decimal('0.00'),
'category': 'Concierge',
'slug': 'butler-service',
'image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=800&fit=crop',
'content': '<p>Our dedicated butlers provide personalized service to suite guests. From unpacking to arranging special requests, we ensure every detail is perfect.</p>',
'sections': None,
'meta_title': 'Butler Service | Personalized Assistance',
'meta_description': 'Personalized butler service for suite guests. Available 24/7 to attend to your every need and ensure a flawless stay.',
'meta_keywords': 'butler service, personal butler, suite service, luxury service',
'is_active': True
},
{
'name': 'Event Planning',
'description': 'Let our expert event planners organize your special occasion. From intimate dinners to grand celebrations, we handle every detail.',
'price': Decimal('500.00'),
'category': 'Events',
'slug': 'event-planning',
'image': 'https://images.unsplash.com/photo-1519167758481-83f29da1c4fe?w=1200&h=800&fit=crop',
'content': '<p>Our event planning team will work with you to create unforgettable celebrations. From venue selection to catering and entertainment, we manage it all.</p>',
'sections': None,
'meta_title': 'Event Planning Service | Special Occasions',
'meta_description': 'Expert event planning service for special occasions. From intimate dinners to grand celebrations, we handle every detail.',
'meta_keywords': 'event planning, party planning, special events, celebration planning',
'is_active': True
},
{
'name': 'Photography Service',
'description': 'Capture your special moments with our professional photography service. Available for events, portraits, and special occasions.',
'price': Decimal('300.00'),
'category': 'Events',
'slug': 'photography-service',
'image': 'https://images.unsplash.com/photo-1516035069371-29a1b244cc32?w=1200&h=800&fit=crop',
'content': '<p>Our professional photographers will capture your special moments with artistic flair. Perfect for weddings, anniversaries, and other celebrations.</p>',
'sections': None,
'meta_title': 'Professional Photography Service',
'meta_description': 'Professional photography service for events, portraits, and special occasions. Capture your special moments with artistic flair.',
'meta_keywords': 'photography, photographer, event photography, portrait photography',
'is_active': True
},
{
'name': 'Babysitting Service',
'description': 'Professional babysitting service for families. Certified caregivers available to watch your children while you enjoy your stay.',
'price': Decimal('50.00'),
'category': 'Family',
'slug': 'babysitting-service',
'image': 'https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?w=1200&h=800&fit=crop',
'content': '<p>Enjoy peace of mind with our professional babysitting service. All caregivers are certified and experienced in childcare.</p>',
'sections': None,
'meta_title': 'Babysitting Service | Childcare',
'meta_description': 'Professional babysitting service with certified caregivers. Enjoy your stay while your children are safely cared for.',
'meta_keywords': 'babysitting, childcare, kids service, family service',
'is_active': True
}
]
return services
def seed_services(db: Session, clear_existing: bool = False):
"""Seed services into the database"""
try:
if clear_existing:
logger.info('Clearing existing services...')
db.query(Service).delete()
db.commit()
logger.info('Existing services cleared.')
services_data = get_services_data()
now = datetime.now(timezone.utc)
created_count = 0
updated_count = 0
for service_data in services_data:
# Generate slug if not provided
if not service_data.get('slug'):
service_data['slug'] = slugify(service_data['name'])
existing = db.query(Service).filter(Service.slug == service_data['slug']).first()
if existing:
logger.debug(f"Service '{service_data['name']}' already exists. Updating...")
for key, value in service_data.items():
setattr(existing, key, value)
existing.updated_at = now
updated_count += 1
else:
logger.debug(f"Creating service: {service_data['name']}")
service = Service(
**service_data,
created_at=now,
updated_at=now
)
db.add(service)
created_count += 1
db.commit()
logger.info(f'Successfully seeded services! Created: {created_count}, Updated: {updated_count}, Total: {len(services_data)}')
except Exception as e:
db.rollback()
logger.error(f'Error seeding services: {str(e)}', exc_info=True)
raise
def main():
import argparse
parser = argparse.ArgumentParser(description='Seed hotel services')
parser.add_argument(
'--clear',
action='store_true',
help='Clear existing services before seeding'
)
args = parser.parse_args()
db = SessionLocal()
try:
seed_services(db, clear_existing=args.clear)
except Exception as e:
logger.error(f'Failed to seed services: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,339 @@
"""
Settings Seeder
Seeds the database with system settings
"""
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.system.models.system_settings import SystemSettings
from src.auth.models.user import User
# Import all models to ensure relationships are loaded correctly
from src.models import *
logger = get_logger(__name__)
def get_settings_data():
"""Generate comprehensive system settings data"""
return [
# Company Settings
{
'key': 'company_name',
'value': 'Luxury Hotel & Resort',
'description': 'The official name of the hotel/company'
},
{
'key': 'company_tagline',
'value': 'Experience Unparalleled Elegance and Comfort',
'description': 'Company tagline or slogan'
},
{
'key': 'company_logo_url',
'value': 'https://ui-avatars.com/api/?name=Luxury+Hotel&background=d4af37&color=fff&size=400&bold=true&font-size=0.5',
'description': 'URL to the company logo image'
},
{
'key': 'company_favicon_url',
'value': 'https://ui-avatars.com/api/?name=LH&background=d4af37&color=fff&size=64&bold=true',
'description': 'URL to the company favicon image'
},
{
'key': 'company_phone',
'value': '+1 (555) 123-4567',
'description': 'Primary company phone number'
},
{
'key': 'company_email',
'value': 'info@luxuryhotel.com',
'description': 'Primary company email address'
},
{
'key': 'company_address',
'value': '123 Luxury Avenue, Premium City, PC 12345, United States',
'description': 'Company physical address'
},
{
'key': 'tax_rate',
'value': '10.0',
'description': 'Default tax rate percentage (e.g., 10.0 for 10%)'
},
{
'key': 'chat_working_hours_start',
'value': '9',
'description': 'Chat support working hours start (24-hour format, e.g., 9 for 9 AM)'
},
{
'key': 'chat_working_hours_end',
'value': '18',
'description': 'Chat support working hours end (24-hour format, e.g., 18 for 6 PM)'
},
# Platform Settings
{
'key': 'platform_currency',
'value': 'USD',
'description': 'Default platform currency code (ISO 4217 format, e.g., USD, EUR, GBP)'
},
# Payment Gateway Settings (Placeholder values - should be configured in production)
{
'key': 'stripe_secret_key',
'value': '',
'description': 'Stripe secret API key (configure in production)'
},
{
'key': 'stripe_publishable_key',
'value': '',
'description': 'Stripe publishable API key (configure in production)'
},
{
'key': 'stripe_webhook_secret',
'value': '',
'description': 'Stripe webhook secret for verifying webhook events (configure in production)'
},
{
'key': 'paypal_client_id',
'value': '',
'description': 'PayPal client ID (configure in production)'
},
{
'key': 'paypal_client_secret',
'value': '',
'description': 'PayPal client secret (configure in production)'
},
{
'key': 'paypal_mode',
'value': 'sandbox',
'description': 'PayPal mode: "sandbox" for testing, "live" for production'
},
{
'key': 'borica_terminal_id',
'value': '',
'description': 'Borica terminal ID (configure if using Borica payment gateway)'
},
{
'key': 'borica_merchant_id',
'value': '',
'description': 'Borica merchant ID (configure if using Borica payment gateway)'
},
{
'key': 'borica_private_key_path',
'value': '',
'description': 'Path to Borica private key file (configure if using Borica)'
},
{
'key': 'borica_certificate_path',
'value': '',
'description': 'Path to Borica certificate file (configure if using Borica)'
},
{
'key': 'borica_gateway_url',
'value': '',
'description': 'Borica gateway URL (configure if using Borica payment gateway)'
},
{
'key': 'borica_mode',
'value': 'test',
'description': 'Borica mode: "test" for testing, "production" for live transactions'
},
# SMTP Settings (Placeholder values - should be configured in production)
{
'key': 'smtp_host',
'value': '',
'description': 'SMTP server hostname (e.g., smtp.gmail.com, smtp.sendgrid.net)'
},
{
'key': 'smtp_port',
'value': '587',
'description': 'SMTP server port (587 for STARTTLS, 465 for SSL)'
},
{
'key': 'smtp_user',
'value': '',
'description': 'SMTP authentication username/email'
},
{
'key': 'smtp_password',
'value': '',
'description': 'SMTP authentication password (stored securely)'
},
{
'key': 'smtp_from_email',
'value': 'noreply@luxuryhotel.com',
'description': 'Default "From" email address for outgoing emails'
},
{
'key': 'smtp_from_name',
'value': 'Luxury Hotel & Resort',
'description': 'Default "From" name for outgoing emails'
},
{
'key': 'smtp_use_tls',
'value': 'true',
'description': 'Use TLS/SSL for SMTP connection (true for port 465, false for port 587 with STARTTLS)'
},
# Security Settings
{
'key': 'recaptcha_site_key',
'value': '',
'description': 'Google reCAPTCHA site key (configure if using reCAPTCHA)'
},
{
'key': 'recaptcha_secret_key',
'value': '',
'description': 'Google reCAPTCHA secret key (configure if using reCAPTCHA)'
},
{
'key': 'recaptcha_enabled',
'value': 'false',
'description': 'Enable/disable reCAPTCHA verification (true/false)'
},
# Additional Settings
{
'key': 'booking_confirmation_email_enabled',
'value': 'true',
'description': 'Enable automatic booking confirmation emails (true/false)'
},
{
'key': 'booking_cancellation_email_enabled',
'value': 'true',
'description': 'Enable automatic booking cancellation emails (true/false)'
},
{
'key': 'newsletter_enabled',
'value': 'true',
'description': 'Enable newsletter subscription feature (true/false)'
},
{
'key': 'maintenance_mode',
'value': 'false',
'description': 'Enable maintenance mode (true/false)'
},
{
'key': 'maintenance_message',
'value': 'We are currently performing scheduled maintenance. Please check back soon.',
'description': 'Message to display when maintenance mode is enabled'
},
{
'key': 'default_checkin_time',
'value': '15:00',
'description': 'Default check-in time (24-hour format, e.g., 15:00 for 3 PM)'
},
{
'key': 'default_checkout_time',
'value': '11:00',
'description': 'Default check-out time (24-hour format, e.g., 11:00 for 11 AM)'
},
{
'key': 'cancellation_hours',
'value': '24',
'description': 'Number of hours before check-in that cancellation is allowed without penalty'
},
{
'key': 'max_guests_per_room',
'value': '4',
'description': 'Maximum number of guests allowed per room'
},
{
'key': 'min_booking_advance_days',
'value': '0',
'description': 'Minimum number of days in advance required for booking (0 = same day allowed)'
},
{
'key': 'max_booking_advance_days',
'value': '365',
'description': 'Maximum number of days in advance bookings can be made'
}
]
def seed_settings(db: Session, clear_existing: bool = False, admin_user_id: int = None):
"""Seed system settings into the database"""
try:
if clear_existing:
logger.info('Clearing existing system settings...')
db.query(SystemSettings).delete()
db.commit()
logger.info('Existing system settings cleared.')
# Get admin user if not provided
if admin_user_id is None:
admin_user = db.query(User).filter(User.email == 'admin@hotel.com').first()
if admin_user:
admin_user_id = admin_user.id
else:
logger.warning('Admin user not found. Settings will be created without updated_by_id.')
settings_data = get_settings_data()
now = datetime.now(timezone.utc)
created_count = 0
updated_count = 0
for setting_data in settings_data:
existing = db.query(SystemSettings).filter(SystemSettings.key == setting_data['key']).first()
if existing:
logger.debug(f"Setting '{setting_data['key']}' already exists. Updating...")
existing.value = setting_data['value']
existing.description = setting_data['description']
if admin_user_id:
existing.updated_by_id = admin_user_id
existing.updated_at = now
updated_count += 1
else:
logger.debug(f"Creating setting: {setting_data['key']}")
setting = SystemSettings(
key=setting_data['key'],
value=setting_data['value'],
description=setting_data['description'],
updated_by_id=admin_user_id,
updated_at=now
)
db.add(setting)
created_count += 1
db.commit()
logger.info(f'Successfully seeded system settings! Created: {created_count}, Updated: {updated_count}, Total: {len(settings_data)}')
except Exception as e:
db.rollback()
logger.error(f'Error seeding system settings: {str(e)}', exc_info=True)
raise
def main():
import argparse
parser = argparse.ArgumentParser(description='Seed system settings')
parser.add_argument(
'--clear',
action='store_true',
help='Clear existing settings before seeding'
)
args = parser.parse_args()
db = SessionLocal()
try:
seed_settings(db, clear_existing=args.clear)
except Exception as e:
logger.error(f'Failed to seed system settings: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,178 @@
"""
Terms of Use Page Seeder
Seeds the database with comprehensive terms of use content
"""
import json
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add parent directory to path to allow importing from src
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.shared.config.logging_config import get_logger
from src.content.models.page_content import PageContent, PageType
# Import all models to ensure relationships are loaded
from src.models import *
logger = get_logger(__name__)
def get_terms_page_data():
"""Generate comprehensive terms of use page data"""
now = datetime.now(timezone.utc)
return {
'page_type': PageType.TERMS,
'title': 'Terms of Use',
'subtitle': 'Terms and Conditions for Using Our Services',
'description': 'Please read these terms and conditions carefully before using our website or services. By using our services, you agree to be bound by these terms.',
'content': """
<h2>1. Acceptance of Terms</h2>
<p>By accessing and using the Luxury Hotel & Resort website and services, you accept and agree to be bound by the terms and provision of this agreement. If you do not agree to these terms, please do not use our services.</p>
<h2>2. Use of Website</h2>
<h3>2.1 Eligibility</h3>
<p>You must be at least 18 years old to make a reservation or use our services. By using our website, you represent and warrant that you are at least 18 years of age and have the legal capacity to enter into this agreement.</p>
<h3>2.2 User Account</h3>
<p>If you create an account with us, you are responsible for maintaining the confidentiality of your account and password. You agree to accept responsibility for all activities that occur under your account.</p>
<h3>2.3 Prohibited Uses</h3>
<p>You agree not to use our website or services:</p>
<ul>
<li>For any unlawful purpose or to solicit others to perform unlawful acts</li>
<li>To violate any international, federal, provincial, or state regulations, rules, laws, or local ordinances</li>
<li>To infringe upon or violate our intellectual property rights or the intellectual property rights of others</li>
<li>To harass, abuse, insult, harm, defame, slander, disparage, intimidate, or discriminate</li>
<li>To submit false or misleading information</li>
<li>To upload or transmit viruses or any other type of malicious code</li>
<li>To collect or track the personal information of others</li>
<li>To spam, phish, pharm, pretext, spider, crawl, or scrape</li>
<li>For any obscene or immoral purpose</li>
<li>To interfere with or circumvent the security features of our website</li>
</ul>
<h2>3. Reservations and Bookings</h2>
<h3>3.1 Reservation Terms</h3>
<p>When you make a reservation through our website or by phone, you agree to:</p>
<ul>
<li>Provide accurate and complete information</li>
<li>Use a valid payment method</li>
<li>Pay all charges incurred by your account</li>
<li>Comply with our cancellation and refund policies</li>
</ul>
<h3>3.2 Pricing</h3>
<p>All prices are displayed in the currency specified and are subject to change without notice. We reserve the right to correct any pricing errors. Taxes and fees may apply and will be disclosed at the time of booking.</p>
<h3>3.3 Payment</h3>
<p>Payment is required at the time of booking or as specified in your reservation confirmation. We accept major credit cards and other payment methods as indicated on our website.</p>
<h2>4. Cancellation and Refund Policy</h2>
<p>Cancellation and refund terms vary by rate type and are specified at the time of booking. Please refer to your booking confirmation and our Refund Policy for detailed information.</p>
<h2>5. Intellectual Property</h2>
<p>The content on our website, including text, graphics, logos, images, and software, is the property of Luxury Hotel & Resort or its content suppliers and is protected by copyright and other intellectual property laws. You may not reproduce, distribute, modify, or create derivative works from any content without our express written permission.</p>
<h2>6. User Content</h2>
<p>If you submit content to our website (such as reviews, comments, or photos), you grant us a non-exclusive, royalty-free, perpetual, and worldwide license to use, reproduce, modify, and distribute such content for any purpose.</p>
<h2>7. Limitation of Liability</h2>
<p>To the fullest extent permitted by law, Luxury Hotel & Resort shall not be liable for any indirect, incidental, special, consequential, or punitive damages, or any loss of profits or revenues, whether incurred directly or indirectly, or any loss of data, use, goodwill, or other intangible losses resulting from your use of our services.</p>
<h2>8. Indemnification</h2>
<p>You agree to indemnify, defend, and hold harmless Luxury Hotel & Resort and its officers, directors, employees, and agents from any claims, damages, losses, liabilities, and expenses (including legal fees) arising out of or relating to your use of our services or violation of these terms.</p>
<h2>9. Disclaimer of Warranties</h2>
<p>Our services are provided "as is" and "as available" without warranties of any kind, either express or implied. We do not warrant that our services will be uninterrupted, secure, or error-free.</p>
<h2>10. Third-Party Links</h2>
<p>Our website may contain links to third-party websites. We are not responsible for the content, privacy policies, or practices of third-party websites. Your use of third-party websites is at your own risk.</p>
<h2>11. Force Majeure</h2>
<p>We shall not be liable for any failure or delay in performance under these terms which is due to circumstances beyond our reasonable control, including but not limited to natural disasters, war, terrorism, pandemics, government actions, or other force majeure events.</p>
<h2>12. Governing Law</h2>
<p>These terms shall be governed by and construed in accordance with the laws of the jurisdiction in which our hotel is located, without regard to its conflict of law provisions.</p>
<h2>13. Dispute Resolution</h2>
<p>Any disputes arising out of or relating to these terms or our services shall be resolved through binding arbitration in accordance with the rules of the applicable arbitration association, except where prohibited by law.</p>
<h2>14. Changes to Terms</h2>
<p>We reserve the right to modify these terms at any time. Changes will be effective immediately upon posting on our website. Your continued use of our services after changes are posted constitutes acceptance of the modified terms.</p>
<h2>15. Severability</h2>
<p>If any provision of these terms is found to be unenforceable or invalid, that provision shall be limited or eliminated to the minimum extent necessary, and the remaining provisions shall remain in full force and effect.</p>
<h2>16. Entire Agreement</h2>
<p>These terms constitute the entire agreement between you and Luxury Hotel & Resort regarding the use of our services and supersede all prior agreements and understandings.</p>
<h2>17. Contact Information</h2>
<p>If you have any questions about these Terms of Use, please contact us:</p>
<ul>
<li><strong>Email:</strong> legal@luxuryhotel.com</li>
<li><strong>Phone:</strong> +1 (555) 123-4567</li>
<li><strong>Address:</strong> 123 Luxury Avenue, Premium City, PC 12345, United States</li>
</ul>
<p><em>Last Updated: {}</em></p>
""".format(now.strftime('%B %d, %Y')),
'meta_title': 'Terms of Use | Luxury Hotel & Resort - Terms and Conditions',
'meta_description': 'Read our terms and conditions for using our website and services. By using our services, you agree to these terms.',
'meta_keywords': 'terms of use, terms and conditions, user agreement, legal terms, hotel terms',
'og_title': 'Terms of Use - Luxury Hotel & Resort',
'og_description': 'Terms and conditions for using our website and services. Please read carefully before using our services.',
'og_image': 'https://images.unsplash.com/photo-1556761175-5973dc0f32e7?w=1200&h=630&fit=crop',
'canonical_url': 'https://luxuryhotel.com/terms',
'is_active': True,
'created_at': now,
'updated_at': now
}
def seed_terms_page(db: Session):
"""Seed terms of use page content into the database"""
try:
terms_data = get_terms_page_data()
# Check if terms page content already exists
existing_content = db.query(PageContent).filter(PageContent.page_type == PageType.TERMS).first()
if existing_content:
logger.info('Updating existing terms of use page content...')
for key, value in terms_data.items():
if key not in ['id', 'page_type', 'created_at']:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.now(timezone.utc)
else:
logger.info('Creating new terms of use page content...')
terms_page = PageContent(**terms_data)
db.add(terms_page)
db.commit()
logger.info('Terms of use page content seeded successfully!')
except Exception as e:
db.rollback()
logger.error(f'Error seeding terms of use page: {str(e)}', exc_info=True)
raise
def main():
db = SessionLocal()
try:
seed_terms_page(db)
except Exception as e:
logger.error(f'Failed to seed terms of use page: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,198 @@
"""
User and Role Seeder
Creates default roles and an admin user
"""
import sys
from pathlib import Path
from datetime import datetime, timezone
import bcrypt
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
# Import all models to ensure relationships are properly initialized
from src.models import *
from src.auth.models.role import Role
from src.auth.models.user import User
from src.shared.config.logging_config import get_logger
logger = get_logger(__name__)
def get_roles_data():
"""Generate default roles data"""
return [
{
'name': 'admin',
'description': 'Full system access with all administrative privileges'
},
{
'name': 'staff',
'description': 'Hotel staff with operational access'
},
{
'name': 'customer',
'description': 'Regular customer/guest user'
},
{
'name': 'accountant',
'description': 'Financial management and accounting access'
},
{
'name': 'housekeeping',
'description': 'Housekeeping and room management access'
}
]
def seed_roles(db: Session):
"""Seed roles into the database"""
try:
roles_data = get_roles_data()
created_count = 0
updated_count = 0
role_map = {}
for role_data in roles_data:
existing = db.query(Role).filter(Role.name == role_data['name']).first()
if existing:
logger.info(f'Role already exists: {role_data["name"]}')
role_map[role_data['name']] = existing
else:
logger.info(f'Creating role: {role_data["name"]}')
role = Role(**role_data)
db.add(role)
db.flush() # Flush to get the ID
role_map[role_data['name']] = role
created_count += 1
db.commit()
logger.info(f'Role seeding completed! Created: {created_count}, Existing: {len(roles_data) - created_count}')
return role_map
except Exception as e:
logger.error(f'Error seeding roles: {str(e)}', exc_info=True)
db.rollback()
raise
def seed_admin_user(db: Session, admin_role: Role, email: str = 'admin@hotel.com', password: str = 'admin123', full_name: str = 'Admin User'):
"""Seed admin user into the database"""
try:
# Check if admin user already exists
existing = db.query(User).filter(User.email == email).first()
if existing:
logger.info(f'Admin user already exists: {email}')
# Update role if needed
if existing.role_id != admin_role.id:
existing.role_id = admin_role.id
existing.updated_at = datetime.now(timezone.utc)
db.commit()
logger.info(f'Updated admin user role: {email}')
return existing
# Create new admin user
logger.info(f'Creating admin user: {email}')
password_bytes = password.encode('utf-8')
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
admin_user = User(
email=email,
password=hashed_password,
full_name=full_name,
role_id=admin_role.id,
is_active=True,
phone=None,
address=None
)
db.add(admin_user)
db.commit()
db.refresh(admin_user)
logger.info(f'Admin user created successfully: {email}')
return admin_user
except Exception as e:
logger.error(f'Error seeding admin user: {str(e)}', exc_info=True)
db.rollback()
raise
def seed_users_and_roles(db: Session, admin_email: str = 'admin@hotel.com', admin_password: str = 'admin123', admin_name: str = 'Admin User'):
"""Seed roles and admin user"""
try:
# First, seed roles
role_map = seed_roles(db)
# Get admin role
admin_role = role_map.get('admin')
if not admin_role:
raise ValueError('Admin role not found after seeding')
# Seed admin user
admin_user = seed_admin_user(db, admin_role, admin_email, admin_password, admin_name)
return role_map, admin_user
except Exception as e:
logger.error(f'Error seeding users and roles: {str(e)}', exc_info=True)
raise
def main():
"""Main function to run the seeder"""
import argparse
parser = argparse.ArgumentParser(description='Seed roles and admin user')
parser.add_argument(
'--email',
default='admin@hotel.com',
help='Admin user email (default: admin@hotel.com)'
)
parser.add_argument(
'--password',
default='admin123',
help='Admin user password (default: admin123)'
)
parser.add_argument(
'--name',
default='Admin User',
help='Admin user full name (default: Admin User)'
)
args = parser.parse_args()
logger.info('Starting user and role seeder...')
db = SessionLocal()
try:
role_map, admin_user = seed_users_and_roles(
db,
admin_email=args.email,
admin_password=args.password,
admin_name=args.name
)
logger.info(f'User and role seeder completed successfully!')
logger.info(f'Admin user: {admin_user.email} (ID: {admin_user.id})')
logger.info(f'Roles created: {len(role_map)}')
print(f'\n✓ Admin user created successfully!')
print(f' Email: {admin_user.email}')
print(f' Password: {args.password}')
print(f' Role: admin')
print(f'\n⚠️ IMPORTANT: Change the default password after first login!')
except Exception as e:
logger.error(f'Failed to seed users and roles: {str(e)}', exc_info=True)
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,57 +0,0 @@
#!/usr/bin/env python3
"""
Script to add the 'accountant' role to the database.
Run this script once to create the accountant role if it doesn't exist.
"""
import sys
from pathlib import Path
# Add the Backend directory to the path
backend_dir = Path(__file__).parent
sys.path.insert(0, str(backend_dir))
from src.shared.config.database import SessionLocal
from src.models.role import Role
def add_accountant_role():
"""Add the accountant role to the database if it doesn't exist."""
db = SessionLocal()
try:
# Check if accountant role already exists
existing_role = db.query(Role).filter(Role.name == 'accountant').first()
if existing_role:
print("✓ Accountant role already exists in the database.")
print(f" Role ID: {existing_role.id}")
print(f" Role Name: {existing_role.name}")
return
# Create the accountant role
accountant_role = Role(
name='accountant',
description='Accountant role with access to financial data, payments, and invoices'
)
db.add(accountant_role)
db.commit()
db.refresh(accountant_role)
print("✓ Accountant role created successfully!")
print(f" Role ID: {accountant_role.id}")
print(f" Role Name: {accountant_role.name}")
print(f" Description: {accountant_role.description}")
except Exception as e:
db.rollback()
print(f"✗ Error creating accountant role: {e}")
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
print("Adding accountant role to the database...")
print("-" * 50)
add_accountant_role()
print("-" * 50)
print("Done!")

View File

@@ -1,59 +0,0 @@
#!/usr/bin/env python3
"""
Script to add the 'housekeeping' role to the database.
Run this script once to create the housekeeping role if it doesn't exist.
"""
import sys
import os
from pathlib import Path
# Add the Backend directory to the path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from src.shared.config.database import SessionLocal
from src.models import Role # Use the models __init__ which handles all imports
def add_housekeeping_role():
"""Add the housekeeping role to the database if it doesn't exist."""
db = SessionLocal()
try:
# Check if housekeeping role already exists
existing_role = db.query(Role).filter(Role.name == 'housekeeping').first()
if existing_role:
print("✓ Housekeeping role already exists in the database.")
print(f" Role ID: {existing_role.id}")
print(f" Role Name: {existing_role.name}")
return
# Create the housekeeping role
housekeeping_role = Role(
name='housekeeping',
description='Housekeeping staff role with access to room cleaning tasks and status updates'
)
db.add(housekeeping_role)
db.commit()
db.refresh(housekeeping_role)
print("✓ Housekeeping role created successfully!")
print(f" Role ID: {housekeeping_role.id}")
print(f" Role Name: {housekeeping_role.name}")
print(f" Description: {housekeeping_role.description}")
except Exception as e:
db.rollback()
print(f"✗ Error creating housekeeping role: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
print("Adding housekeeping role to the database...")
print("=" * 60)
add_housekeeping_role()
print("=" * 60)
print("Done!")

View File

@@ -1,81 +0,0 @@
#!/usr/bin/env python3
"""
Script to add a housekeeping user to the database.
"""
import sys
import os
from pathlib import Path
# Add the Backend directory to the path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from src.shared.config.database import SessionLocal
from src.models import Role, User
import bcrypt
def add_housekeeping_user():
"""Add the housekeeping user to the database if it doesn't exist."""
db = SessionLocal()
try:
# Get housekeeping role
housekeeping_role = db.query(Role).filter(Role.name == 'housekeeping').first()
if not housekeeping_role:
print("✗ Housekeeping role not found! Please run add_housekeeping_role.py first.")
sys.exit(1)
# Check if user already exists
existing_user = db.query(User).filter(User.email == 'housekeeping@gnxsoft.com').first()
if existing_user:
print("✓ Housekeeping user already exists in the database.")
print(f" User ID: {existing_user.id}")
print(f" Email: {existing_user.email}")
print(f" Full Name: {existing_user.full_name}")
print(f" Role: {existing_user.role.name if existing_user.role else 'N/A'}")
return
# Hash password
password = 'P4eli240453.'
password_bytes = password.encode('utf-8')
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
# Create the housekeeping user
housekeeping_user = User(
email='housekeeping@gnxsoft.com',
password=hashed_password,
full_name='Housekeeping Staff',
role_id=housekeeping_role.id,
is_active=True,
currency='EUR'
)
db.add(housekeeping_user)
db.commit()
db.refresh(housekeeping_user)
print("✓ Housekeeping user created successfully!")
print(f" User ID: {housekeeping_user.id}")
print(f" Email: {housekeeping_user.email}")
print(f" Full Name: {housekeeping_user.full_name}")
print(f" Role: {housekeeping_role.name}")
print(f" Password: P4eli240453.")
except Exception as e:
db.rollback()
print(f"✗ Error creating housekeeping user: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
print("Adding housekeeping user to the database...")
print("=" * 60)
add_housekeeping_user()
print("=" * 60)
print("Done!")

View File

@@ -1,149 +0,0 @@
#!/usr/bin/env python3
"""
Script to assign test housekeeping tasks to the housekeeping user.
This creates sample tasks for testing the housekeeping dashboard.
"""
import sys
import os
from pathlib import Path
from datetime import datetime, timedelta
# Add the Backend directory to the path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
from src.shared.config.database import SessionLocal
from src.models import Role, User, Room
from src.hotel_services.models.housekeeping_task import HousekeepingTask, HousekeepingStatus, HousekeepingType
def assign_housekeeping_tasks():
"""Assign test housekeeping tasks to the housekeeping user."""
db = SessionLocal()
try:
# Get housekeeping user
housekeeping_user = db.query(User).join(Role).filter(
Role.name == 'housekeeping',
User.email == 'housekeeping@gnxsoft.com'
).first()
if not housekeeping_user:
print("✗ Housekeeping user not found! Please run add_housekeeping_user.py first.")
sys.exit(1)
print(f"✓ Found housekeeping user: {housekeeping_user.email} (ID: {housekeeping_user.id})")
# Get admin user for created_by
admin_role = db.query(Role).filter(Role.name == 'admin').first()
admin_user = db.query(User).filter(User.role_id == admin_role.id).first() if admin_role else None
# Get some rooms
rooms = db.query(Room).limit(5).all()
if not rooms:
print("✗ No rooms found in the database! Please seed rooms first.")
sys.exit(1)
print(f"✓ Found {len(rooms)} rooms")
# Default checklist items for different task types
checklists = {
'checkout': [
{'item': 'Bathroom cleaned', 'completed': False, 'notes': ''},
{'item': 'Beds made with fresh linens', 'completed': False, 'notes': ''},
{'item': 'Trash emptied', 'completed': False, 'notes': ''},
{'item': 'Towels replaced', 'completed': False, 'notes': ''},
{'item': 'Amenities restocked', 'completed': False, 'notes': ''},
{'item': 'Floor vacuumed and mopped', 'completed': False, 'notes': ''},
{'item': 'Surfaces dusted', 'completed': False, 'notes': ''},
{'item': 'Windows and mirrors cleaned', 'completed': False, 'notes': ''},
],
'stayover': [
{'item': 'Beds made', 'completed': False, 'notes': ''},
{'item': 'Trash emptied', 'completed': False, 'notes': ''},
{'item': 'Towels replaced', 'completed': False, 'notes': ''},
{'item': 'Bathroom cleaned', 'completed': False, 'notes': ''},
],
'vacant': [
{'item': 'Deep clean bathroom', 'completed': False, 'notes': ''},
{'item': 'Change linens', 'completed': False, 'notes': ''},
{'item': 'Vacuum and mop', 'completed': False, 'notes': ''},
{'item': 'Dust surfaces', 'completed': False, 'notes': ''},
{'item': 'Check amenities', 'completed': False, 'notes': ''},
],
'inspection': [
{'item': 'Check all amenities', 'completed': False, 'notes': ''},
{'item': 'Test electronics', 'completed': False, 'notes': ''},
{'item': 'Check for damages', 'completed': False, 'notes': ''},
{'item': 'Verify cleanliness', 'completed': False, 'notes': ''},
],
}
# Create tasks for today
today = datetime.utcnow().replace(hour=9, minute=0, second=0, microsecond=0)
task_types = ['checkout', 'stayover', 'vacant', 'inspection']
created_count = 0
skipped_count = 0
for i, room in enumerate(rooms):
# Cycle through task types
task_type = task_types[i % len(task_types)]
# Check if task already exists for this room today
existing_task = db.query(HousekeepingTask).filter(
HousekeepingTask.room_id == room.id,
HousekeepingTask.assigned_to == housekeeping_user.id,
HousekeepingTask.status == HousekeepingStatus.pending,
HousekeepingTask.scheduled_time >= today.replace(hour=0, minute=0),
HousekeepingTask.scheduled_time < today.replace(hour=23, minute=59, second=59)
).first()
if existing_task:
print(f" ⚠️ Task already exists for Room {room.room_number}, skipping...")
skipped_count += 1
continue
# Schedule tasks at different times throughout the day
scheduled_time = today + timedelta(hours=i)
task = HousekeepingTask(
room_id=room.id,
booking_id=None,
task_type=HousekeepingType(task_type),
status=HousekeepingStatus.pending,
scheduled_time=scheduled_time,
assigned_to=housekeeping_user.id,
created_by=admin_user.id if admin_user else housekeeping_user.id,
checklist_items=checklists.get(task_type, []),
notes=f'Test task for Room {room.room_number} - {task_type} cleaning',
estimated_duration_minutes=45 if task_type == 'checkout' else 30
)
db.add(task)
created_count += 1
print(f" ✓ Created {task_type} task for Room {room.room_number} (scheduled: {scheduled_time.strftime('%Y-%m-%d %H:%M')})")
db.commit()
print(f"\n✓ Tasks assigned successfully!")
print(f" - Created: {created_count} task(s)")
print(f" - Skipped: {skipped_count} task(s) (already exist)")
print(f" - Assigned to: {housekeeping_user.email}")
except Exception as e:
db.rollback()
print(f"✗ Error assigning housekeeping tasks: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
finally:
db.close()
if __name__ == '__main__':
print("Assigning test housekeeping tasks to housekeeping user...")
print("=" * 60)
assign_housekeeping_tasks()
print("=" * 60)
print("Done!")

View File

@@ -1,50 +0,0 @@
"""
Fix blog post published_at dates to be in the past
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.models.blog import BlogPost
from datetime import datetime, timedelta
def fix_blog_dates():
"""Update all blog posts to have published_at dates in the past"""
db: Session = SessionLocal()
try:
# Get all published posts
posts = db.query(BlogPost).filter(BlogPost.is_published == True).order_by(BlogPost.created_at.asc()).all()
if not posts:
print("No published posts found.")
return
# Set base date to 60 days ago
base_date = datetime.utcnow() - timedelta(days=60)
updated = 0
for i, post in enumerate(posts):
# Set each post's date going backwards from base_date
# Each post is 2 days earlier than the previous one
new_date = base_date - timedelta(days=i * 2)
post.published_at = new_date
updated += 1
db.commit()
print(f"Successfully updated {updated} blog posts with past published_at dates")
except Exception as e:
db.rollback()
print(f"Error fixing blog dates: {str(e)}")
raise
finally:
db.close()
if __name__ == "__main__":
print("Fixing blog post published_at dates...")
fix_blog_dates()
print("Done!")

View File

@@ -1,201 +0,0 @@
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
import json
sys.path.insert(0, str(Path(__file__).parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.models.page_content import PageContent, PageType
from datetime import datetime
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_about_page(db: Session):
print("=" * 80)
print("SEEDING ABOUT PAGE CONTENT")
print("=" * 80)
about_data = {
"title": "About Luxury Hotel",
"subtitle": "Where Excellence Meets Unforgettable Experiences",
"description": "Discover the story behind our commitment to luxury hospitality and exceptional service.",
"story_content": "For over three decades, Luxury Hotel has been a beacon of excellence in the hospitality industry. Founded with a vision to redefine luxury travel, we have grown from a single property to a collection of world-renowned destinations, each offering a unique blend of timeless elegance and modern sophistication. Our journey has been marked by countless awards, memorable moments, and the unwavering trust of our guests who return year after year.",
"mission": "To provide unparalleled luxury hospitality experiences that exceed expectations, creating lasting memories for our guests through exceptional service, attention to detail, and genuine care.",
"vision": "To be recognized as the world's premier luxury hotel brand, setting the standard for excellence in hospitality while maintaining our commitment to sustainability and community engagement.",
"about_hero_image": "https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1920&h=1080&fit=crop",
"values": json.dumps([
{
"icon": "Heart",
"title": "Passion",
"description": "We are passionate about hospitality and dedicated to creating exceptional experiences for every guest."
},
{
"icon": "Award",
"title": "Excellence",
"description": "We strive for excellence in every aspect of our service, from the smallest detail to the grandest gesture."
},
{
"icon": "Shield",
"title": "Integrity",
"description": "We conduct our business with honesty, transparency, and respect for our guests and community."
},
{
"icon": "Users",
"title": "Service",
"description": "Our guests are at the heart of everything we do. Your comfort and satisfaction are our top priorities."
}
]),
"features": json.dumps([
{
"icon": "Star",
"title": "Premium Accommodations",
"description": "Luxuriously appointed rooms and suites designed for ultimate comfort and relaxation."
},
{
"icon": "Clock",
"title": "24/7 Service",
"description": "Round-the-clock concierge and room service to attend to your needs at any time."
},
{
"icon": "Award",
"title": "Award-Winning",
"description": "Recognized for excellence in hospitality and guest satisfaction."
}
]),
"team": json.dumps([
{
"name": "Sarah Johnson",
"role": "General Manager",
"image": "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop",
"bio": "With over 15 years of experience in luxury hospitality, Sarah leads our team with passion and dedication.",
"social_links": {
"linkedin": "https://linkedin.com/in/sarahjohnson",
"twitter": "https://twitter.com/sarahjohnson"
}
},
{
"name": "Michael Chen",
"role": "Head Chef",
"image": "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=400&fit=crop",
"bio": "Award-winning chef with expertise in international cuisine, bringing world-class dining experiences to our guests.",
"social_links": {
"linkedin": "https://linkedin.com/in/michaelchen",
"twitter": "https://twitter.com/michaelchen"
}
},
{
"name": "Emily Rodriguez",
"role": "Guest Relations Manager",
"image": "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&h=400&fit=crop",
"bio": "Ensuring every guest feels valued and receives personalized attention throughout their stay.",
"social_links": {
"linkedin": "https://linkedin.com/in/emilyrodriguez"
}
}
]),
"timeline": json.dumps([
{
"year": "2010",
"title": "Grand Opening",
"description": "Luxury Hotel opened its doors, welcoming guests to a new standard of luxury hospitality.",
"image": "https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800&h=600&fit=crop"
},
{
"year": "2015",
"title": "First Award",
"description": "Received our first 'Best Luxury Hotel' award, recognizing our commitment to excellence.",
"image": "https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800&h=600&fit=crop"
},
{
"year": "2018",
"title": "Major Renovation",
"description": "Completed a comprehensive renovation, adding state-of-the-art facilities and expanding our capacity.",
"image": "https://images.unsplash.com/photo-1590490360182-c33d57733427?w=800&h=600&fit=crop"
},
{
"year": "2020",
"title": "Sustainability Initiative",
"description": "Launched our sustainability program, committing to eco-friendly practices and community engagement.",
"image": "https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=800&h=600&fit=crop"
},
{
"year": "2023",
"title": "International Recognition",
"description": "Achieved international recognition as one of the world's top luxury hotels.",
"image": "https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=800&h=600&fit=crop"
}
]),
"achievements": json.dumps([
{
"icon": "Award",
"title": "Best Luxury Hotel 2023",
"description": "Recognized as the best luxury hotel in the region for exceptional service and amenities.",
"year": "2023",
"image": "https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=400&h=300&fit=crop"
},
{
"icon": "Star",
"title": "5-Star Rating",
"description": "Maintained our prestigious 5-star rating for over a decade, a testament to our consistent excellence.",
"year": "2022",
"image": "https://images.unsplash.com/photo-1566073771259-6a8506099945?w=400&h=300&fit=crop"
},
{
"icon": "Award",
"title": "Sustainable Hotel of the Year",
"description": "Awarded for our commitment to environmental sustainability and green practices.",
"year": "2021",
"image": "https://images.unsplash.com/photo-1611892440504-42a792e24d32?w=400&h=300&fit=crop"
},
{
"icon": "Users",
"title": "Guest Satisfaction Excellence",
"description": "Achieved 98% guest satisfaction rate, the highest in our category.",
"year": "2023",
"image": "https://images.unsplash.com/photo-1590490360182-c33d57733427?w=400&h=300&fit=crop"
}
]),
"meta_title": "About Us - Luxury Hotel | Our Story, Mission & Vision",
"meta_description": "Learn about Luxury Hotel's commitment to excellence, our story, values, and the dedicated team that makes every stay unforgettable."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.ABOUT).first()
if existing:
for key, value in about_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing about page content")
else:
new_content = PageContent(
page_type=PageType.ABOUT,
**about_data
)
db.add(new_content)
print("✓ Created new about page content")
db.commit()
print("\n✅ About page content seeded successfully!")
print("=" * 80)
if __name__ == "__main__":
db = get_db()
try:
seed_about_page(db)
except Exception as e:
print(f"\n❌ Error: {e}")
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()

View File

@@ -1,154 +0,0 @@
#!/usr/bin/env python3
"""
Master script to seed all test data for the hotel booking system.
This script runs all necessary seed scripts in the correct order.
"""
import sys
import os
from pathlib import Path
# Add the Backend directory to the path
backend_dir = Path(__file__).parent.parent
sys.path.insert(0, str(backend_dir))
# Also add the seeds_data directory like other seed scripts
sys.path.insert(0, str(Path(__file__).parent))
import bcrypt
def ensure_housekeeping_role(db):
"""Ensure housekeeping role exists"""
from src.models.role import Role
housekeeping_role = db.query(Role).filter(Role.name == 'housekeeping').first()
if not housekeeping_role:
print('Creating housekeeping role...')
housekeeping_role = Role(name='housekeeping', description='Housekeeping staff role')
db.add(housekeeping_role)
db.commit()
db.refresh(housekeeping_role)
print('✓ Housekeeping role created')
return housekeeping_role
def ensure_housekeeping_users(db):
"""Ensure housekeeping users exist"""
from src.models.role import Role
from src.models.user import User
housekeeping_role = db.query(Role).filter(Role.name == 'housekeeping').first()
if not housekeeping_role:
print('❌ Housekeeping role not found!')
return
housekeeping_users = [
{
'email': 'housekeeping@gnxsoft.com',
'password': 'housekeeping123',
'full_name': 'Housekeeping Staff',
'phone': '+1 (555) 999-0000'
},
{
'email': 'housekeeping2@gnxsoft.com',
'password': 'housekeeping123',
'full_name': 'Housekeeping Staff 2',
'phone': '+1 (555) 999-0001'
}
]
for user_data in housekeeping_users:
existing = db.query(User).filter(User.email == user_data['email']).first()
if not existing:
password_bytes = user_data['password'].encode('utf-8')
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
user = User(
email=user_data['email'],
password=hashed_password,
full_name=user_data['full_name'],
phone=user_data['phone'],
role_id=housekeeping_role.id,
currency='EUR',
is_active=True
)
db.add(user)
print(f' ✓ Created housekeeping user: {user_data["email"]} - Password: {user_data["password"]}')
else:
print(f' ⚠️ Housekeeping user "{user_data["email"]}" already exists')
db.commit()
def main():
print('=' * 80)
print('SEEDING ALL TEST DATA FOR HOTEL BOOKING SYSTEM')
print('=' * 80)
print()
from src.shared.config.database import SessionLocal
db = SessionLocal()
try:
# Step 1: Ensure housekeeping role exists
print('Step 1: Ensuring housekeeping role exists...')
ensure_housekeeping_role(db)
print()
# Step 2: Ensure housekeeping users exist
print('Step 2: Ensuring housekeeping users exist...')
ensure_housekeeping_users(db)
print()
# Step 3: Import and run seed scripts
print('Step 3: Running seed scripts...')
print()
# Import seed modules
from seeds_data.seed_initial_data import seed_roles, seed_room_types, seed_admin_user
from seeds_data.seed_users import seed_users
from seeds_data.seed_rooms import seed_rooms
from seeds_data.seed_bookings import seed_bookings
# Run seed scripts
print('Running seed_initial_data...')
seed_initial_data.seed_roles(db)
seed_initial_data.seed_room_types(db)
seed_initial_data.seed_admin_user(db)
print()
print('Running seed_users...')
seed_users_module.seed_users(db)
print()
print('Running seed_rooms...')
seed_rooms_module.seed_rooms(db)
print()
print('Running seed_bookings...')
seed_bookings_module.seed_bookings(db)
print()
print('=' * 80)
print('✅ ALL TEST DATA SEEDED SUCCESSFULLY!')
print('=' * 80)
print()
print('📋 Test Accounts:')
print(' Staff: staff@gnxsoft.com / staff123')
print(' Housekeeping: housekeeping@gnxsoft.com / housekeeping123')
print(' Housekeeping 2: housekeeping2@gnxsoft.com / housekeeping123')
print(' Customer: customer@gnxsoft.com / customer123')
print()
print('🧪 To test notifications:')
print(' 1. Log in as staff (staff@gnxsoft.com)')
print(' 2. Go to Bookings and mark a checked_in booking as checked_out')
print(' 3. Log in as housekeeping user in another browser/tab')
print(' 4. You should receive a real-time notification about the room needing cleaning')
print('=' * 80)
except Exception as e:
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,70 +0,0 @@
import sys
import os
from datetime import datetime, timedelta
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.models.banner import Banner
from src.models.system_settings import SystemSettings
from src.models.user import User
def seed_banners(db: Session):
print('Seeding banners...')
admin_user = db.query(User).filter(User.email == 'admin@hotel.com').first()
admin_id = admin_user.id if admin_user else None
existing_banners = db.query(Banner).all()
if existing_banners:
for banner in existing_banners:
db.delete(banner)
db.commit()
print(f' ✓ Removed {len(existing_banners)} existing banner(s)')
banners_data = [{'title': 'Welcome to Unparalleled Luxury', 'description': 'Where timeless elegance meets modern sophistication. Experience the pinnacle of hospitality in our award-winning luxury hotel.', 'image_url': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1920', 'link_url': '/rooms', 'position': 'home', 'display_order': 1, 'is_active': True, 'start_date': datetime.utcnow() - timedelta(days=30), 'end_date': datetime.utcnow() + timedelta(days=365)}, {'title': 'Exclusive Presidential Suites', 'description': 'Indulge in our most opulent accommodations. Spacious suites with panoramic views, private terraces, and personalized butler service.', 'image_url': 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1920', 'link_url': '/rooms', 'position': 'home', 'display_order': 2, 'is_active': True, 'start_date': datetime.utcnow() - timedelta(days=7), 'end_date': datetime.utcnow() + timedelta(days=365)}, {'title': 'World-Class Spa & Wellness', 'description': 'Rejuvenate your mind, body, and soul. Our award-winning spa offers bespoke treatments using the finest luxury products.', 'image_url': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1920', 'link_url': '/services', 'position': 'home', 'display_order': 3, 'is_active': True, 'start_date': datetime.utcnow() - timedelta(days=1), 'end_date': datetime.utcnow() + timedelta(days=365)}, {'title': 'Michelin-Starred Culinary Excellence', 'description': 'Savor extraordinary flavors crafted by world-renowned chefs. Our fine dining restaurants offer an unforgettable gastronomic journey.', 'image_url': 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=1920', 'link_url': '/services', 'position': 'home', 'display_order': 4, 'is_active': True, 'start_date': datetime.utcnow(), 'end_date': datetime.utcnow() + timedelta(days=365)}, {'title': 'Private Yacht & Exclusive Experiences', 'description': 'Create unforgettable memories with our curated luxury experiences. From private yacht charters to exclusive cultural tours.', 'image_url': 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=1920', 'link_url': '/services', 'position': 'home', 'display_order': 5, 'is_active': True, 'start_date': datetime.utcnow() - timedelta(days=15), 'end_date': datetime.utcnow() + timedelta(days=365)}]
for banner_data in banners_data:
new_banner = Banner(**banner_data)
db.add(new_banner)
print(f' ✓ Created banner: {banner_data['title']}')
db.commit()
print('✓ Banners seeded successfully!\n')
def seed_company_info(db: Session):
print('Seeding company information...')
admin_user = db.query(User).filter(User.email == 'admin@hotel.com').first()
admin_id = admin_user.id if admin_user else None
company_settings = [{'key': 'company_name', 'value': 'Luxury Hotel', 'description': 'Company name displayed throughout the application'}, {'key': 'company_tagline', 'value': 'Experience Unparalleled Elegance', 'description': 'Company tagline or slogan'}, {'key': 'company_logo_url', 'value': '', 'description': 'URL to company logo image (upload via admin dashboard)'}, {'key': 'company_favicon_url', 'value': '', 'description': 'URL to company favicon image (upload via admin dashboard)'}, {'key': 'company_phone', 'value': '+1 (555) 123-4567', 'description': 'Company contact phone number'}, {'key': 'company_email', 'value': 'info@luxuryhotel.com', 'description': 'Company contact email address'}, {'key': 'company_address', 'value': '123 Luxury Avenue, Premium District, City 12345, Country', 'description': 'Company physical address'}, {'key': 'tax_rate', 'value': '10.0', 'description': 'Default tax rate percentage (e.g., 10.0 for 10%)'}, {'key': 'platform_currency', 'value': 'EUR', 'description': 'Platform-wide currency setting for displaying prices'}]
for setting_data in company_settings:
existing = db.query(SystemSettings).filter(SystemSettings.key == setting_data['key']).first()
if existing:
existing.value = setting_data['value']
existing.description = setting_data['description']
if admin_id:
existing.updated_by_id = admin_id
print(f' ✓ Updated setting: {setting_data['key']}')
else:
new_setting = SystemSettings(key=setting_data['key'], value=setting_data['value'], description=setting_data['description'], updated_by_id=admin_id)
db.add(new_setting)
print(f' ✓ Created setting: {setting_data['key']}')
db.commit()
print('✓ Company information seeded successfully!\n')
def main():
db: Session = SessionLocal()
try:
print('=' * 80)
print('SEEDING BANNERS AND COMPANY INFORMATION')
print('=' * 80)
print()
seed_banners(db)
seed_company_info(db)
print('=' * 80)
print('✓ All data seeded successfully!')
print('=' * 80)
except Exception as e:
db.rollback()
print(f'\n✗ Error seeding data: {e}')
import traceback
traceback.print_exc()
raise
finally:
db.close()
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -1,329 +0,0 @@
#!/usr/bin/env python3
"""
Script to seed sample bookings for testing check-in/check-out and housekeeping notifications.
"""
import sys
import os
from pathlib import Path
# Add both the seeds_data directory and the Backend directory to the path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from sqlalchemy import and_
from src.shared.config.database import SessionLocal
# Import all models needed for SQLAlchemy relationship setup
# Import base models first
from src.auth.models.role import Role
from src.auth.models.user import User
from src.rooms.models.room import Room, RoomStatus
from src.rooms.models.room_type import RoomType # For Room relationship
from src.rooms.models.rate_plan import RatePlan # For RoomType relationship
from src.rooms.models.room_maintenance import RoomMaintenance # For Room relationship
from src.rooms.models.room_inspection import RoomInspection # For Room relationship
from src.rooms.models.room_attribute import RoomAttribute # For Room relationship
from src.hotel_services.models.housekeeping_task import HousekeepingTask # For Room relationship
from src.bookings.models.booking import Booking, BookingStatus
from src.bookings.models.group_booking import GroupBooking # For Booking relationship
# Import all related models to satisfy SQLAlchemy relationships
# This is necessary because SQLAlchemy needs all related models loaded
try:
from src.auth.models.refresh_token import RefreshToken
from src.reviews.models.review import Review
from src.reviews.models.favorite import Favorite
from src.hotel_services.models.service import Service # For ServiceBooking relationship
from src.hotel_services.models.service_booking import ServiceBooking
from src.hotel_services.models.service_usage import ServiceUsage # For Booking relationship
from src.bookings.models.checkin_checkout import CheckInCheckOut
from src.payments.models.payment import Payment
from src.payments.models.invoice import Invoice
from src.ai.models.chat import Chat
from src.loyalty.models.user_loyalty import UserLoyalty
from src.loyalty.models.loyalty_tier import LoyaltyTier # For UserLoyalty relationship
from src.loyalty.models.loyalty_point_transaction import LoyaltyPointTransaction # For UserLoyalty relationship
from src.loyalty.models.referral import Referral
from src.loyalty.models.package import Package # For RoomType relationship
from src.guest_management.models.guest_preference import GuestPreference
from src.guest_management.models.guest_note import GuestNote
from src.guest_management.models.guest_communication import GuestCommunication
from src.guest_management.models.guest_tag import GuestTag, guest_tag_association
from src.guest_management.models.guest_segment import GuestSegment, guest_segment_association
# Import any other models that might be related
except ImportError:
pass # Some models might not exist, that's okay
from datetime import datetime, timedelta
import random
import secrets
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def generate_booking_number() -> str:
"""Generate a unique booking number"""
prefix = 'BK'
ts = int(datetime.utcnow().timestamp() * 1000)
rand = secrets.randbelow(9000) + 1000
return f'{prefix}-{ts}-{rand}'
def seed_bookings(db: Session):
print('=' * 80)
print('SEEDING SAMPLE BOOKINGS FOR TESTING')
print('=' * 80)
# Get roles
customer_role = db.query(Role).filter(Role.name == 'customer').first()
staff_role = db.query(Role).filter(Role.name == 'staff').first()
admin_role = db.query(Role).filter(Role.name == 'admin').first()
if not customer_role:
print(' ❌ Customer role not found! Please seed roles first.')
return
# Get customers
customers = db.query(User).filter(User.role_id == customer_role.id).all()
if not customers:
print(' ❌ No customer users found! Please seed users first.')
return
# Get available rooms
rooms = db.query(Room).all()
if not rooms:
print(' ❌ No rooms found! Please seed rooms first.')
return
print(f'\n✓ Found {len(customers)} customer(s) and {len(rooms)} room(s)')
# Delete existing bookings (optional - comment out if you want to keep existing bookings)
existing_bookings = db.query(Booking).all()
if existing_bookings:
print(f'\n🗑️ Deleting {len(existing_bookings)} existing booking(s)...')
booking_ids = [b.id for b in existing_bookings]
# Delete related records first to avoid foreign key constraints
try:
from src.guest_management.models.guest_complaint import GuestComplaint, ComplaintUpdate
complaints = db.query(GuestComplaint).filter(GuestComplaint.booking_id.in_(booking_ids)).all()
if complaints:
complaint_ids = [c.id for c in complaints]
# Delete complaint updates first
updates = db.query(ComplaintUpdate).filter(ComplaintUpdate.complaint_id.in_(complaint_ids)).all()
if updates:
for update in updates:
db.delete(update)
print(f' ✓ Deleted {len(updates)} complaint update(s)')
# Then delete complaints
for complaint in complaints:
db.delete(complaint)
print(f' ✓ Deleted {len(complaints)} guest complaint(s)')
except ImportError:
pass
for booking in existing_bookings:
db.delete(booking)
db.commit()
print(f'✓ Deleted {len(existing_bookings)} booking(s)')
# Create sample bookings with different statuses
now = datetime.utcnow()
bookings_data = []
# 1. Past bookings (checked out) - These should trigger cleaning notifications
print('\n📅 Creating past bookings (checked out)...')
for i in range(3):
room = random.choice(rooms)
customer = random.choice(customers)
# Check-out was 1-3 days ago
days_ago = random.randint(1, 3)
check_out_date = now - timedelta(days=days_ago)
check_in_date = check_out_date - timedelta(days=random.randint(1, 5))
# Calculate price
base_price = float(room.price) if room.price else 100.0
num_nights = (check_out_date - check_in_date).days
total_price = base_price * num_nights
booking = Booking(
booking_number=generate_booking_number(),
user_id=customer.id,
room_id=room.id,
check_in_date=check_in_date,
check_out_date=check_out_date,
num_guests=random.randint(1, min(room.capacity, 4)),
total_price=total_price,
status=BookingStatus.checked_out,
deposit_paid=True,
requires_deposit=False,
special_requests=f'Sample booking for testing - Checked out {days_ago} day(s) ago'
)
db.add(booking)
db.flush() # Flush to get booking ID
# Set room status to cleaning for checked out bookings
# Check if there's active maintenance first
try:
from src.rooms.models.room_maintenance import RoomMaintenance, MaintenanceStatus
active_maintenance = db.query(RoomMaintenance).filter(
and_(
RoomMaintenance.room_id == room.id,
RoomMaintenance.blocks_room == True,
RoomMaintenance.status.in_([MaintenanceStatus.scheduled, MaintenanceStatus.in_progress])
)
).first()
if not active_maintenance:
room.status = RoomStatus.cleaning
# Create housekeeping task for checkout cleaning
try:
from src.hotel_services.models.housekeeping_task import HousekeepingTask, HousekeepingStatus, HousekeepingType
checkout_checklist = [
{'item': 'Bathroom cleaned', 'completed': False, 'notes': ''},
{'item': 'Beds made with fresh linens', 'completed': False, 'notes': ''},
{'item': 'Trash emptied', 'completed': False, 'notes': ''},
{'item': 'Towels replaced', 'completed': False, 'notes': ''},
{'item': 'Amenities restocked', 'completed': False, 'notes': ''},
{'item': 'Floor vacuumed and mopped', 'completed': False, 'notes': ''},
{'item': 'Surfaces dusted', 'completed': False, 'notes': ''},
{'item': 'Windows and mirrors cleaned', 'completed': False, 'notes': ''},
]
housekeeping_task = HousekeepingTask(
room_id=room.id,
booking_id=booking.id,
task_type=HousekeepingType.checkout,
status=HousekeepingStatus.pending,
scheduled_time=datetime.utcnow(),
created_by=admin_role.id if admin_role else (staff_role.id if staff_role else None),
checklist_items=checkout_checklist,
notes=f'Auto-created on checkout for booking {booking.booking_number}',
estimated_duration_minutes=45
)
db.add(housekeeping_task)
except ImportError:
pass # If housekeeping models not available, skip task creation
except ImportError:
# If maintenance model not available, just set to cleaning
room.status = RoomStatus.cleaning
bookings_data.append({
'number': booking.booking_number,
'room': room.room_number,
'status': 'checked_out',
'check_out': check_out_date.strftime('%Y-%m-%d')
})
print(f' ✓ Created booking {booking.booking_number} - Room {room.room_number}, Checked out {days_ago} day(s) ago')
# 2. Current bookings (checked in) - Guests currently staying
print('\n📅 Creating current bookings (checked in)...')
for i in range(2):
room = random.choice(rooms)
customer = random.choice(customers)
# Checked in 1-3 days ago, checking out in 1-3 days
days_ago = random.randint(1, 3)
check_in_date = now - timedelta(days=days_ago)
check_out_date = now + timedelta(days=random.randint(1, 3))
base_price = float(room.price) if room.price else 100.0
num_nights = (check_out_date - check_in_date).days
total_price = base_price * num_nights
booking = Booking(
booking_number=generate_booking_number(),
user_id=customer.id,
room_id=room.id,
check_in_date=check_in_date,
check_out_date=check_out_date,
num_guests=random.randint(1, min(room.capacity, 4)),
total_price=total_price,
status=BookingStatus.checked_in,
deposit_paid=True,
requires_deposit=False,
special_requests=f'Sample booking for testing - Currently checked in'
)
db.add(booking)
db.flush() # Flush to get booking ID
# Set room status to occupied for checked in bookings
room.status = RoomStatus.occupied
bookings_data.append({
'number': booking.booking_number,
'room': room.room_number,
'status': 'checked_in',
'check_out': check_out_date.strftime('%Y-%m-%d')
})
print(f' ✓ Created booking {booking.booking_number} - Room {room.room_number}, Checked in {days_ago} day(s) ago')
# 3. Future bookings (confirmed) - Upcoming reservations
print('\n📅 Creating future bookings (confirmed)...')
for i in range(3):
room = random.choice(rooms)
customer = random.choice(customers)
# Check-in in 1-7 days, staying for 2-5 days
days_ahead = random.randint(1, 7)
check_in_date = now + timedelta(days=days_ahead)
check_out_date = check_in_date + timedelta(days=random.randint(2, 5))
base_price = float(room.price) if room.price else 100.0
num_nights = (check_out_date - check_in_date).days
total_price = base_price * num_nights
booking = Booking(
booking_number=generate_booking_number(),
user_id=customer.id,
room_id=room.id,
check_in_date=check_in_date,
check_out_date=check_out_date,
num_guests=random.randint(1, min(room.capacity, 4)),
total_price=total_price,
status=BookingStatus.confirmed,
deposit_paid=random.choice([True, False]),
requires_deposit=random.choice([True, False]),
special_requests=f'Sample booking for testing - Future reservation'
)
db.add(booking)
bookings_data.append({
'number': booking.booking_number,
'room': room.room_number,
'status': 'confirmed',
'check_in': check_in_date.strftime('%Y-%m-%d')
})
print(f' ✓ Created booking {booking.booking_number} - Room {room.room_number}, Check-in in {days_ahead} day(s)')
db.commit()
print(f'\n✅ Successfully created {len(bookings_data)} sample bookings!')
print(f'\n📊 Summary:')
checked_out = sum(1 for b in bookings_data if b['status'] == 'checked_out')
checked_in = sum(1 for b in bookings_data if b['status'] == 'checked_in')
confirmed = sum(1 for b in bookings_data if b['status'] == 'confirmed')
print(f' - Checked out: {checked_out} (rooms should be in cleaning status)')
print(f' - Checked in: {checked_in} (guests currently staying)')
print(f' - Confirmed: {confirmed} (upcoming reservations)')
print('\n💡 To test notifications:')
print(' 1. Log in as staff user (staff@gnxsoft.com / staff123)')
print(' 2. Go to Bookings and mark a checked_in booking as checked_out')
print(' 3. Log in as housekeeping user (housekeeping@gnxsoft.com / P4eli240453.)')
print(' 4. You should receive a notification about the room needing cleaning')
print('=' * 80)
def main():
db = get_db()
try:
seed_bookings(db)
except Exception as e:
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,392 +0,0 @@
import sys
import os
import json
from datetime import datetime, timedelta
# Add parent directory to path to import from src
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.content.models.page_content import PageContent, PageType
def seed_homepage_content(db: Session):
existing = db.query(PageContent).filter(PageContent.page_type == PageType.HOME).first()
luxury_features = [{'icon': 'Sparkles', 'title': 'Premium Amenities', 'description': 'World-class facilities designed for your comfort and relaxation'}, {'icon': 'Crown', 'title': 'Royal Service', 'description': 'Dedicated concierge service available 24/7 for all your needs'}, {'icon': 'Award', 'title': 'Award-Winning', 'description': 'Recognized for excellence in hospitality and guest satisfaction'}, {'icon': 'Shield', 'title': 'Secure & Private', 'description': 'Your privacy and security are our top priorities'}, {'icon': 'Heart', 'title': 'Personalized Care', 'description': 'Tailored experiences crafted just for you'}, {'icon': 'Gem', 'title': 'Luxury Design', 'description': 'Elegantly designed spaces with attention to every detail'}]
luxury_gallery = ['https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800', 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800', 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=800', 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=800', 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=800', 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=800']
luxury_testimonials = [{'name': 'Sarah Johnson', 'title': 'Business Executive', 'quote': 'An absolutely stunning experience. The attention to detail and level of service exceeded all expectations.', 'image': 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200'}, {'name': 'Michael Chen', 'title': 'Travel Enthusiast', 'quote': 'The epitome of luxury. Every moment was perfect, from check-in to check-out.', 'image': 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200'}, {'name': 'Emma Williams', 'title': 'Luxury Traveler', 'quote': 'This hotel redefines what luxury means. I will definitely return.', 'image': 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=200'}]
luxury_services = [
{
'icon': 'UtensilsCrossed',
'title': 'Fine Dining',
'description': 'Michelin-starred restaurants offering world-class cuisine',
'image': 'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=600',
'slug': 'fine-dining',
'category': 'Dining',
'content': '<p>Experience culinary excellence at our Michelin-starred restaurants. Our world-renowned chefs craft exquisite dishes using the finest ingredients sourced from around the globe. From intimate dining experiences to grand celebrations, we offer a variety of settings to suit every occasion.</p><p>Our restaurants feature seasonal menus that showcase the best of local and international cuisine, paired with an extensive wine collection curated by our master sommelier.</p>',
'sections': [],
'meta_title': 'Fine Dining Experience - Luxury Hotel',
'meta_description': 'Discover our Michelin-starred restaurants offering world-class cuisine in elegant settings.',
'meta_keywords': 'fine dining, michelin star, luxury restaurant, gourmet cuisine'
},
{
'icon': 'Wine',
'title': 'Premium Bar',
'description': 'Extensive wine collection and craft cocktails in elegant settings',
'image': 'https://images.unsplash.com/photo-1514362545857-3bc16c4c7d1b?w=600',
'slug': 'premium-bar',
'category': 'Dining',
'content': '<p>Unwind in sophistication at our premium bar, featuring an extensive collection of rare wines, vintage spirits, and expertly crafted cocktails. Our master mixologists create unique beverages tailored to your preferences.</p><p>The elegant ambiance, combined with live music on select evenings, creates the perfect setting for business meetings, romantic evenings, or casual gatherings with friends.</p>',
'sections': [],
'meta_title': 'Premium Bar & Lounge - Luxury Hotel',
'meta_description': 'Enjoy an extensive wine collection and craft cocktails in our elegant bar and lounge.',
'meta_keywords': 'premium bar, wine collection, craft cocktails, luxury lounge'
},
{
'icon': 'Dumbbell',
'title': 'Spa & Wellness',
'description': 'Rejuvenating spa treatments and state-of-the-art fitness center',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=600',
'slug': 'spa-wellness',
'category': 'Wellness',
'content': '<p>Escape to tranquility at our world-class spa and wellness center. Indulge in a range of rejuvenating treatments designed to restore balance and vitality. Our expert therapists use premium products and ancient techniques to provide an unparalleled wellness experience.</p><p>Our state-of-the-art fitness center is equipped with the latest equipment and offers personal training sessions, yoga classes, and wellness programs tailored to your needs.</p>',
'sections': [],
'meta_title': 'Spa & Wellness Center - Luxury Hotel',
'meta_description': 'Rejuvenate with our spa treatments and state-of-the-art fitness facilities.',
'meta_keywords': 'spa, wellness, fitness center, massage, luxury spa'
},
{
'icon': 'Car',
'title': 'Concierge Services',
'description': 'Personalized assistance for all your travel and entertainment needs',
'image': 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=600',
'slug': 'concierge-services',
'category': 'Services',
'content': '<p>Our dedicated concierge team is available 24/7 to ensure your stay is nothing short of extraordinary. From restaurant reservations and event tickets to private tours and transportation arrangements, we handle every detail with precision and care.</p><p>Whether you need assistance with business arrangements, special celebrations, or unique local experiences, our concierge team has the expertise and connections to make it happen.</p>',
'sections': [],
'meta_title': 'Concierge Services - Luxury Hotel',
'meta_description': 'Personalized assistance for all your travel and entertainment needs, available 24/7.',
'meta_keywords': 'concierge, personal assistant, travel services, luxury service'
}
]
luxury_experiences = [{'icon': 'Sunset', 'title': 'Sunset Rooftop', 'description': 'Breathtaking views and exclusive rooftop experiences', 'image': 'https://images.unsplash.com/photo-1514933651103-005eec06c04b?w=600'}, {'icon': 'Ship', 'title': 'Yacht Excursions', 'description': 'Private yacht charters for unforgettable sea adventures', 'image': 'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=600'}, {'icon': 'Music', 'title': 'Live Entertainment', 'description': 'World-class performances and exclusive events', 'image': 'https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?w=600'}, {'icon': 'Palette', 'title': 'Art & Culture', 'description': 'Curated art collections and cultural experiences', 'image': 'https://images.unsplash.com/photo-1578301978018-3005759f48f7?w=600'}]
awards = [{'icon': 'Trophy', 'title': 'Best Luxury Hotel 2024', 'description': 'Awarded by International Luxury Travel Association', 'image': 'https://images.unsplash.com/photo-1579783902614-a3fb3927b6a5?w=400', 'year': '2024'}, {'icon': 'Star', 'title': '5-Star Excellence', 'description': 'Consistently rated 5 stars by leading travel publications', 'image': 'https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=400', 'year': '2023'}, {'icon': 'Award', 'title': 'Sustainable Luxury', 'description': 'Recognized for environmental responsibility and sustainability', 'image': 'https://images.unsplash.com/photo-1473341304170-971dccb5ac1e?w=400', 'year': '2024'}]
partners = [{'name': 'Luxury Travel Group', 'logo': 'https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200', 'link': '#'}, {'name': 'Premium Airlines', 'logo': 'https://images.unsplash.com/photo-1436491865332-7a61a109cc05?w=200', 'link': '#'}, {'name': 'Exclusive Events', 'logo': 'https://images.unsplash.com/photo-1511578314322-379afb476865?w=200', 'link': '#'}, {'name': 'Fine Dining Network', 'logo': 'https://images.unsplash.com/photo-1555396273-367ea4eb4db5?w=200', 'link': '#'}]
stats = [{'icon': 'Users', 'number': '50,000+', 'label': 'Happy Guests'}, {'icon': 'Award', 'number': '25+', 'label': 'Awards Won'}, {'icon': 'Star', 'number': '4.9', 'label': 'Average Rating'}, {'icon': 'Globe', 'number': '100+', 'label': 'Countries Served'}]
amenities = [{'icon': 'Wifi', 'title': 'High-Speed WiFi', 'description': 'Complimentary high-speed internet throughout the property', 'image': ''}, {'icon': 'Coffee', 'title': '24/7 Room Service', 'description': 'Round-the-clock dining and beverage service', 'image': ''}, {'icon': 'Car', 'title': 'Valet Parking', 'description': 'Complimentary valet parking for all guests', 'image': ''}, {'icon': 'Plane', 'title': 'Airport Transfer', 'description': 'Luxury airport transfer service available', 'image': ''}]
features = [{'icon': 'Shield', 'title': 'Secure & Safe', 'description': '24/7 security and state-of-the-art safety systems'}, {'icon': 'Wifi', 'title': 'Free WiFi', 'description': 'High-speed internet access throughout the property'}, {'icon': 'Coffee', 'title': 'Room Service', 'description': '24/7 room service available for your convenience'}, {'icon': 'Car', 'title': 'Parking', 'description': 'Complimentary valet parking for all guests'}, {'icon': 'UtensilsCrossed', 'title': 'Fine Dining', 'description': 'World-class restaurants and dining experiences'}, {'icon': 'Dumbbell', 'title': 'Fitness Center', 'description': 'State-of-the-art fitness facilities'}]
testimonials = [{'name': 'Robert Martinez', 'role': 'CEO, Tech Corp', 'image': 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=200', 'rating': 5, 'comment': 'Exceptional service and attention to detail. The staff went above and beyond to make our stay memorable.'}, {'name': 'Lisa Anderson', 'role': 'Travel Blogger', 'image': 'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?w=200', 'rating': 5, 'comment': "The most luxurious hotel experience I've ever had. Every detail was perfect."}, {'name': 'David Thompson', 'role': 'Investment Banker', 'image': 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=200', 'rating': 5, 'comment': 'Outstanding facilities and impeccable service. Highly recommend for business travelers.'}]
gallery_images = ['https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=800', 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=800', 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=800', 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=800', 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=800', 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=800']
# Enterprise homepage fields
hero_video_url = 'https://videos.unsplash.com/video-1564501049412-61c2a3083791'
hero_video_poster = 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200'
features_section_title = 'Why Choose Us'
features_section_subtitle = 'Discover what makes us the perfect choice for your stay'
stats_section_title = 'Our Achievements'
stats_section_subtitle = 'Numbers that speak for themselves'
rooms_section_title = 'Luxurious Rooms & Suites'
rooms_section_subtitle = 'Experience comfort and elegance in every room'
rooms_section_button_text = 'View All Rooms'
rooms_section_button_link = '/rooms'
rooms_section_enabled = True
services_section_button_text = 'Explore All Services'
services_section_button_link = '/services'
services_section_limit = 4
# Sections enabled configuration
sections_enabled = {
'features': True,
'luxury': True,
'gallery': True,
'testimonials': True,
'stats': True,
'amenities': True,
'about_preview': True,
'services': True,
'experiences': True,
'awards': True,
'cta': True,
'partners': True,
'rooms': True,
'newsletter': True,
'trust_badges': True,
'promotions': True,
'blog': True
}
# Newsletter section
newsletter_section_title = 'Stay Connected'
newsletter_section_subtitle = 'Subscribe to our newsletter for exclusive offers and updates'
newsletter_placeholder = 'Enter your email address'
newsletter_button_text = 'Subscribe'
newsletter_enabled = True
# Trust badges
trust_badges = [
{
'name': '5-Star Rating',
'logo': 'https://images.unsplash.com/photo-1579783902614-a3fb3927b6a5?w=200',
'description': 'Awarded 5 stars by leading travel organizations',
'link': '#'
},
{
'name': 'TripAdvisor Excellence',
'logo': 'https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=200',
'description': 'Certificate of Excellence winner',
'link': '#'
},
{
'name': 'Green Certified',
'logo': 'https://images.unsplash.com/photo-1473341304170-971dccb5ac1e?w=200',
'description': 'Eco-friendly and sustainable practices',
'link': '#'
},
{
'name': 'Luxury Collection',
'logo': 'https://images.unsplash.com/photo-1599305445671-ac291c95aaa9?w=200',
'description': 'Member of the world\'s finest luxury hotels',
'link': '#'
}
]
trust_badges_section_title = 'Trusted & Recognized'
trust_badges_section_subtitle = 'Awards and certifications that validate our commitment to excellence'
trust_badges_enabled = True
# Promotions - Mix of valid and expired for testing
# Calculate dates relative to current date
today = datetime.now()
next_month = today + timedelta(days=30)
next_3_months = today + timedelta(days=90)
next_6_months = today + timedelta(days=180)
expired_1_month_ago = today - timedelta(days=30)
expired_3_months_ago = today - timedelta(days=90)
promotions = [
{
'title': 'Early Bird Special',
'description': 'Book 30 days in advance and save 20% on your stay. Perfect for planning ahead!',
'image': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=600',
'discount': '20% OFF',
'valid_until': next_3_months.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Book Now',
'code': 'EARLYBIRD20'
},
{
'title': 'Weekend Getaway',
'description': 'Perfect weekend escape with complimentary breakfast and spa access. Relax and unwind!',
'image': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=600',
'discount': '30% OFF',
'valid_until': next_month.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'View Offer',
'code': 'WEEKEND30'
},
{
'title': 'Luxury Suite Package',
'description': 'Experience our premium suites with exclusive amenities, fine dining, and concierge service',
'image': 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=600',
'discount': 'Save $200',
'valid_until': next_6_months.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Explore Suites',
'code': 'LUXURY200'
},
{
'title': 'Honeymoon Special',
'description': 'Romantic getaway with champagne, flowers, special amenities, and complimentary room upgrade',
'image': 'https://images.unsplash.com/photo-1596394516093-501ba68a0ba6?w=600',
'discount': '25% OFF',
'valid_until': next_3_months.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Book Package',
'code': 'HONEYMOON25'
},
{
'title': 'Family Fun Package',
'description': 'Perfect for families! Includes family room, kids activities, and complimentary meals for children under 12',
'image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=600',
'discount': '15% OFF',
'valid_until': next_6_months.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Book Now',
'code': 'FAMILY15'
},
{
'title': 'Business Traveler',
'description': 'Extended stay discounts for business travelers. Includes high-speed WiFi, workspace, and airport transfer',
'image': 'https://images.unsplash.com/photo-1551882547-ff40c63fe5fa?w=600',
'discount': '10% OFF',
'valid_until': next_3_months.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Learn More',
'code': 'BUSINESS10'
},
# Expired promotions for testing display logic
{
'title': 'Summer Special',
'description': 'Enjoy 25% off on all room bookings this summer. Limited time offer!',
'image': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=600',
'discount': '25% OFF',
'valid_until': expired_3_months_ago.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'Book Now',
'code': 'SUMMER25'
},
{
'title': 'New Year Celebration',
'description': 'Ring in the new year with our special celebration package. Includes party access and premium amenities',
'image': 'https://images.unsplash.com/photo-1590490360182-c33d57733427?w=600',
'discount': '35% OFF',
'valid_until': expired_1_month_ago.strftime('%Y-%m-%d'),
'link': '/rooms',
'button_text': 'View Offer',
'code': 'NEWYEAR35'
}
]
promotions_section_title = 'Special Offers'
promotions_section_subtitle = 'Exclusive deals and packages designed just for you'
promotions_enabled = True
# Blog section
blog_section_title = 'Latest News & Updates'
blog_section_subtitle = 'Stay informed about our latest news, events, and travel tips'
blog_posts_limit = 3
blog_enabled = True
homepage_data = {
'page_type': PageType.HOME,
'title': 'Luxury Hotel - Experience Unparalleled Elegance',
'subtitle': 'Where timeless luxury meets modern sophistication',
'description': 'Discover a world of refined elegance and exceptional service',
'hero_title': 'Welcome to Luxury',
'hero_subtitle': 'Experience the pinnacle of hospitality',
'hero_image': 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?w=1200',
'hero_video_url': hero_video_url,
'hero_video_poster': hero_video_poster,
'features': json.dumps(features),
'features_section_title': features_section_title,
'features_section_subtitle': features_section_subtitle,
'luxury_section_title': 'Experience Unparalleled Luxury',
'luxury_section_subtitle': 'Where elegance meets comfort in every detail',
'luxury_section_image': 'https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=1200',
'luxury_features': json.dumps(luxury_features),
'luxury_gallery_section_title': 'Our Luxury Gallery',
'luxury_gallery_section_subtitle': 'A glimpse into our world of elegance',
'luxury_gallery': json.dumps(luxury_gallery),
'luxury_testimonials_section_title': 'What Our Guests Say',
'luxury_testimonials_section_subtitle': 'Testimonials from our valued guests',
'luxury_testimonials': json.dumps(luxury_testimonials),
'luxury_services_section_title': 'Premium Services',
'luxury_services_section_subtitle': 'Indulge in our world-class amenities',
'luxury_services': json.dumps(luxury_services),
'services_section_button_text': services_section_button_text,
'services_section_button_link': services_section_button_link,
'services_section_limit': services_section_limit,
'luxury_experiences_section_title': 'Exclusive Experiences',
'luxury_experiences_section_subtitle': 'Create unforgettable memories',
'luxury_experiences': json.dumps(luxury_experiences),
'awards_section_title': 'Awards & Recognition',
'awards_section_subtitle': 'Recognized for excellence worldwide',
'awards': json.dumps(awards),
'partners_section_title': 'Our Partners',
'partners_section_subtitle': 'Trusted by leading brands',
'partners': json.dumps(partners),
'amenities_section_title': 'Premium Amenities',
'amenities_section_subtitle': 'Everything you need for a perfect stay',
'amenities': json.dumps(amenities),
'testimonials_section_title': 'Guest Reviews',
'testimonials_section_subtitle': 'Hear from our satisfied guests',
'testimonials': json.dumps(testimonials),
'gallery_section_title': 'Photo Gallery',
'gallery_section_subtitle': 'Explore our beautiful spaces',
'gallery_images': json.dumps(gallery_images),
'about_preview_title': 'About Our Luxury Hotel',
'about_preview_subtitle': 'A legacy of excellence',
'about_preview_content': 'Discover a world of refined elegance and exceptional service. Our hotel combines timeless luxury with modern amenities to create an unforgettable experience. With over 50,000 satisfied guests and numerous awards, we continue to set the standard for luxury hospitality.',
'about_preview_image': 'https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=800',
'stats': json.dumps(stats),
'stats_section_title': stats_section_title,
'stats_section_subtitle': stats_section_subtitle,
'rooms_section_title': rooms_section_title,
'rooms_section_subtitle': rooms_section_subtitle,
'rooms_section_button_text': rooms_section_button_text,
'rooms_section_button_link': rooms_section_button_link,
'rooms_section_enabled': rooms_section_enabled,
'sections_enabled': json.dumps(sections_enabled),
'newsletter_section_title': newsletter_section_title,
'newsletter_section_subtitle': newsletter_section_subtitle,
'newsletter_placeholder': newsletter_placeholder,
'newsletter_button_text': newsletter_button_text,
'newsletter_enabled': newsletter_enabled,
'trust_badges_section_title': trust_badges_section_title,
'trust_badges_section_subtitle': trust_badges_section_subtitle,
'trust_badges': json.dumps(trust_badges),
'trust_badges_enabled': trust_badges_enabled,
'promotions_section_title': promotions_section_title,
'promotions_section_subtitle': promotions_section_subtitle,
'promotions': json.dumps(promotions),
'promotions_enabled': promotions_enabled,
'blog_section_title': blog_section_title,
'blog_section_subtitle': blog_section_subtitle,
'blog_posts_limit': blog_posts_limit,
'blog_enabled': blog_enabled,
'cta_title': 'Ready to Experience Luxury?',
'cta_subtitle': 'Book your stay today and discover the difference',
'cta_button_text': 'Book Now',
'cta_button_link': '/rooms',
'cta_image': 'https://images.unsplash.com/photo-1566073771259-6a8506099945?w=1200',
'is_active': True
}
if existing:
for key, value in homepage_data.items():
if key != 'page_type':
setattr(existing, key, value)
print('✓ Updated existing homepage content')
else:
new_content = PageContent(**homepage_data)
db.add(new_content)
print('✓ Created new homepage content')
db.commit()
def seed_footer_content(db: Session):
existing = db.query(PageContent).filter(PageContent.page_type == PageType.FOOTER).first()
contact_info = {'phone': '+1 (555) 123-4567', 'email': 'info@luxuryhotel.com', 'address': '123 Luxury Avenue, Premium District, City 12345'}
social_links = {'facebook': 'https://facebook.com/luxuryhotel', 'twitter': 'https://twitter.com/luxuryhotel', 'instagram': 'https://instagram.com/luxuryhotel', 'linkedin': 'https://linkedin.com/company/luxuryhotel', 'youtube': 'https://youtube.com/luxuryhotel'}
footer_links = {'quick_links': [{'label': 'Home', 'url': '/'}, {'label': 'Rooms & Suites', 'url': '/rooms'}, {'label': 'About Us', 'url': '/about'}, {'label': 'Contact', 'url': '/contact'}, {'label': 'Gallery', 'url': '/gallery'}], 'support_links': [{'label': 'FAQ', 'url': '/faq'}, {'label': 'Privacy Policy', 'url': '/privacy'}, {'label': 'Terms of Service', 'url': '/terms'}, {'label': 'Cancellation Policy', 'url': '/cancellation'}, {'label': 'Accessibility', 'url': '/accessibility'}]}
badges = [{'text': '5-Star Rated', 'icon': 'Star'}, {'text': 'Award Winning', 'icon': 'Award'}, {'text': 'Eco Certified', 'icon': 'Leaf'}, {'text': 'Luxury Collection', 'icon': 'Crown'}]
footer_data = {'page_type': PageType.FOOTER, 'title': 'Luxury Hotel', 'subtitle': 'Experience Unparalleled Elegance', 'description': 'Your gateway to luxury hospitality and exceptional service', 'contact_info': json.dumps(contact_info), 'social_links': json.dumps(social_links), 'footer_links': json.dumps(footer_links), 'badges': json.dumps(badges), 'copyright_text': '© {YEAR} Luxury Hotel. All rights reserved.', 'is_active': True}
if existing:
for key, value in footer_data.items():
if key != 'page_type':
setattr(existing, key, value)
print('✓ Updated existing footer content')
else:
new_content = PageContent(**footer_data)
db.add(new_content)
print('✓ Created new footer content')
db.commit()
def main():
db: Session = SessionLocal()
try:
print('=' * 80)
print('SEEDING HOMEPAGE AND FOOTER CONTENT')
print('=' * 80)
print()
print('Seeding homepage content...')
seed_homepage_content(db)
print('\nSeeding footer content...')
seed_footer_content(db)
print('\n' + '=' * 80)
print('✓ All content seeded successfully!')
print('=' * 80)
except Exception as e:
db.rollback()
print(f'\n✗ Error seeding content: {e}')
import traceback
traceback.print_exc()
raise
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,163 +0,0 @@
import sys
import os
from pathlib import Path
# Add both the seeds_data directory and the Backend directory to the path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
# Import all models needed for SQLAlchemy relationship setup
from src.auth.models.role import Role
from src.auth.models.user import User
from src.rooms.models.room_type import RoomType
from src.rooms.models.room import Room
from src.rooms.models.rate_plan import RatePlan # For RoomType relationship
from src.bookings.models.booking import Booking # For Room relationship
import bcrypt
from datetime import datetime
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_roles(db: Session):
print('=' * 80)
print('SEEDING ROLES')
print('=' * 80)
roles_data = [
{'name': 'admin', 'description': 'Administrator with full access'},
{'name': 'staff', 'description': 'Staff member with limited admin access'},
{'name': 'customer', 'description': 'Regular customer'},
{'name': 'accountant', 'description': 'Accountant role with access to financial data, payments, and invoices'},
{'name': 'housekeeping', 'description': 'Housekeeping staff role with access to room cleaning tasks and status updates'}
]
for role_data in roles_data:
existing = db.query(Role).filter(Role.name == role_data['name']).first()
if existing:
print(f' ✓ Role "{role_data["name"]}" already exists')
else:
role = Role(**role_data)
db.add(role)
print(f' ✓ Created role: {role_data["name"]}')
db.commit()
print('✓ Roles seeded successfully!\n')
def seed_room_types(db: Session):
print('=' * 80)
print('SEEDING ROOM TYPES')
print('=' * 80)
room_types_data = [
{
'name': 'Standard Room',
'description': 'Comfortable and well-appointed standard accommodation',
'base_price': 150.00,
'capacity': 2,
'amenities': ['Free WiFi', 'Air Conditioning', 'TV', 'Minibar', 'Safe']
},
{
'name': 'Superior Room',
'description': 'Spacious room with enhanced amenities and better views',
'base_price': 200.00,
'capacity': 2,
'amenities': ['Free WiFi', 'Air Conditioning', 'Smart TV', 'Minibar', 'Safe', 'Coffee Maker']
},
{
'name': 'Deluxe Room',
'description': 'Luxurious room with premium furnishings and amenities',
'base_price': 280.00,
'capacity': 3,
'amenities': ['Free WiFi', 'Air Conditioning', 'Smart TV', 'Netflix', 'Minibar', 'Safe', 'Coffee Maker', 'Premium Toiletries']
},
{
'name': 'Executive Suite',
'description': 'Elegant suite with separate living area and premium amenities',
'base_price': 400.00,
'capacity': 4,
'amenities': ['Free WiFi', 'Air Conditioning', 'Smart TV', 'Netflix', 'Minibar', 'Safe', 'Espresso Machine', 'Premium Toiletries', 'Bathrobes', 'Work Desk']
},
{
'name': 'Presidential Suite',
'description': 'The ultimate in luxury with expansive space and exclusive amenities',
'base_price': 800.00,
'capacity': 6,
'amenities': ['Free WiFi', 'Air Conditioning', 'Smart TV', 'Netflix', 'Private Bar', 'Jacuzzi', 'Butler Service', 'Premium Toiletries', 'Bathrobes', 'Private Terrace']
}
]
import json
for rt_data in room_types_data:
existing = db.query(RoomType).filter(RoomType.name == rt_data['name']).first()
if existing:
print(f' ✓ Room type "{rt_data["name"]}" already exists')
else:
amenities = rt_data.pop('amenities')
room_type = RoomType(**rt_data, amenities=json.dumps(amenities))
db.add(room_type)
print(f' ✓ Created room type: {rt_data["name"]} (€{rt_data["base_price"]:.2f}/night)')
db.commit()
print('✓ Room types seeded successfully!\n')
def seed_admin_user(db: Session):
print('=' * 80)
print('SEEDING ADMIN USER')
print('=' * 80)
admin_role = db.query(Role).filter(Role.name == 'admin').first()
if not admin_role:
print(' ❌ Admin role not found! Please seed roles first.')
return
admin_email = 'admin@hotel.com'
existing_admin = db.query(User).filter(User.email == admin_email).first()
if existing_admin:
print(f' ✓ Admin user "{admin_email}" already exists')
else:
password = 'admin123' # Default password - should be changed in production
password_bytes = password.encode('utf-8')
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
admin_user = User(
email=admin_email,
password=hashed_password,
full_name='Administrator',
role_id=admin_role.id,
is_active=True,
currency='EUR'
)
db.add(admin_user)
db.commit()
print(f' ✓ Created admin user: {admin_email}')
print(f' ⚠️ Default password: admin123 (please change in production!)')
print('✓ Admin user seeded successfully!\n')
def main():
db = get_db()
try:
seed_roles(db)
seed_room_types(db)
seed_admin_user(db)
print('=' * 80)
print('✅ Initial data seeding completed successfully!')
print('=' * 80)
except Exception as e:
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,303 +0,0 @@
import sys
import os
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.models.loyalty_reward import LoyaltyReward, RewardType
from src.models.loyalty_tier import LoyaltyTier, TierLevel
from datetime import datetime, timedelta
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_loyalty_rewards(db: Session):
print('=' * 80)
print('SEEDING LOYALTY REWARDS')
print('=' * 80)
# Get tier IDs for tier-specific rewards
bronze_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.bronze).first()
silver_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.silver).first()
gold_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.gold).first()
platinum_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.platinum).first()
# Create default tiers if they don't exist
if not bronze_tier:
from src.services.loyalty_service import LoyaltyService
LoyaltyService.create_default_tiers(db)
db.refresh()
bronze_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.bronze).first()
silver_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.silver).first()
gold_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.gold).first()
platinum_tier = db.query(LoyaltyTier).filter(LoyaltyTier.level == TierLevel.platinum).first()
# Sample rewards data
rewards_data = [
# Discount Rewards (Available to all tiers)
{
'name': '5% Booking Discount',
'description': 'Get 5% off your next booking. Valid for bookings over $100.',
'reward_type': RewardType.discount,
'points_cost': 5000,
'discount_percentage': 5.0,
'max_discount_amount': 50.0,
'min_booking_amount': 100.0,
'applicable_tier_id': None, # Available to all tiers
'stock_quantity': None, # Unlimited
'icon': '🎫',
'is_active': True
},
{
'name': '10% Booking Discount',
'description': 'Get 10% off your next booking. Valid for bookings over $200.',
'reward_type': RewardType.discount,
'points_cost': 10000,
'discount_percentage': 10.0,
'max_discount_amount': 100.0,
'min_booking_amount': 200.0,
'applicable_tier_id': silver_tier.id if silver_tier else None,
'stock_quantity': None,
'icon': '🎫',
'is_active': True
},
{
'name': '15% Premium Discount',
'description': 'Get 15% off your next booking. Maximum discount $150. Valid for bookings over $300.',
'reward_type': RewardType.discount,
'points_cost': 15000,
'discount_percentage': 15.0,
'max_discount_amount': 150.0,
'min_booking_amount': 300.0,
'applicable_tier_id': gold_tier.id if gold_tier else None,
'stock_quantity': None,
'icon': '💎',
'is_active': True
},
{
'name': '20% VIP Discount',
'description': 'Exclusive 20% discount for Platinum members. Maximum discount $200. Valid for bookings over $500.',
'reward_type': RewardType.discount,
'points_cost': 25000,
'discount_percentage': 20.0,
'max_discount_amount': 200.0,
'min_booking_amount': 500.0,
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
'stock_quantity': None,
'icon': '👑',
'is_active': True
},
# Room Upgrade Rewards
{
'name': 'Complimentary Room Upgrade',
'description': 'Upgrade to the next room category at no extra cost. Subject to availability at check-in.',
'reward_type': RewardType.room_upgrade,
'points_cost': 20000,
'applicable_tier_id': silver_tier.id if silver_tier else None,
'stock_quantity': 50, # Limited stock
'icon': '🛏️',
'is_active': True
},
{
'name': 'Premium Suite Upgrade',
'description': 'Upgrade to a premium suite or executive room. Subject to availability.',
'reward_type': RewardType.room_upgrade,
'points_cost': 35000,
'applicable_tier_id': gold_tier.id if gold_tier else None,
'stock_quantity': 30,
'icon': '🏨',
'is_active': True
},
{
'name': 'Luxury Suite Upgrade',
'description': 'Upgrade to our most luxurious suite category. Ultimate comfort guaranteed. Subject to availability.',
'reward_type': RewardType.room_upgrade,
'points_cost': 50000,
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
'stock_quantity': 20,
'icon': '',
'is_active': True
},
# Amenity Rewards
{
'name': 'Welcome Amenity Package',
'description': 'Complimentary welcome basket with fruits, chocolates, and wine upon arrival.',
'reward_type': RewardType.amenity,
'points_cost': 3000,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '🍾',
'is_active': True
},
{
'name': 'Breakfast for Two',
'description': 'Complimentary breakfast buffet for two guests during your stay.',
'reward_type': RewardType.amenity,
'points_cost': 8000,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '🍳',
'is_active': True
},
{
'name': 'Spa Treatment Voucher',
'description': 'One complimentary spa treatment of your choice (60 minutes). Valid for 90 days.',
'reward_type': RewardType.amenity,
'points_cost': 12000,
'applicable_tier_id': silver_tier.id if silver_tier else None,
'stock_quantity': 40,
'icon': '💆',
'is_active': True,
'valid_until': datetime.utcnow() + timedelta(days=90)
},
{
'name': 'Romantic Dinner Package',
'description': 'Private romantic dinner for two with wine pairing at our fine dining restaurant.',
'reward_type': RewardType.amenity,
'points_cost': 18000,
'applicable_tier_id': gold_tier.id if gold_tier else None,
'stock_quantity': 25,
'icon': '🍽️',
'is_active': True
},
{
'name': 'VIP Airport Transfer',
'description': 'Complimentary luxury airport transfer (one-way) in premium vehicle.',
'reward_type': RewardType.amenity,
'points_cost': 15000,
'applicable_tier_id': platinum_tier.id if platinum_tier else None,
'stock_quantity': 20,
'icon': '🚗',
'is_active': True
},
# Voucher Rewards
{
'name': '$50 Hotel Credit',
'description': 'Redeem for $50 credit towards room service, spa, or dining at the hotel. Valid for 6 months.',
'reward_type': RewardType.voucher,
'points_cost': 10000,
'discount_amount': 50.0,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '💳',
'is_active': True,
'valid_until': datetime.utcnow() + timedelta(days=180)
},
{
'name': '$100 Hotel Credit',
'description': 'Redeem for $100 credit towards any hotel service. Valid for 6 months.',
'reward_type': RewardType.voucher,
'points_cost': 20000,
'discount_amount': 100.0,
'applicable_tier_id': silver_tier.id if silver_tier else None,
'stock_quantity': None,
'icon': '💵',
'is_active': True,
'valid_until': datetime.utcnow() + timedelta(days=180)
},
{
'name': '$200 Premium Credit',
'description': 'Redeem for $200 credit towards premium services. Perfect for special occasions. Valid for 1 year.',
'reward_type': RewardType.voucher,
'points_cost': 40000,
'discount_amount': 200.0,
'applicable_tier_id': gold_tier.id if gold_tier else None,
'stock_quantity': None,
'icon': '💰',
'is_active': True,
'valid_until': datetime.utcnow() + timedelta(days=365)
},
# Cashback Rewards
{
'name': 'Early Check-in Benefit',
'description': 'Guaranteed early check-in (12:00 PM) at no extra charge. Subject to availability.',
'reward_type': RewardType.amenity,
'points_cost': 2000,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '',
'is_active': True
},
{
'name': 'Late Check-out Benefit',
'description': 'Extended check-out until 2:00 PM at no extra charge. Subject to availability.',
'reward_type': RewardType.amenity,
'points_cost': 2000,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '🕐',
'is_active': True
},
{
'name': 'Free Night Stay',
'description': 'One complimentary night stay in a standard room. Valid for bookings of 2+ nights.',
'reward_type': RewardType.voucher,
'points_cost': 30000,
'applicable_tier_id': gold_tier.id if gold_tier else None,
'stock_quantity': 15,
'icon': '🌙',
'is_active': True,
'valid_until': datetime.utcnow() + timedelta(days=180)
},
{
'name': 'Complimentary Room Service',
'description': '$75 credit for room service orders. Valid for one stay.',
'reward_type': RewardType.amenity,
'points_cost': 6000,
'discount_amount': 75.0,
'applicable_tier_id': None,
'stock_quantity': None,
'icon': '🍽️',
'is_active': True
},
]
created_count = 0
skipped_count = 0
for reward_data in rewards_data:
# Check if reward already exists by name
existing = db.query(LoyaltyReward).filter(LoyaltyReward.name == reward_data['name']).first()
if existing:
print(f' ⚠️ Reward "{reward_data["name"]}" already exists, skipping...')
skipped_count += 1
continue
# Create reward object
reward = LoyaltyReward(**reward_data)
db.add(reward)
print(f' ✓ Created reward: {reward_data["name"]} ({reward_data["points_cost"]:,} points)')
created_count += 1
db.commit()
print('\n✓ Loyalty rewards seeded successfully!')
print(f' - Created: {created_count} reward(s)')
print(f' - Skipped: {skipped_count} reward(s) (already exist)')
print('=' * 80)
def main():
db = get_db()
try:
seed_loyalty_rewards(db)
print('\n✅ Loyalty rewards seeding completed successfully!')
print('=' * 80)
except Exception as e:
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,42 +0,0 @@
import sys
import os
import json
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal, engine
from src.models.page_content import PageContent
from src.models.user import User
def seed_luxury_content():
db: Session = SessionLocal()
try:
existing = db.query(PageContent).filter(PageContent.page_type == 'home').first()
luxury_features = [{'icon': 'Sparkles', 'title': 'Premium Amenities', 'description': 'World-class facilities designed for your comfort and relaxation'}, {'icon': 'Crown', 'title': 'Royal Service', 'description': 'Dedicated concierge service available 24/7 for all your needs'}, {'icon': 'Award', 'title': 'Award-Winning', 'description': 'Recognized for excellence in hospitality and guest satisfaction'}, {'icon': 'Shield', 'title': 'Secure & Private', 'description': 'Your privacy and security are our top priorities'}, {'icon': 'Heart', 'title': 'Personalized Care', 'description': 'Tailored experiences crafted just for you'}, {'icon': 'Gem', 'title': 'Luxury Design', 'description': 'Elegantly designed spaces with attention to every detail'}]
luxury_testimonials = [{'name': 'Sarah Johnson', 'title': 'Business Executive', 'quote': 'An absolutely stunning experience. The attention to detail and level of service exceeded all expectations.', 'image': ''}, {'name': 'Michael Chen', 'title': 'Travel Enthusiast', 'quote': 'The epitome of luxury. Every moment was perfect, from check-in to check-out.', 'image': ''}, {'name': 'Emma Williams', 'title': 'Luxury Traveler', 'quote': 'This hotel redefines what luxury means. I will definitely return.', 'image': ''}]
if existing:
existing.luxury_section_title = 'Experience Unparalleled Luxury'
existing.luxury_section_subtitle = 'Where elegance meets comfort in every detail'
existing.luxury_section_image = None
existing.luxury_features = json.dumps(luxury_features)
existing.luxury_gallery = json.dumps([])
existing.luxury_testimonials = json.dumps(luxury_testimonials)
existing.about_preview_title = 'About Our Luxury Hotel'
existing.about_preview_content = 'Discover a world of refined elegance and exceptional service. Our hotel combines timeless luxury with modern amenities to create an unforgettable experience.'
existing.about_preview_image = None
print('✓ Updated existing home page content with luxury sections')
else:
new_content = PageContent(page_type='home', luxury_section_title='Experience Unparalleled Luxury', luxury_section_subtitle='Where elegance meets comfort in every detail', luxury_section_image=None, luxury_features=json.dumps(luxury_features), luxury_gallery=json.dumps([]), luxury_testimonials=json.dumps(luxury_testimonials), about_preview_title='About Our Luxury Hotel', about_preview_content='Discover a world of refined elegance and exceptional service. Our hotel combines timeless luxury with modern amenities to create an unforgettable experience.', about_preview_image=None, is_active=True)
db.add(new_content)
print('✓ Created new home page content with luxury sections')
db.commit()
print('✓ Luxury content seeded successfully!')
except Exception as e:
db.rollback()
print(f'✗ Error seeding luxury content: {e}')
raise
finally:
db.close()
if __name__ == '__main__':
print('Seeding luxury content...')
seed_luxury_content()
print('Done!')

View File

@@ -1,517 +0,0 @@
#!/usr/bin/env python3
import sys
import os
from pathlib import Path
import json
sys.path.insert(0, str(Path(__file__).parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.models.page_content import PageContent, PageType
from datetime import datetime
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_privacy_policy(db: Session):
print("=" * 80)
print("SEEDING PRIVACY POLICY PAGE CONTENT")
print("=" * 80)
privacy_content = """
<h2>Introduction</h2>
<p>At our hotel, we are committed to protecting your privacy and ensuring the security of your personal information. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you visit our website or use our services.</p>
<h2>Information We Collect</h2>
<p>We collect information that you provide directly to us, including:</p>
<ul>
<li>Personal identification information (name, email address, phone number)</li>
<li>Payment information (credit card details, billing address)</li>
<li>Booking and reservation details</li>
<li>Preferences and special requests</li>
</ul>
<h2>How We Use Your Information</h2>
<p>We use the information we collect to:</p>
<ul>
<li>Process and manage your bookings and reservations</li>
<li>Communicate with you about your bookings and our services</li>
<li>Improve our services and customer experience</li>
<li>Send you promotional materials (with your consent)</li>
<li>Comply with legal obligations</li>
</ul>
<h2>Data Security</h2>
<p>We implement appropriate technical and organizational measures to protect your personal information against unauthorized access, alteration, disclosure, or destruction.</p>
<h2>Your Rights</h2>
<p>You have the right to:</p>
<ul>
<li>Access your personal information</li>
<li>Correct inaccurate information</li>
<li>Request deletion of your information</li>
<li>Object to processing of your information</li>
<li>Data portability</li>
</ul>
<h2>Contact Us</h2>
<p>If you have any questions about this Privacy Policy, please contact us at privacy@hotel.com.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
privacy_data = {
"title": "Privacy Policy",
"subtitle": "Your privacy is important to us",
"description": "Learn how we collect, use, and protect your personal information.",
"content": privacy_content,
"meta_title": "Privacy Policy - Luxury Hotel | Data Protection & Privacy",
"meta_description": "Read our privacy policy to understand how we collect, use, and protect your personal information when you use our hotel booking services."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.PRIVACY).first()
if existing:
for key, value in privacy_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing privacy policy page content")
else:
new_content = PageContent(
page_type=PageType.PRIVACY,
**privacy_data
)
db.add(new_content)
print("✓ Created new privacy policy page content")
db.commit()
print("\n✅ Privacy policy page content seeded successfully!")
print("=" * 80)
def seed_terms_conditions(db: Session):
print("=" * 80)
print("SEEDING TERMS & CONDITIONS PAGE CONTENT")
print("=" * 80)
terms_content = """
<h2>Agreement to Terms</h2>
<p>By accessing and using our hotel's website and services, you accept and agree to be bound by the terms and provision of this agreement.</p>
<h2>Booking Terms</h2>
<p>When making a reservation with us, you agree to:</p>
<ul>
<li>Provide accurate and complete information</li>
<li>Be responsible for all charges incurred during your stay</li>
<li>Comply with hotel policies and regulations</li>
<li>Respect other guests and hotel property</li>
</ul>
<h2>Payment Terms</h2>
<p>Payment terms include:</p>
<ul>
<li>A 20% deposit is required to secure your booking</li>
<li>The remaining balance is due on arrival at the hotel</li>
<li>All prices are subject to applicable taxes and fees</li>
<li>Payment methods accepted: credit cards, debit cards, and cash</li>
</ul>
<h2>Cancellation Policy</h2>
<p>Our cancellation policy is as follows:</p>
<ul>
<li>Cancellations made 48 hours or more before check-in: Full refund of deposit</li>
<li>Cancellations made less than 48 hours before check-in: Deposit is non-refundable</li>
<li>No-shows: Full booking amount is charged</li>
</ul>
<h2>Check-in and Check-out</h2>
<p>Standard check-in time is 3:00 PM and check-out time is 11:00 AM. Early check-in and late check-out may be available upon request and subject to availability.</p>
<h2>Guest Responsibilities</h2>
<p>Guests are responsible for:</p>
<ul>
<li>Any damage to hotel property</li>
<li>Compliance with all hotel rules and regulations</li>
<li>Respecting quiet hours and other guests</li>
<li>Proper use of hotel facilities</li>
</ul>
<h2>Limitation of Liability</h2>
<p>The hotel shall not be liable for any loss, damage, or injury to persons or property during your stay, except where such loss, damage, or injury is caused by our negligence.</p>
<h2>Modifications to Terms</h2>
<p>We reserve the right to modify these terms at any time. Changes will be effective immediately upon posting on our website.</p>
<h2>Contact Information</h2>
<p>For questions about these terms, please contact us at legal@hotel.com.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
terms_data = {
"title": "Terms & Conditions",
"subtitle": "Please read these terms carefully",
"description": "Terms and conditions governing your use of our hotel booking services.",
"content": terms_content,
"meta_title": "Terms & Conditions - Luxury Hotel | Booking Terms & Policies",
"meta_description": "Read our terms and conditions to understand the rules and policies governing your bookings and stay at our luxury hotel."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.TERMS).first()
if existing:
for key, value in terms_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing terms & conditions page content")
else:
new_content = PageContent(
page_type=PageType.TERMS,
**terms_data
)
db.add(new_content)
print("✓ Created new terms & conditions page content")
db.commit()
print("\n✅ Terms & conditions page content seeded successfully!")
print("=" * 80)
def seed_refunds_policy(db: Session):
print("=" * 80)
print("SEEDING REFUNDS POLICY PAGE CONTENT")
print("=" * 80)
refunds_content = """
<h2>Refund Policy Overview</h2>
<p>At our hotel, we understand that plans can change. This policy outlines our refund procedures and timelines for various scenarios.</p>
<h2>Booking Cancellations</h2>
<p>Refunds for cancelled bookings are processed as follows:</p>
<ul>
<li><strong>More than 48 hours before check-in:</strong> Full refund of the 20% deposit</li>
<li><strong>48 hours or less before check-in:</strong> Deposit is non-refundable</li>
<li><strong>No-show:</strong> No refund will be issued</li>
</ul>
<h2>Early Check-out</h2>
<p>If you check out earlier than your reserved departure date:</p>
<ul>
<li>You will be charged for the nights you stayed</li>
<li>The remaining 80% balance for unused nights will be refunded</li>
<li>Refunds are processed within 5-7 business days</li>
</ul>
<h2>Service Issues</h2>
<p>If you experience service issues during your stay:</p>
<ul>
<li>Please report the issue immediately to our front desk</li>
<li>We will make every effort to resolve the issue promptly</li>
<li>If the issue cannot be resolved, partial or full refunds may be considered on a case-by-case basis</li>
</ul>
<h2>Refund Processing Time</h2>
<p>Refunds are typically processed within:</p>
<ul>
<li><strong>Credit/Debit Cards:</strong> 5-7 business days</li>
<li><strong>Bank Transfers:</strong> 7-10 business days</li>
<li><strong>Cash Payments:</strong> Refunds will be processed via bank transfer</li>
</ul>
<h2>Refund Method</h2>
<p>Refunds will be issued to the original payment method used for the booking. If the original payment method is no longer available, please contact us to arrange an alternative refund method.</p>
<h2>Non-Refundable Bookings</h2>
<p>Some special offers or promotional rates may be non-refundable. This will be clearly stated at the time of booking.</p>
<h2>Force Majeure</h2>
<p>In cases of force majeure (natural disasters, pandemics, government restrictions, etc.), we will work with you to reschedule your booking or provide appropriate refunds based on the circumstances.</p>
<h2>Dispute Resolution</h2>
<p>If you have concerns about a refund decision, please contact our customer service team. We are committed to resolving all disputes fairly and promptly.</p>
<h2>Contact Us</h2>
<p>For refund inquiries, please contact us at refunds@hotel.com or call our customer service line.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
refunds_data = {
"title": "Refunds Policy",
"subtitle": "Our commitment to fair refunds",
"description": "Learn about our refund policies and procedures for bookings and cancellations.",
"content": refunds_content,
"meta_title": "Refunds Policy - Luxury Hotel | Cancellation & Refund Terms",
"meta_description": "Understand our refund policy, including cancellation terms, processing times, and how to request refunds for your hotel bookings."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.REFUNDS).first()
if existing:
for key, value in refunds_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing refunds policy page content")
else:
new_content = PageContent(
page_type=PageType.REFUNDS,
**refunds_data
)
db.add(new_content)
print("✓ Created new refunds policy page content")
db.commit()
print("\n✅ Refunds policy page content seeded successfully!")
print("=" * 80)
def seed_cancellation_policy(db: Session):
print("=" * 80)
print("SEEDING CANCELLATION POLICY PAGE CONTENT")
print("=" * 80)
cancellation_content = """
<h2>Cancellation Policy Overview</h2>
<p>We understand that plans can change. This policy outlines our cancellation procedures and fees.</p>
<h2>Standard Cancellation Terms</h2>
<p>For standard bookings, the following cancellation terms apply:</p>
<ul>
<li><strong>More than 48 hours before check-in:</strong> Full refund of the 20% deposit</li>
<li><strong>48 hours or less before check-in:</strong> Deposit is non-refundable</li>
<li><strong>No-show:</strong> No refund will be issued</li>
</ul>
<h2>Special Rate Bookings</h2>
<p>Some special rates or promotional offers may have different cancellation terms. Please review your booking confirmation for specific details.</p>
<h2>How to Cancel</h2>
<p>To cancel your booking:</p>
<ul>
<li>Log into your account and visit "My Bookings"</li>
<li>Select the booking you wish to cancel</li>
<li>Click "Cancel Booking" and confirm</li>
<li>Or contact us directly via phone or email</li>
</ul>
<h2>Refund Processing</h2>
<p>Refunds will be processed to the original payment method within 5-10 business days after cancellation confirmation.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
cancellation_data = {
"title": "Cancellation Policy",
"subtitle": "Flexible cancellation options for your peace of mind",
"description": "Learn about our cancellation policy, fees, and refund procedures.",
"content": cancellation_content,
"meta_title": "Cancellation Policy - Luxury Hotel | Booking Cancellation Terms",
"meta_description": "Review our cancellation policy to understand cancellation fees, refund procedures, and terms for modifying or canceling your hotel booking."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.CANCELLATION).first()
if existing:
for key, value in cancellation_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing cancellation policy page content")
else:
new_content = PageContent(
page_type=PageType.CANCELLATION,
**cancellation_data
)
db.add(new_content)
print("✓ Created new cancellation policy page content")
db.commit()
print("\n✅ Cancellation policy page content seeded successfully!")
print("=" * 80)
def seed_accessibility_policy(db: Session):
print("=" * 80)
print("SEEDING ACCESSIBILITY PAGE CONTENT")
print("=" * 80)
accessibility_content = """
<h2>Our Commitment to Accessibility</h2>
<p>We are committed to ensuring that our hotel and website are accessible to all guests, regardless of ability. We strive to provide an inclusive experience for everyone.</p>
<h2>Hotel Accessibility Features</h2>
<p>Our hotel offers the following accessibility features:</p>
<ul>
<li>Wheelchair-accessible rooms with roll-in showers</li>
<li>Accessible parking spaces</li>
<li>Elevator access to all floors</li>
<li>Ramp access to main entrances</li>
<li>Accessible public restrooms</li>
<li>Visual and auditory emergency alarms</li>
<li>Service animal friendly</li>
</ul>
<h2>Website Accessibility</h2>
<p>We are continuously working to improve the accessibility of our website. Our website includes:</p>
<ul>
<li>Keyboard navigation support</li>
<li>Screen reader compatibility</li>
<li>Alt text for images</li>
<li>High contrast options</li>
<li>Resizable text</li>
</ul>
<h2>Requesting Accommodations</h2>
<p>If you require specific accommodations during your stay, please contact us at least 48 hours before your arrival. We will do our best to accommodate your needs.</p>
<h2>Feedback</h2>
<p>We welcome feedback on how we can improve accessibility. Please contact us with your suggestions or concerns.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
accessibility_data = {
"title": "Accessibility",
"subtitle": "Committed to providing an inclusive experience for all guests",
"description": "Learn about our accessibility features and accommodations.",
"content": accessibility_content,
"meta_title": "Accessibility - Luxury Hotel | Accessible Accommodations",
"meta_description": "Discover our commitment to accessibility, including accessible rooms, facilities, and website features for guests with disabilities."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.ACCESSIBILITY).first()
if existing:
for key, value in accessibility_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing accessibility page content")
else:
new_content = PageContent(
page_type=PageType.ACCESSIBILITY,
**accessibility_data
)
db.add(new_content)
print("✓ Created new accessibility page content")
db.commit()
print("\n✅ Accessibility page content seeded successfully!")
print("=" * 80)
def seed_faq_page(db: Session):
print("=" * 80)
print("SEEDING FAQ PAGE CONTENT")
print("=" * 80)
faq_content = """
<h2>Frequently Asked Questions</h2>
<p>Find answers to common questions about our hotel, bookings, and services.</p>
<h2>Booking & Reservations</h2>
<h3>How do I make a reservation?</h3>
<p>You can make a reservation online through our website, by phone, or by email. Simply select your dates, choose your room, and complete the booking process.</p>
<h3>What is the deposit requirement?</h3>
<p>A 20% deposit is required to secure your booking. The remaining balance is due upon arrival at the hotel.</p>
<h3>Can I modify my booking?</h3>
<p>Yes, you can modify your booking by logging into your account and visiting "My Bookings", or by contacting us directly. Changes are subject to availability and may incur fees.</p>
<h2>Check-in & Check-out</h2>
<h3>What are your check-in and check-out times?</h3>
<p>Check-in is from 3:00 PM, and check-out is by 11:00 AM. Early check-in and late check-out may be available upon request, subject to availability.</p>
<h3>Do you offer early check-in or late check-out?</h3>
<p>Early check-in and late check-out are available upon request, subject to availability. Additional fees may apply.</p>
<h2>Payment & Cancellation</h2>
<h3>What payment methods do you accept?</h3>
<p>We accept major credit cards, debit cards, and bank transfers. Payment can be made online or at the hotel.</p>
<h3>What is your cancellation policy?</h3>
<p>For cancellations made more than 48 hours before check-in, the deposit is fully refundable. Cancellations made 48 hours or less before check-in are non-refundable. Please see our Cancellation Policy page for full details.</p>
<h2>Hotel Services & Amenities</h2>
<h3>What amenities are included?</h3>
<p>Our hotel offers complimentary Wi-Fi, parking, fitness center access, and more. Please check the room details for specific amenities.</p>
<h3>Do you have parking available?</h3>
<p>Yes, we offer complimentary parking for all guests. Valet parking is also available for an additional fee.</p>
<h3>Is Wi-Fi available?</h3>
<p>Yes, complimentary high-speed Wi-Fi is available throughout the hotel.</p>
<h2>Special Requests</h2>
<h3>Can I request a specific room?</h3>
<p>Yes, you can make special requests when booking. We will do our best to accommodate your preferences, subject to availability.</p>
<h3>Do you accommodate dietary restrictions?</h3>
<p>Yes, please inform us of any dietary restrictions or allergies when making your reservation, and we will do our best to accommodate your needs.</p>
<h2>Contact & Support</h2>
<h3>How can I contact the hotel?</h3>
<p>You can contact us by phone, email, or through our website's contact form. Our team is available 24/7 to assist you.</p>
<p><strong>Last updated:</strong> """ + datetime.now().strftime("%B %d, %Y") + """</p>
"""
faq_data = {
"title": "Frequently Asked Questions",
"subtitle": "Find answers to common questions",
"description": "Get answers to frequently asked questions about bookings, services, and policies.",
"content": faq_content,
"meta_title": "FAQ - Luxury Hotel | Frequently Asked Questions",
"meta_description": "Find answers to common questions about hotel bookings, check-in, payment, cancellation, amenities, and more."
}
existing = db.query(PageContent).filter(PageContent.page_type == PageType.FAQ).first()
if existing:
for key, value in faq_data.items():
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
print("✓ Updated existing FAQ page content")
else:
new_content = PageContent(
page_type=PageType.FAQ,
**faq_data
)
db.add(new_content)
print("✓ Created new FAQ page content")
db.commit()
print("\n✅ FAQ page content seeded successfully!")
print("=" * 80)
def main():
db = get_db()
try:
print("\n")
seed_privacy_policy(db)
print("\n")
seed_terms_conditions(db)
print("\n")
seed_refunds_policy(db)
print("\n")
seed_cancellation_policy(db)
print("\n")
seed_accessibility_policy(db)
print("\n")
seed_faq_page(db)
print("\n")
print("=" * 80)
print("✅ ALL POLICY PAGES SEEDED SUCCESSFULLY!")
print("=" * 80)
print("\n")
except Exception as e:
print(f"\n❌ Error: {e}")
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == "__main__":
main()

View File

@@ -1,157 +0,0 @@
import sys
import os
from datetime import datetime, timedelta
# Add parent directory to path to import from src
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.loyalty.models.promotion import Promotion, DiscountType
def seed_promotions(db: Session):
"""Seed promotions that match the homepage promotion codes"""
# Calculate dates relative to current UTC date
# Use UTC consistently to match validation logic
now = datetime.utcnow()
# Start date: Start of today (00:00:00) to ensure promotion is immediately active
start_date = datetime(now.year, now.month, now.day, 0, 0, 0)
# End dates: future dates at end of day (23:59:59)
next_month_date = now + timedelta(days=30)
next_month = datetime(next_month_date.year, next_month_date.month, next_month_date.day, 23, 59, 59)
next_3_months_date = now + timedelta(days=90)
next_3_months = datetime(next_3_months_date.year, next_3_months_date.month, next_3_months_date.day, 23, 59, 59)
next_6_months_date = now + timedelta(days=180)
next_6_months = datetime(next_6_months_date.year, next_6_months_date.month, next_6_months_date.day, 23, 59, 59)
promotions_data = [
{
'code': 'EARLYBIRD20',
'name': 'Early Bird Special',
'description': 'Book 30 days in advance and save 20% on your stay. Perfect for planning ahead!',
'discount_type': DiscountType.percentage,
'discount_value': 20.00,
'start_date': start_date,
'end_date': next_3_months,
'is_active': True,
'min_booking_amount': None,
'max_discount_amount': None,
'usage_limit': None,
},
{
'code': 'WEEKEND30',
'name': 'Weekend Getaway',
'description': 'Perfect weekend escape with complimentary breakfast and spa access. Relax and unwind!',
'discount_type': DiscountType.percentage,
'discount_value': 30.00,
'start_date': start_date,
'end_date': next_month,
'is_active': True,
'min_booking_amount': None,
'max_discount_amount': None,
'usage_limit': None,
},
{
'code': 'LUXURY200',
'name': 'Luxury Suite Package',
'description': 'Experience our premium suites with exclusive amenities, fine dining, and concierge service',
'discount_type': DiscountType.fixed_amount,
'discount_value': 200.00,
'start_date': start_date,
'end_date': next_6_months,
'is_active': True,
'min_booking_amount': None, # No minimum for now
'max_discount_amount': None,
'usage_limit': None,
},
{
'code': 'HONEYMOON25',
'name': 'Honeymoon Special',
'description': 'Romantic getaway with champagne, flowers, special amenities, and complimentary room upgrade',
'discount_type': DiscountType.percentage,
'discount_value': 25.00,
'start_date': start_date,
'end_date': next_3_months,
'is_active': True,
'min_booking_amount': None,
'max_discount_amount': None,
'usage_limit': None,
},
{
'code': 'FAMILY15',
'name': 'Family Fun Package',
'description': 'Perfect for families! Includes family room, kids activities, and complimentary meals for children under 12',
'discount_type': DiscountType.percentage,
'discount_value': 15.00,
'start_date': start_date,
'end_date': next_6_months,
'is_active': True,
'min_booking_amount': None,
'max_discount_amount': None,
'usage_limit': None,
},
{
'code': 'BUSINESS10',
'name': 'Business Traveler',
'description': 'Extended stay discounts for business travelers. Includes high-speed WiFi, workspace, and airport transfer',
'discount_type': DiscountType.percentage,
'discount_value': 10.00,
'start_date': start_date,
'end_date': next_3_months,
'is_active': True,
'min_booking_amount': None,
'max_discount_amount': None,
'usage_limit': None,
},
]
created_count = 0
updated_count = 0
for promo_data in promotions_data:
existing = db.query(Promotion).filter(Promotion.code == promo_data['code']).first()
if existing:
# Update existing promotion
for key, value in promo_data.items():
if key != 'code': # Don't update the code
setattr(existing, key, value)
existing.updated_at = datetime.utcnow()
updated_count += 1
print(f'✓ Updated promotion: {promo_data["code"]}')
else:
# Create new promotion
promotion = Promotion(**promo_data)
db.add(promotion)
created_count += 1
print(f'✓ Created promotion: {promo_data["code"]}')
db.commit()
print(f'\n✓ Promotions seeded: {created_count} created, {updated_count} updated')
def main():
db: Session = SessionLocal()
try:
print('=' * 80)
print('SEEDING PROMOTIONS')
print('=' * 80)
print()
seed_promotions(db)
print('\n' + '=' * 80)
print('✓ All promotions seeded successfully!')
print('=' * 80)
except Exception as e:
db.rollback()
print(f'\n✗ Error seeding promotions: {e}')
import traceback
traceback.print_exc()
raise
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,141 +0,0 @@
import sys
import os
from pathlib import Path
# Add both the seeds_data directory and the Backend directory to the path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal, engine
from src.rooms.models.room import Room, RoomStatus
from src.rooms.models.room_type import RoomType
from datetime import datetime
import json
import random
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_rooms(db: Session):
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.')
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})')
from src.bookings.models.booking import Booking
from src.reviews.models.review import Review
from src.reviews.models.favorite import Favorite
existing_rooms = db.query(Room).all()
if existing_rooms:
print(f'\n🗑️ Deleting {len(existing_rooms)} existing room(s)...')
room_ids = [room.id for room in existing_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)')
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)')
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)')
for room in existing_rooms:
db.delete(room)
db.commit()
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
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
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 not room_type:
room_type = random.choice(room_types)
base_price = float(room_type.base_price)
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
price = base_price + floor_premium + view_premium + random_variation + size_premium
price = max(base_price * 0.95, price)
price = round(price, 2)
selected_amenities = random.sample(all_amenities, min(amenities_count, len(all_amenities)))
if floor >= 13:
premium_count = min(2, len(premium_amenities))
selected_amenities.extend(random.sample(premium_amenities, premium_count))
size_min, size_max = size_range
room_size = f'{random.randint(size_min, size_max)} sqm'
capacity = room_type.capacity
if random.random() > 0.7:
capacity = max(1, capacity + random.randint(-1, 1))
room_number = f'{floor}{room_counter % 100:02d}'
room_counter += 1
shuffled_images = luxury_room_images.copy()
random.shuffle(shuffled_images)
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_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}')
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()

View File

@@ -1,218 +0,0 @@
import sys
import os
import json
import re
from pathlib import Path
# Add parent directory to path to import from src
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
# Import all models to ensure relationships are set up
from src.models import * # This ensures all models are loaded and relationships are configured
from src.hotel_services.models.service import Service
def generate_slug(name: str) -> str:
"""Generate a URL-friendly slug from a name"""
slug = name.lower()
slug = re.sub(r'[^a-z0-9\s-]', '', slug)
slug = re.sub(r'\s+', '-', slug)
slug = re.sub(r'-+', '-', slug)
return slug.strip('-')
def seed_services(db: Session):
"""Seed initial services data"""
print('Seeding services...')
services_data = [
{
'name': 'Room Service',
'description': '24/7 in-room dining service with a wide selection of gourmet meals, snacks, and beverages delivered directly to your room.',
'price': 25.00,
'category': 'Dining',
'slug': 'room-service',
'image': 'https://images.unsplash.com/photo-1556911220-bff31c812dba?w=600',
'content': '<p>Enjoy the convenience of 24/7 room service with our extensive menu featuring international cuisine, local specialties, and premium beverages. Our professional staff ensures your meals are delivered hot, fresh, and beautifully presented.</p><p>From breakfast in bed to late-night snacks, we cater to all your dining needs with the highest standards of quality and service.</p>',
'sections': json.dumps([]),
'meta_title': 'Room Service - Luxury Hotel',
'meta_description': '24/7 in-room dining service with gourmet meals delivered to your room.',
'meta_keywords': 'room service, in-room dining, hotel service, 24/7 service',
'is_active': True
},
{
'name': 'Spa & Massage',
'description': 'Relaxing spa treatments and professional massage therapy to rejuvenate your mind and body.',
'price': 120.00,
'category': 'Wellness',
'slug': 'spa-massage',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=600',
'content': '<p>Indulge in our world-class spa treatments designed to restore balance and vitality. Our expert therapists offer a range of services including Swedish massage, deep tissue massage, hot stone therapy, and aromatherapy.</p><p>Each treatment is customized to your preferences, using premium products and ancient techniques to provide an unparalleled wellness experience.</p>',
'sections': json.dumps([]),
'meta_title': 'Spa & Massage Services - Luxury Hotel',
'meta_description': 'Professional spa treatments and massage therapy for ultimate relaxation and rejuvenation.',
'meta_keywords': 'spa, massage, wellness, relaxation, therapy',
'is_active': True
},
{
'name': 'Laundry Service',
'description': 'Professional dry cleaning and laundry service with same-day or next-day delivery options.',
'price': 15.00,
'category': 'Housekeeping',
'slug': 'laundry-service',
'image': 'https://images.unsplash.com/photo-1582735689369-4fe89db7114c?w=600',
'content': '<p>Keep your wardrobe fresh and clean with our professional laundry and dry cleaning service. We handle everything from delicate garments to business suits with the utmost care and attention.</p><p>Choose from same-day express service or standard next-day delivery. All items are professionally cleaned, pressed, and returned to your room.</p>',
'sections': json.dumps([]),
'meta_title': 'Laundry & Dry Cleaning Service - Luxury Hotel',
'meta_description': 'Professional laundry and dry cleaning service with same-day or next-day delivery.',
'meta_keywords': 'laundry, dry cleaning, hotel service, cleaning',
'is_active': True
},
{
'name': 'Airport Transfer',
'description': 'Complimentary airport pickup and drop-off service in luxury vehicles with professional drivers.',
'price': 50.00,
'category': 'Transportation',
'slug': 'airport-transfer',
'image': 'https://images.unsplash.com/photo-1449824913935-59a10b8d2000?w=600',
'content': '<p>Travel in comfort and style with our premium airport transfer service. Our fleet of luxury vehicles, including sedans and SUVs, ensures a smooth and comfortable journey to or from the airport.</p><p>Our professional drivers are punctual, courteous, and knowledgeable about the local area. Flight monitoring ensures we adjust to any delays or early arrivals.</p>',
'sections': json.dumps([]),
'meta_title': 'Airport Transfer Service - Luxury Hotel',
'meta_description': 'Premium airport pickup and drop-off service in luxury vehicles.',
'meta_keywords': 'airport transfer, transportation, airport shuttle, luxury car',
'is_active': True
},
{
'name': 'Concierge Service',
'description': 'Personalized assistance for restaurant reservations, event tickets, tours, and special requests.',
'price': 0.00,
'category': 'Concierge',
'slug': 'concierge-service',
'image': 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=600',
'content': '<p>Our dedicated concierge team is available 24/7 to ensure your stay is nothing short of extraordinary. From restaurant reservations and event tickets to private tours and transportation arrangements, we handle every detail with precision and care.</p><p>Whether you need assistance with business arrangements, special celebrations, or unique local experiences, our concierge team has the expertise and connections to make it happen.</p>',
'sections': json.dumps([]),
'meta_title': 'Concierge Services - Luxury Hotel',
'meta_description': 'Personalized assistance for all your travel and entertainment needs, available 24/7.',
'meta_keywords': 'concierge, personal assistant, travel services, luxury service',
'is_active': True
},
{
'name': 'Fitness Center Access',
'description': 'Access to our state-of-the-art fitness center with modern equipment and personal training options.',
'price': 20.00,
'category': 'Wellness',
'slug': 'fitness-center',
'image': 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=600',
'content': '<p>Maintain your fitness routine at our fully equipped fitness center featuring the latest cardio and strength training equipment. Our facilities are open 24/7 for your convenience.</p><p>Enhance your workout with personal training sessions, group fitness classes, or yoga sessions led by certified instructors. Towels, water, and fresh fruit are provided.</p>',
'sections': json.dumps([]),
'meta_title': 'Fitness Center - Luxury Hotel',
'meta_description': 'State-of-the-art fitness center with modern equipment and personal training options.',
'meta_keywords': 'fitness center, gym, workout, exercise, personal training',
'is_active': True
},
{
'name': 'Business Center',
'description': 'Fully equipped business center with meeting rooms, printing, copying, and secretarial services.',
'price': 30.00,
'category': 'Business',
'slug': 'business-center',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=600',
'content': '<p>Stay productive with our fully equipped business center featuring private meeting rooms, high-speed internet, printing and copying services, and professional secretarial support.</p><p>Our meeting rooms can accommodate small groups and are equipped with presentation equipment, video conferencing capabilities, and refreshments.</p>',
'sections': json.dumps([]),
'meta_title': 'Business Center Services - Luxury Hotel',
'meta_description': 'Fully equipped business center with meeting rooms and professional services.',
'meta_keywords': 'business center, meeting room, conference, office services',
'is_active': True
},
{
'name': 'Valet Parking',
'description': 'Secure valet parking service with 24/7 vehicle care and quick retrieval.',
'price': 35.00,
'category': 'Transportation',
'slug': 'valet-parking',
'image': 'https://images.unsplash.com/photo-1502877338535-766e1452684a?w=600',
'content': '<p>Enjoy the convenience of valet parking with our professional service. Your vehicle will be safely parked and secured, ready for quick retrieval whenever you need it.</p><p>Our valet team is available 24/7 and can also assist with luggage handling and vehicle care services.</p>',
'sections': json.dumps([]),
'meta_title': 'Valet Parking Service - Luxury Hotel',
'meta_description': 'Secure valet parking service with 24/7 vehicle care and quick retrieval.',
'meta_keywords': 'valet parking, parking service, car service, vehicle care',
'is_active': True
},
{
'name': 'Babysitting Service',
'description': 'Professional and certified babysitting service for your peace of mind.',
'price': 25.00,
'category': 'Family',
'slug': 'babysitting-service',
'image': 'https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?w=600',
'content': '<p>Enjoy your time knowing your children are in safe hands with our professional babysitting service. Our certified caregivers are experienced, background-checked, and trained in child safety and first aid.</p><p>Available for both in-room care and supervised activities, we ensure your children are entertained and well-cared for while you enjoy your stay.</p>',
'sections': json.dumps([]),
'meta_title': 'Babysitting Service - Luxury Hotel',
'meta_description': 'Professional and certified babysitting service for your peace of mind.',
'meta_keywords': 'babysitting, childcare, kids service, family service',
'is_active': True
},
{
'name': 'Pet Care Service',
'description': 'Pet-friendly accommodations with pet care services including walking, feeding, and grooming.',
'price': 20.00,
'category': 'Pet Services',
'slug': 'pet-care-service',
'image': 'https://images.unsplash.com/photo-1601758228041-f3b2795255f1?w=600',
'content': '<p>Your furry friends are welcome at our hotel! We offer pet-friendly accommodations and a range of pet care services including daily walks, feeding, and grooming.</p><p>Our pet care team ensures your pets are comfortable and well-cared for during your stay. Pet amenities including beds, bowls, and treats are provided.</p>',
'sections': json.dumps([]),
'meta_title': 'Pet Care Services - Luxury Hotel',
'meta_description': 'Pet-friendly accommodations with professional pet care services.',
'meta_keywords': 'pet care, pet service, dog walking, pet friendly',
'is_active': True
}
]
created_count = 0
updated_count = 0
for service_data in services_data:
# Check if service already exists by slug
existing = db.query(Service).filter(Service.slug == service_data['slug']).first()
if existing:
# Update existing service
for key, value in service_data.items():
if key != 'slug': # Don't update slug
setattr(existing, key, value)
updated_count += 1
print(f' ✓ Updated service: {service_data["name"]}')
else:
# Create new service
service = Service(**service_data)
db.add(service)
created_count += 1
print(f' ✓ Created service: {service_data["name"]}')
db.commit()
print(f'\n✓ Services seeded successfully!')
print(f' - Created: {created_count}')
print(f' - Updated: {updated_count}')
print(f' - Total: {len(services_data)}\n')
def main():
db: Session = SessionLocal()
try:
print('=' * 80)
print('SEEDING SERVICES')
print('=' * 80)
print()
seed_services(db)
print('=' * 80)
print('✓ All services data seeded successfully!')
print('=' * 80)
except Exception as e:
db.rollback()
print(f'\n✗ Error seeding services: {e}')
import traceback
traceback.print_exc()
raise
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,756 +0,0 @@
import sys
import os
import json
import re
from pathlib import Path
# Add parent directory to path to import from src
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
# Import all models to ensure relationships are set up
from src.models import * # This ensures all models are loaded and relationships are configured
from src.hotel_services.models.service import Service
def generate_slug(name: str) -> str:
"""Generate a URL-friendly slug from a name"""
slug = name.lower()
slug = re.sub(r'[^a-z0-9\s-]', '', slug)
slug = re.sub(r'\s+', '-', slug)
slug = re.sub(r'-+', '-', slug)
return slug.strip('-')
def seed_enterprise_services(db: Session):
"""Seed enterprise-level services with rich detail page content"""
print('Seeding enterprise services...')
services_data = [
{
'name': 'Luxury Spa & Wellness Retreat',
'description': 'Indulge in our world-class spa treatments designed to restore balance and vitality. Experience ultimate relaxation with our expert therapists.',
'price': 250.00,
'category': 'Wellness',
'slug': 'luxury-spa-wellness-retreat',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Experience Ultimate Relaxation</h2>
<p>Our Luxury Spa & Wellness Retreat offers an unparalleled journey of rejuvenation and tranquility. Nestled in a serene environment, our spa combines ancient healing traditions with modern wellness techniques to create a transformative experience.</p>
<h3>What's Included</h3>
<ul>
<li>90-minute signature massage therapy</li>
<li>Access to steam room and sauna</li>
<li>Complimentary herbal tea and refreshments</li>
<li>Premium aromatherapy oils and products</li>
<li>Relaxation lounge access</li>
</ul>
<h3>Our Signature Treatments</h3>
<p>Choose from our curated selection of treatments including Swedish massage, deep tissue therapy, hot stone massage, and aromatherapy sessions. Each treatment is customized to your specific needs and preferences.</p>
<h3>Expert Therapists</h3>
<p>Our team of certified therapists brings years of experience and a deep understanding of holistic wellness. They are trained in various massage techniques and wellness practices to ensure you receive the highest quality care.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Transform Your Wellbeing',
'content': 'Discover a sanctuary of peace and rejuvenation where every detail is designed to restore your mind, body, and spirit.',
'image': 'https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Why Choose Our Spa',
'features': [
{'title': 'Expert Therapists', 'description': 'Certified professionals with years of experience', 'icon': 'User'},
{'title': 'Premium Products', 'description': 'Luxury skincare and aromatherapy products', 'icon': 'Sparkles'},
{'title': 'Customized Treatments', 'description': 'Personalized sessions tailored to your needs', 'icon': 'Heart'},
{'title': 'Serene Environment', 'description': 'Peaceful setting designed for relaxation', 'icon': 'Leaf'}
]
},
{
'type': 'quote',
'quote': 'The most luxurious spa experience I\'ve ever had. Truly transformative.',
'author': 'Sarah M., Guest'
}
]),
'meta_title': 'Luxury Spa & Wellness Retreat - Premium Hotel Services',
'meta_description': 'Experience ultimate relaxation with our world-class spa treatments. Expert therapists, premium products, and a serene environment await you.',
'meta_keywords': 'luxury spa, wellness retreat, massage therapy, hotel spa, relaxation, aromatherapy, wellness services',
'is_active': True
},
{
'name': 'Fine Dining Experience',
'description': 'Savor culinary excellence at our Michelin-starred restaurants. World-renowned chefs craft exquisite dishes using the finest ingredients.',
'price': 150.00,
'category': 'Dining',
'slug': 'fine-dining-experience',
'image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Culinary Excellence Awaits</h2>
<p>Embark on a gastronomic journey at our award-winning restaurants, where culinary artistry meets exceptional service. Our Michelin-starred chefs create masterpieces that celebrate both local traditions and international flavors.</p>
<h3>Our Restaurants</h3>
<ul>
<li><strong>The Grand Ballroom:</strong> Elegant fine dining with seasonal tasting menus</li>
<li><strong>Sky Terrace:</strong> Rooftop dining with panoramic city views</li>
<li><strong>Chef's Table:</strong> Intimate 8-seat private dining experience</li>
<li><strong>Wine Cellar:</strong> Exclusive wine pairing dinners</li>
</ul>
<h3>What's Included</h3>
<ul>
<li>Multi-course tasting menu</li>
<li>Wine pairing recommendations</li>
<li>Complimentary amuse-bouche</li>
<li>Professional sommelier service</li>
<li>Personalized menu customization</li>
</ul>
<h3>Reservation Information</h3>
<p>Reservations are recommended and can be made through our concierge or directly at the restaurant. Special dietary requirements and preferences are accommodated with advance notice.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'A Culinary Journey Like No Other',
'content': 'Where every dish tells a story and every meal becomes a memory.',
'image': 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&h=600&fit=crop'
},
{
'type': 'gallery',
'title': 'Our Culinary Creations',
'images': [
'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=800',
'https://images.unsplash.com/photo-1556911220-bff31c812dba?w=800',
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=800'
]
},
{
'type': 'quote',
'quote': 'An extraordinary dining experience that exceeded all expectations. The attention to detail is remarkable.',
'author': 'Michael R., Food Critic'
}
]),
'meta_title': 'Fine Dining Experience - Michelin-Starred Restaurant',
'meta_description': 'Savor culinary excellence at our Michelin-starred restaurants. World-renowned chefs, exquisite dishes, and exceptional service.',
'meta_keywords': 'fine dining, michelin star, luxury restaurant, gourmet cuisine, fine dining hotel',
'is_active': True
},
{
'name': '24/7 Premium Room Service',
'description': 'Enjoy the convenience of round-the-clock in-room dining with our extensive menu featuring international cuisine and premium beverages.',
'price': 35.00,
'category': 'Dining',
'slug': 'premium-room-service',
'image': 'https://images.unsplash.com/photo-1556911220-bff31c812dba?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Dining at Your Convenience</h2>
<p>Experience the ultimate in-room dining service available 24 hours a day. From breakfast in bed to late-night snacks, our extensive menu caters to every craving with the highest standards of quality and presentation.</p>
<h3>Menu Highlights</h3>
<ul>
<li><strong>Breakfast:</strong> Continental, American, and healthy options</li>
<li><strong>Lunch & Dinner:</strong> International cuisine, local specialties, and chef's recommendations</li>
<li><strong>Desserts:</strong> Artisanal pastries and premium ice creams</li>
<li><strong>Beverages:</strong> Premium wines, craft cocktails, and specialty coffees</li>
</ul>
<h3>Service Features</h3>
<ul>
<li>Average delivery time: 25-30 minutes</li>
<li>Professional table setup in your room</li>
<li>Hot meals served at optimal temperature</li>
<li>Special dietary accommodations available</li>
<li>Complimentary bread and butter service</li>
</ul>
<h3>How to Order</h3>
<p>Simply call our room service line from your in-room phone or use our mobile app. Our team is available 24/7 to take your order and ensure prompt delivery.</p>
</div>''',
'sections': json.dumps([
{
'type': 'features',
'title': 'Why Choose Our Room Service',
'features': [
{'title': '24/7 Availability', 'description': 'Order anytime, day or night', 'icon': 'Clock'},
{'title': 'Fast Delivery', 'description': 'Average 25-30 minute delivery time', 'icon': 'Zap'},
{'title': 'Premium Quality', 'description': 'Restaurant-quality meals in your room', 'icon': 'Award'},
{'title': 'Professional Service', 'description': 'Elegant table setup and presentation', 'icon': 'UserCheck'}
]
}
]),
'meta_title': '24/7 Premium Room Service - Luxury Hotel',
'meta_description': 'Enjoy round-the-clock in-room dining with our extensive menu. International cuisine, premium beverages, and professional service delivered to your room.',
'meta_keywords': 'room service, in-room dining, 24/7 service, hotel dining, room service menu',
'is_active': True
},
{
'name': 'Executive Business Center',
'description': 'Fully equipped business center with private meeting rooms, high-speed internet, printing services, and professional secretarial support.',
'price': 75.00,
'category': 'Business',
'slug': 'executive-business-center',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Your Office Away From Office</h2>
<p>Stay productive with our state-of-the-art Executive Business Center, designed to meet all your professional needs. Whether you need a quiet workspace, a meeting room, or professional support services, we have everything you need.</p>
<h3>Facilities & Services</h3>
<ul>
<li><strong>Private Meeting Rooms:</strong> Various sizes accommodating 2-20 people</li>
<li><strong>High-Speed Internet:</strong> Fiber-optic connection with secure Wi-Fi</li>
<li><strong>Printing & Copying:</strong> Color and black & white printing, scanning, and binding</li>
<li><strong>Presentation Equipment:</strong> Projectors, screens, video conferencing</li>
<li><strong>Secretarial Services:</strong> Typing, translation, and administrative support</li>
<li><strong>Refreshments:</strong> Complimentary coffee, tea, and water</li>
</ul>
<h3>Meeting Room Features</h3>
<ul>
<li>Soundproof walls for privacy</li>
<li>Ergonomic seating and modern furniture</li>
<li>Whiteboards and flip charts</li>
<li>Video conferencing capabilities</li>
<li>Climate control and natural lighting</li>
</ul>
<h3>Reservation</h3>
<p>Meeting rooms can be reserved in advance through our concierge or business center. Hourly and daily rates available. Special packages for extended stays.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Productivity Meets Luxury',
'content': 'A professional workspace designed for success, equipped with everything you need to stay productive.',
'image': 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Everything You Need',
'features': [
{'title': 'Private Meeting Rooms', 'description': 'Various sizes for any business need', 'icon': 'Users'},
{'title': 'High-Speed Internet', 'description': 'Fiber-optic connection with secure Wi-Fi', 'icon': 'Wifi'},
{'title': 'Professional Support', 'description': 'Secretarial and administrative services', 'icon': 'Briefcase'},
{'title': 'Modern Equipment', 'description': 'Latest technology and presentation tools', 'icon': 'Monitor'}
]
}
]),
'meta_title': 'Executive Business Center - Professional Workspace',
'meta_description': 'Fully equipped business center with meeting rooms, high-speed internet, printing services, and professional support. Your office away from office.',
'meta_keywords': 'business center, meeting room, conference room, office services, hotel business center',
'is_active': True
},
{
'name': 'Luxury Airport Transfer',
'description': 'Travel in comfort and style with our premium airport transfer service. Luxury vehicles, professional drivers, and flight monitoring for a seamless journey.',
'price': 85.00,
'category': 'Transportation',
'slug': 'luxury-airport-transfer',
'image': 'https://images.unsplash.com/photo-1449824913935-59a10b8d2000?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Arrive in Style</h2>
<p>Begin or end your journey with our premium airport transfer service. Our fleet of luxury vehicles and professional drivers ensure a comfortable, punctual, and stress-free experience.</p>
<h3>Our Fleet</h3>
<ul>
<li><strong>Luxury Sedans:</strong> Premium sedans for up to 3 passengers</li>
<li><strong>Executive SUVs:</strong> Spacious SUVs for up to 6 passengers</li>
<li><strong>Luxury Vans:</strong> Large vehicles for groups up to 8 passengers</li>
<li><strong>VIP Limousines:</strong> Ultimate luxury for special occasions</li>
</ul>
<h3>Service Features</h3>
<ul>
<li>Flight monitoring for delays and early arrivals</li>
<li>Meet & greet service at the airport</li>
<li>Complimentary bottled water and newspapers</li>
<li>Luggage assistance</li>
<li>Wi-Fi connectivity in vehicles</li>
<li>Professional, licensed, and insured drivers</li>
</ul>
<h3>Booking Information</h3>
<p>Reservations should be made at least 24 hours in advance. Please provide flight details for arrival transfers. Our team monitors flights and adjusts pickup times accordingly.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Your Journey Starts Here',
'content': 'Experience the comfort and convenience of premium airport transfers.',
'image': 'https://images.unsplash.com/photo-1449824913935-59a10b8d2000?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Why Choose Our Transfer Service',
'features': [
{'title': 'Luxury Fleet', 'description': 'Premium vehicles for every need', 'icon': 'Car'},
{'title': 'Professional Drivers', 'description': 'Licensed, experienced, and courteous', 'icon': 'User'},
{'title': 'Flight Monitoring', 'description': 'Automatic updates for delays', 'icon': 'Plane'},
{'title': 'Complimentary Amenities', 'description': 'Water, Wi-Fi, and newspapers', 'icon': 'Gift'}
]
}
]),
'meta_title': 'Luxury Airport Transfer - Premium Transportation',
'meta_description': 'Travel in comfort with our premium airport transfer service. Luxury vehicles, professional drivers, and flight monitoring for a seamless journey.',
'meta_keywords': 'airport transfer, luxury transportation, airport shuttle, hotel transfer, airport service',
'is_active': True
},
{
'name': 'Personal Concierge Service',
'description': 'Dedicated 24/7 concierge assistance for restaurant reservations, event tickets, tours, transportation, and all your special requests.',
'price': 0.00,
'category': 'Concierge',
'slug': 'personal-concierge-service',
'image': 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Your Personal Assistant</h2>
<p>Our dedicated concierge team is available 24/7 to ensure your stay is nothing short of extraordinary. From restaurant reservations and event tickets to private tours and unique experiences, we handle every detail with precision and care.</p>
<h3>Services We Provide</h3>
<ul>
<li><strong>Dining:</strong> Restaurant reservations at the finest establishments</li>
<li><strong>Entertainment:</strong> Theater tickets, concerts, and event access</li>
<li><strong>Tours & Activities:</strong> Private tours, cultural experiences, and adventure activities</li>
<li><strong>Transportation:</strong> Car rentals, chauffeur services, and travel arrangements</li>
<li><strong>Business Services:</strong> Meeting room bookings, translation services, and more</li>
<li><strong>Special Requests:</strong> Gift arrangements, celebrations, and unique experiences</li>
</ul>
<h3>How We Can Help</h3>
<p>Whether you need last-minute reservations at a popular restaurant, tickets to a sold-out show, or help planning a special celebration, our concierge team has the expertise and connections to make it happen. No request is too big or too small.</p>
<h3>Contact Us</h3>
<p>Reach our concierge team 24/7 via phone, email, or in-person at the concierge desk. We're here to make your stay unforgettable.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Making Your Dreams Come True',
'content': 'Your personal assistant, available 24/7 to fulfill every request.',
'image': 'https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=1200&h=600&fit=crop'
},
{
'type': 'cta',
'title': 'Need Assistance?',
'cta_text': 'Contact Our Concierge',
'cta_link': '/contact',
'content': 'Our team is standing by to help with any request, big or small.'
}
]),
'meta_title': 'Personal Concierge Service - 24/7 Assistance',
'meta_description': 'Dedicated 24/7 concierge service for restaurant reservations, event tickets, tours, and all your special requests. Making your stay extraordinary.',
'meta_keywords': 'concierge service, personal assistant, hotel concierge, travel services, luxury service',
'is_active': True
},
{
'name': 'State-of-the-Art Fitness Center',
'description': 'Access our fully equipped fitness center with modern equipment, personal training options, and group fitness classes. Open 24/7 for your convenience.',
'price': 30.00,
'category': 'Wellness',
'slug': 'fitness-center-access',
'image': 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Stay Fit, Stay Strong</h2>
<p>Maintain your fitness routine at our state-of-the-art fitness center featuring the latest cardio and strength training equipment. Our facilities are designed to meet the needs of both casual exercisers and serious athletes.</p>
<h3>Equipment & Facilities</h3>
<ul>
<li><strong>Cardio Equipment:</strong> Treadmills, ellipticals, stationary bikes, and rowing machines</li>
<li><strong>Strength Training:</strong> Free weights, weight machines, and functional training equipment</li>
<li><strong>Group Fitness Studio:</strong> Space for yoga, Pilates, and group classes</li>
<li><strong>Locker Rooms:</strong> Spacious lockers, showers, and sauna access</li>
<li><strong>Complimentary Amenities:</strong> Towels, water, fresh fruit, and protein bars</li>
</ul>
<h3>Additional Services</h3>
<ul>
<li><strong>Personal Training:</strong> One-on-one sessions with certified trainers</li>
<li><strong>Group Classes:</strong> Yoga, Pilates, spinning, and HIIT classes</li>
<li><strong>Fitness Assessments:</strong> Body composition analysis and fitness evaluations</li>
<li><strong>Nutritional Guidance:</strong> Consultation with our wellness experts</li>
</ul>
<h3>Operating Hours</h3>
<p>Our fitness center is open 24/7 for your convenience. Personal training and group classes are available by appointment. Check the schedule at the front desk or contact our fitness team.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Your Fitness Journey Continues',
'content': 'World-class equipment and expert guidance to help you achieve your fitness goals.',
'image': 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Why Our Fitness Center',
'features': [
{'title': '24/7 Access', 'description': 'Work out on your schedule', 'icon': 'Clock'},
{'title': 'Modern Equipment', 'description': 'Latest cardio and strength training machines', 'icon': 'Activity'},
{'title': 'Expert Trainers', 'description': 'Certified personal trainers available', 'icon': 'User'},
{'title': 'Group Classes', 'description': 'Yoga, Pilates, and more', 'icon': 'Users'}
]
}
]),
'meta_title': 'State-of-the-Art Fitness Center - 24/7 Access',
'meta_description': 'Fully equipped fitness center with modern equipment, personal training, and group classes. Open 24/7 for your convenience.',
'meta_keywords': 'fitness center, gym, hotel gym, workout, exercise, personal training, 24/7 gym',
'is_active': True
},
{
'name': 'Premium Laundry & Dry Cleaning',
'description': 'Professional laundry and dry cleaning service with same-day express or next-day standard delivery. Expert care for all your garments.',
'price': 20.00,
'category': 'Housekeeping',
'slug': 'premium-laundry-dry-cleaning',
'image': 'https://images.unsplash.com/photo-1582735689369-4fe89db7114c?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Expert Garment Care</h2>
<p>Keep your wardrobe fresh and impeccably maintained with our professional laundry and dry cleaning service. We handle everything from delicate silk garments to business suits with the utmost care and attention to detail.</p>
<h3>Our Services</h3>
<ul>
<li><strong>Dry Cleaning:</strong> Professional cleaning for suits, dresses, and delicate fabrics</li>
<li><strong>Laundry Service:</strong> Washing, drying, and pressing for everyday garments</li>
<li><strong>Pressing Only:</strong> Professional pressing and steaming services</li>
<li><strong>Alterations:</strong> Minor repairs and adjustments available</li>
<li><strong>Specialty Items:</strong> Wedding dresses, formal wear, and designer garments</li>
</ul>
<h3>Delivery Options</h3>
<ul>
<li><strong>Express Service:</strong> Same-day delivery (orders before 9 AM)</li>
<li><strong>Standard Service:</strong> Next-day delivery</li>
<li><strong>Bulk Service:</strong> Special rates for multiple items</li>
</ul>
<h3>How to Use</h3>
<p>Simply place your items in the laundry bag provided in your room and call housekeeping. Our team will collect your items, process them with care, and return them to your room at the specified time.</p>
</div>''',
'sections': json.dumps([
{
'type': 'features',
'title': 'Why Choose Our Service',
'features': [
{'title': 'Expert Care', 'description': 'Professional handling of all garment types', 'icon': 'Shield'},
{'title': 'Fast Service', 'description': 'Same-day express option available', 'icon': 'Zap'},
{'title': 'Quality Guarantee', 'description': 'Satisfaction guaranteed on all services', 'icon': 'CheckCircle'},
{'title': 'Eco-Friendly', 'description': 'Environmentally conscious cleaning methods', 'icon': 'Leaf'}
]
}
]),
'meta_title': 'Premium Laundry & Dry Cleaning - Professional Service',
'meta_description': 'Professional laundry and dry cleaning with same-day or next-day delivery. Expert care for all your garments.',
'meta_keywords': 'laundry service, dry cleaning, hotel laundry, garment care, cleaning service',
'is_active': True
},
{
'name': 'Valet Parking Service',
'description': 'Secure valet parking with 24/7 vehicle care, quick retrieval, and optional car wash services. Your vehicle is in safe hands.',
'price': 45.00,
'category': 'Transportation',
'slug': 'valet-parking-service',
'image': 'https://images.unsplash.com/photo-1502877338535-766e1452684a?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Secure & Convenient Parking</h2>
<p>Enjoy the ultimate convenience of valet parking with our professional service. Your vehicle will be safely parked and secured, ready for quick retrieval whenever you need it. Our valet team is available 24/7 to assist you.</p>
<h3>Service Features</h3>
<ul>
<li>Secure, monitored parking facility</li>
<li>24/7 valet service availability</li>
<li>Quick vehicle retrieval (average 5 minutes)</li>
<li>Complimentary vehicle inspection</li>
<li>Luggage assistance included</li>
<li>Optional car wash and detailing services</li>
</ul>
<h3>Additional Services</h3>
<ul>
<li><strong>Car Wash:</strong> Exterior wash and interior vacuum</li>
<li><strong>Detailing:</strong> Full interior and exterior detailing</li>
<li><strong>Battery Jump Start:</strong> Assistance with vehicle issues</li>
<li><strong>Tire Pressure Check:</strong> Complimentary tire service</li>
</ul>
<h3>Pricing</h3>
<p>Daily rates available for extended stays. Weekly and monthly packages offer significant savings. Contact our valet team for special rates.</p>
</div>''',
'sections': json.dumps([
{
'type': 'features',
'title': 'Why Choose Our Valet Service',
'features': [
{'title': 'Secure Facility', 'description': 'Monitored and protected parking', 'icon': 'Shield'},
{'title': 'Quick Service', 'description': 'Average 5-minute retrieval time', 'icon': 'Clock'},
{'title': '24/7 Availability', 'description': 'Service available around the clock', 'icon': 'Sun'},
{'title': 'Additional Services', 'description': 'Car wash and detailing available', 'icon': 'Sparkles'}
]
}
]),
'meta_title': 'Valet Parking Service - Secure & Convenient',
'meta_description': 'Secure valet parking with 24/7 service, quick retrieval, and optional car care services. Your vehicle is in safe hands.',
'meta_keywords': 'valet parking, parking service, hotel parking, car service, valet',
'is_active': True
},
{
'name': 'Professional Babysitting Service',
'description': 'Certified and experienced babysitters available for in-room care and supervised activities. Background-checked professionals for your peace of mind.',
'price': 35.00,
'category': 'Family',
'slug': 'professional-babysitting-service',
'image': 'https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Your Children in Safe Hands</h2>
<p>Enjoy your time knowing your children are in the care of our professional babysitting service. Our certified caregivers are experienced, background-checked, and trained in child safety and first aid.</p>
<h3>Our Caregivers</h3>
<ul>
<li>Certified in CPR and first aid</li>
<li>Background-checked and verified</li>
<li>Experienced with children of all ages</li>
<li>Multilingual capabilities available</li>
<li>References available upon request</li>
</ul>
<h3>Services Offered</h3>
<ul>
<li><strong>In-Room Care:</strong> Supervised care in your hotel room</li>
<li><strong>Activity Supervision:</strong> Accompany children to hotel activities</li>
<li><strong>Evening Care:</strong> Bedtime routines and overnight care</li>
<li><strong>Group Care:</strong> Multiple children from the same family</li>
</ul>
<h3>Booking Information</h3>
<p>Reservations should be made at least 4 hours in advance. Same-day service may be available subject to caregiver availability. Minimum booking: 2 hours.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Peace of Mind for Parents',
'content': 'Certified professionals ensuring your children are safe, happy, and well-cared for.',
'image': 'https://images.unsplash.com/photo-1503454537195-1dcabb73ffb9?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Why Parents Trust Us',
'features': [
{'title': 'Certified Caregivers', 'description': 'CPR and first aid certified', 'icon': 'Shield'},
{'title': 'Background Checked', 'description': 'Thoroughly vetted professionals', 'icon': 'UserCheck'},
{'title': 'Experienced', 'description': 'Years of childcare experience', 'icon': 'Heart'},
{'title': 'Flexible Service', 'description': 'In-room or activity supervision', 'icon': 'Clock'}
]
}
]),
'meta_title': 'Professional Babysitting Service - Certified Caregivers',
'meta_description': 'Certified and experienced babysitters for in-room care and supervised activities. Background-checked professionals for your peace of mind.',
'meta_keywords': 'babysitting service, childcare, hotel babysitting, kids care, family services',
'is_active': True
},
{
'name': 'Pet Care & Accommodation',
'description': 'Pet-friendly accommodations with professional pet care services including walking, feeding, grooming, and pet-sitting. Your furry friends are welcome!',
'price': 25.00,
'category': 'Pet Services',
'slug': 'pet-care-accommodation',
'image': 'https://images.unsplash.com/photo-1601758228041-f3b2795255f1?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Your Pets Are Family Too</h2>
<p>We welcome your furry family members! Our pet-friendly accommodations and professional pet care services ensure your pets are as comfortable and well-cared for as you are during your stay.</p>
<h3>Pet Amenities</h3>
<ul>
<li>Comfortable pet beds and blankets</li>
<li>Food and water bowls</li>
<li>Complimentary treats and toys</li>
<li>Pet waste bags and disposal</li>
<li>Designated pet relief areas</li>
</ul>
<h3>Pet Care Services</h3>
<ul>
<li><strong>Dog Walking:</strong> Regular walks and exercise</li>
<li><strong>Pet Sitting:</strong> In-room care while you're away</li>
<li><strong>Feeding Service:</strong> Scheduled feeding times</li>
<li><strong>Grooming:</strong> Basic grooming and bathing</li>
<li><strong>Veterinary Referrals:</strong> Local vet recommendations</li>
</ul>
<h3>Pet Policy</h3>
<p>Pets up to 50 lbs are welcome. A pet fee applies per night. Please inform us in advance about your pet's stay. We ask that pets be leashed in public areas and that owners clean up after their pets.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'A Home Away From Home for Your Pets',
'content': 'Because your pets deserve the same luxury experience as you.',
'image': 'https://images.unsplash.com/photo-1601758228041-f3b2795255f1?w=1200&h=600&fit=crop'
},
{
'type': 'features',
'title': 'Pet-Friendly Features',
'features': [
{'title': 'Pet Amenities', 'description': 'Beds, bowls, treats, and toys provided', 'icon': 'Heart'},
{'title': 'Professional Care', 'description': 'Walking, feeding, and grooming services', 'icon': 'User'},
{'title': 'Designated Areas', 'description': 'Pet relief areas and walking paths', 'icon': 'MapPin'},
{'title': 'Vet Referrals', 'description': 'Local veterinary recommendations', 'icon': 'Stethoscope'}
]
}
]),
'meta_title': 'Pet Care & Accommodation - Pet-Friendly Hotel',
'meta_description': 'Pet-friendly accommodations with professional pet care services. Walking, feeding, grooming, and pet-sitting available. Your pets are welcome!',
'meta_keywords': 'pet care, pet friendly hotel, dog walking, pet services, pet accommodation',
'is_active': True
},
{
'name': 'Premium Wine & Spirits Collection',
'description': 'Extensive collection of fine wines, premium spirits, and craft cocktails. Expert sommelier service and private wine tastings available.',
'price': 0.00,
'category': 'Dining',
'slug': 'premium-wine-spirits-collection',
'image': 'https://images.unsplash.com/photo-1514362545857-3bc16c4c7d1b?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Curated Excellence</h2>
<p>Discover our extensive collection of fine wines, premium spirits, and artisanal cocktails. Our master sommelier has curated a selection that spans the globe, featuring rare vintages, limited editions, and exceptional spirits.</p>
<h3>Our Collection</h3>
<ul>
<li><strong>Fine Wines:</strong> Over 500 labels from renowned vineyards worldwide</li>
<li><strong>Premium Spirits:</strong> Rare whiskeys, cognacs, and artisanal spirits</li>
<li><strong>Craft Cocktails:</strong> Signature cocktails created by our expert mixologists</li>
<li><strong>Champagne & Sparkling:</strong> Exclusive selection of premium bubbles</li>
</ul>
<h3>Services</h3>
<ul>
<li><strong>Sommelier Service:</strong> Expert wine recommendations and pairings</li>
<li><strong>Wine Tastings:</strong> Private tastings and educational sessions</li>
<li><strong>Bar Service:</strong> Craft cocktails at our premium bars</li>
<li><strong>Private Events:</strong> Wine dinners and tasting events</li>
</ul>
<h3>Locations</h3>
<p>Enjoy our collection at our signature bars, restaurants, or through our room service. Our sommelier is available for consultations and recommendations.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'A World of Flavors',
'content': 'Curated by experts, enjoyed by connoisseurs.',
'image': 'https://images.unsplash.com/photo-1514362545857-3bc16c4c7d1b?w=1200&h=600&fit=crop'
},
{
'type': 'quote',
'quote': 'An exceptional collection that rivals the finest establishments in the world.',
'author': 'Wine Enthusiast Magazine'
}
]),
'meta_title': 'Premium Wine & Spirits Collection - Fine Beverages',
'meta_description': 'Extensive collection of fine wines, premium spirits, and craft cocktails. Expert sommelier service and private tastings available.',
'meta_keywords': 'wine collection, premium spirits, sommelier, wine tasting, luxury bar, craft cocktails',
'is_active': True
},
{
'name': 'Private Event & Catering Services',
'description': 'Professional event planning and catering services for weddings, corporate events, celebrations, and private gatherings. Make your special occasion unforgettable.',
'price': 0.00,
'category': 'Entertainment',
'slug': 'private-event-catering-services',
'image': 'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=1200&h=800&fit=crop',
'content': '''<div class="service-detail-content">
<h2>Unforgettable Events</h2>
<p>From intimate gatherings to grand celebrations, our professional event planning and catering team will ensure your special occasion is executed flawlessly. We handle every detail so you can enjoy your event.</p>
<h3>Event Types</h3>
<ul>
<li><strong>Weddings:</strong> Ceremonies, receptions, and rehearsal dinners</li>
<li><strong>Corporate Events:</strong> Conferences, meetings, and team building</li>
<li><strong>Celebrations:</strong> Birthdays, anniversaries, and milestones</li>
<li><strong>Private Dinners:</strong> Intimate gatherings and special occasions</li>
</ul>
<h3>Our Services</h3>
<ul>
<li>Complete event planning and coordination</li>
<li>Customized menu design and catering</li>
<li>Venue selection and setup</li>
<li>Floral arrangements and decorations</li>
<li>Entertainment coordination</li>
<li>Photography and videography services</li>
<li>Technical support and AV equipment</li>
</ul>
<h3>Planning Process</h3>
<p>Our event specialists will work with you from initial consultation through event execution. We offer flexible packages and can customize services to meet your specific needs and budget.</p>
</div>''',
'sections': json.dumps([
{
'type': 'hero',
'title': 'Making Memories That Last',
'content': 'Professional event planning and catering for your most important occasions.',
'image': 'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=1200&h=600&fit=crop'
},
{
'type': 'cta',
'title': 'Planning an Event?',
'cta_text': 'Contact Our Event Team',
'cta_link': '/contact',
'content': 'Let us help you create an unforgettable experience.'
}
]),
'meta_title': 'Private Event & Catering Services - Professional Planning',
'meta_description': 'Professional event planning and catering for weddings, corporate events, and celebrations. Make your special occasion unforgettable.',
'meta_keywords': 'event planning, catering, wedding planning, corporate events, private events, hotel events',
'is_active': True
}
]
created_count = 0
updated_count = 0
for service_data in services_data:
# Check if service already exists by slug
existing = db.query(Service).filter(Service.slug == service_data['slug']).first()
if existing:
# Update existing service
for key, value in service_data.items():
if key != 'slug': # Don't update slug
setattr(existing, key, value)
updated_count += 1
print(f' ✓ Updated service: {service_data["name"]}')
else:
# Create new service
service = Service(**service_data)
db.add(service)
created_count += 1
print(f' ✓ Created service: {service_data["name"]}')
db.commit()
print(f'\n✓ Enterprise services seeded successfully!')
print(f' - Created: {created_count}')
print(f' - Updated: {updated_count}')
print(f' - Total: {len(services_data)}\n')
def main():
db: Session = SessionLocal()
try:
print('=' * 80)
print('SEEDING ENTERPRISE SERVICES')
print('=' * 80)
print()
seed_enterprise_services(db)
print('=' * 80)
print('✓ All enterprise services data seeded successfully!')
print('=' * 80)
except Exception as e:
db.rollback()
print(f'\n✗ Error seeding services: {e}')
import traceback
traceback.print_exc()
raise
finally:
db.close()
if __name__ == '__main__':
main()

View File

@@ -1,194 +0,0 @@
import sys
import os
from pathlib import Path
# Add both the seeds_data directory and the Backend directory to the path
sys.path.insert(0, str(Path(__file__).parent))
sys.path.insert(0, str(Path(__file__).parent.parent))
from sqlalchemy.orm import Session
from src.shared.config.database import SessionLocal
from src.auth.models.role import Role
from src.auth.models.user import User
import bcrypt
from datetime import datetime
def get_db():
db = SessionLocal()
try:
return db
finally:
pass
def seed_users(db: Session):
print('=' * 80)
print('SEEDING USERS')
print('=' * 80)
# Get roles
admin_role = db.query(Role).filter(Role.name == 'admin').first()
staff_role = db.query(Role).filter(Role.name == 'staff').first()
customer_role = db.query(Role).filter(Role.name == 'customer').first()
housekeeping_role = db.query(Role).filter(Role.name == 'housekeeping').first()
if not admin_role or not staff_role or not customer_role:
print(' ❌ Roles not found! Please seed roles first.')
return
users_data = [
{
'email': 'gnxsoft@gnxsoft.com',
'password': 'gnxsoft123',
'full_name': 'GNXSoft Admin',
'phone': '+1 (555) 111-2222',
'role': 'admin',
'currency': 'EUR',
'is_active': True
},
{
'email': 'admin@gnxsoft.com',
'password': 'admin123',
'full_name': 'Administrator',
'phone': '+1 (555) 222-3333',
'role': 'admin',
'currency': 'EUR',
'is_active': True
},
{
'email': 'staff@gnxsoft.com',
'password': 'staff123',
'full_name': 'Staff Member',
'phone': '+1 (555) 333-4444',
'role': 'staff',
'currency': 'EUR',
'is_active': True
},
{
'email': 'customer@gnxsoft.com',
'password': 'customer123',
'full_name': 'Customer User',
'phone': '+1 (555) 444-5555',
'role': 'customer',
'currency': 'EUR',
'is_active': True
},
{
'email': 'john.doe@gnxsoft.com',
'password': 'customer123',
'full_name': 'John Doe',
'phone': '+1 (555) 555-6666',
'role': 'customer',
'currency': 'USD',
'is_active': True
},
{
'email': 'jane.smith@gnxsoft.com',
'password': 'customer123',
'full_name': 'Jane Smith',
'phone': '+1 (555) 666-7777',
'role': 'customer',
'currency': 'EUR',
'is_active': True
},
{
'email': 'robert.wilson@gnxsoft.com',
'password': 'customer123',
'full_name': 'Robert Wilson',
'phone': '+1 (555) 777-8888',
'role': 'customer',
'currency': 'GBP',
'is_active': True
},
{
'email': 'maria.garcia@gnxsoft.com',
'password': 'customer123',
'full_name': 'Maria Garcia',
'phone': '+1 (555) 888-9999',
'role': 'customer',
'currency': 'EUR',
'is_active': True
}
]
# Add housekeeping users if role exists
if housekeeping_role:
users_data.extend([
{
'email': 'housekeeping@gnxsoft.com',
'password': 'housekeeping123',
'full_name': 'Housekeeping Staff',
'phone': '+1 (555) 999-0000',
'role': 'housekeeping',
'currency': 'EUR',
'is_active': True
},
{
'email': 'housekeeping2@gnxsoft.com',
'password': 'housekeeping123',
'full_name': 'Housekeeping Staff 2',
'phone': '+1 (555) 999-0001',
'role': 'housekeeping',
'currency': 'EUR',
'is_active': True
}
])
role_map = {
'admin': admin_role.id,
'staff': staff_role.id,
'customer': customer_role.id
}
if housekeeping_role:
role_map['housekeeping'] = housekeeping_role.id
created_count = 0
skipped_count = 0
for user_data in users_data:
existing = db.query(User).filter(User.email == user_data['email']).first()
if existing:
print(f' ⚠️ User "{user_data["email"]}" already exists, skipping...')
skipped_count += 1
continue
password = user_data.pop('password')
role_name = user_data.pop('role')
role_id = role_map[role_name]
password_bytes = password.encode('utf-8')
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
user = User(
email=user_data['email'],
password=hashed_password,
full_name=user_data['full_name'],
phone=user_data.get('phone'),
role_id=role_id,
currency=user_data.get('currency', 'EUR'),
is_active=user_data.get('is_active', True)
)
db.add(user)
print(f' ✓ Created user: {user_data["email"]} ({role_name}) - Password: {password}')
created_count += 1
db.commit()
print(f'\n✓ Users seeded successfully!')
print(f' - Created: {created_count} user(s)')
print(f' - Skipped: {skipped_count} user(s) (already exist)')
print('=' * 80)
def main():
db = get_db()
try:
seed_users(db)
except Exception as e:
print(f'\n❌ Error: {e}')
import traceback
traceback.print_exc()
db.rollback()
finally:
db.close()
if __name__ == '__main__':
main()

Some files were not shown because too many files have changed in this diff Show More