""" 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()