340 lines
12 KiB
Python
340 lines
12 KiB
Python
"""
|
|
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()
|
|
|