#!/usr/bin/env node /** * Database initialization script for SmartSolTech * Creates initial admin user and sample data for PostgreSQL */ const { sequelize } = require('../config/database'); require('dotenv').config(); // Import models const { User, Service, Portfolio, SiteSettings } = require('../models'); // Configuration const ADMIN_EMAIL = process.env.ADMIN_EMAIL || 'admin@smartsoltech.kr'; const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || 'admin123456'; async function initializeDatabase() { try { console.log('πŸ”„ Connecting to PostgreSQL...'); await sequelize.authenticate(); console.log('βœ… Connected to PostgreSQL'); // Sync database (create tables) console.log('πŸ”„ Syncing database schema...'); await sequelize.sync({ force: false }); console.log('βœ… Database schema synchronized'); // Create admin user await createAdminUser(); // Create sample services await createSampleServices(); // Create sample portfolio items await createSamplePortfolio(); // Create site settings await createSiteSettings(); console.log('πŸŽ‰ Database initialization completed successfully!'); console.log(`πŸ“§ Admin login: ${ADMIN_EMAIL}`); console.log(`πŸ”‘ Admin password: ${ADMIN_PASSWORD}`); console.log('⚠️ Please change the admin password after first login!'); } catch (error) { console.error('❌ Database initialization failed:', error); process.exit(1); } finally { await sequelize.close(); console.log('πŸ”Œ Database connection closed'); process.exit(0); } } async function createAdminUser() { try { const existingAdmin = await User.findOne({ where: { email: ADMIN_EMAIL } }); if (existingAdmin) { console.log('πŸ‘€ Admin user already exists, skipping...'); return; } const adminUser = await User.create({ name: 'Administrator', email: ADMIN_EMAIL, password: ADMIN_PASSWORD, role: 'admin', isActive: true }); console.log('βœ… Admin user created successfully'); } catch (error) { console.error('❌ Error creating admin user:', error); throw error; } } async function createSampleServices() { try { const existingServices = await Service.count(); if (existingServices > 0) { console.log('πŸ› οΈ Services already exist, skipping...'); return; } const services = [ { name: 'μ›Ή 개발', description: 'ν˜„λŒ€μ μ΄κ³  λ°˜μ‘ν˜•μΈ μ›Ήμ‚¬μ΄νŠΈμ™€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•©λ‹ˆλ‹€. React, Node.js, MongoDB λ“± μ΅œμ‹  기술 μŠ€νƒμ„ ν™œμš©ν•˜μ—¬ μ„±λŠ₯κ³Ό μ‚¬μš©μž κ²½ν—˜μ„ μ΅œμ ν™”ν•©λ‹ˆλ‹€.', shortDescription: 'ν˜„λŒ€μ μ΄κ³  λ°˜μ‘ν˜• μ›Ήμ‚¬μ΄νŠΈ 및 μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 개발', icon: 'fas fa-code', category: 'development', features: [ { name: 'λ°˜μ‘ν˜• λ””μžμΈ', description: 'λͺ¨λ“  λ””λ°”μ΄μŠ€μ—μ„œ μ™„λ²½ν•˜κ²Œ μž‘λ™', included: true }, { name: 'SEO μ΅œμ ν™”', description: '검색엔진 μ΅œμ ν™”λ‘œ 더 λ§Žμ€ 방문자 유치', included: true }, { name: 'μ„±λŠ₯ μ΅œμ ν™”', description: 'λΉ λ₯Έ λ‘œλ”© 속도와 μ›ν™œν•œ μ‚¬μš©μž κ²½ν—˜', included: true }, { name: 'λ³΄μ•ˆ κ°•ν™”', description: 'μ΅œμ‹  λ³΄μ•ˆ 기술둜 μ•ˆμ „ν•œ μ›Ήμ‚¬μ΄νŠΈ', included: true }, { name: 'μœ μ§€λ³΄μˆ˜', description: '6κ°œμ›” 무료 μœ μ§€λ³΄μˆ˜ 지원', included: true } ], pricing: { basePrice: 500000, currency: 'KRW', priceType: 'project', priceRange: { min: 500000, max: 5000000 } }, estimatedTime: { min: 2, max: 8, unit: 'weeks' }, featured: true, isActive: true, order: 1, tags: ['React', 'Node.js', 'MongoDB', 'Express', 'JavaScript', 'HTML', 'CSS'] }, { name: 'λͺ¨λ°”일 μ•± 개발', description: 'iOS와 Android ν”Œλž«νΌμ„ μœ„ν•œ λ„€μ΄ν‹°λΈŒ 및 ν¬λ‘œμŠ€ν”Œλž«νΌ λͺ¨λ°”일 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•©λ‹ˆλ‹€. React Native, Flutter 등을 ν™œμš©ν•˜μ—¬ 효율적인 κ°œλ°œμ„ μ§„ν–‰ν•©λ‹ˆλ‹€.', shortDescription: 'iOS/Android λ„€μ΄ν‹°λΈŒ 및 ν¬λ‘œμŠ€ν”Œλž«νΌ μ•± 개발', icon: 'fas fa-mobile-alt', category: 'development', features: [ { name: 'ν¬λ‘œμŠ€ν”Œλž«νΌ 개발', description: 'iOS와 Android λ™μ‹œ 지원', included: true }, { name: 'λ„€μ΄ν‹°λΈŒ μ„±λŠ₯', description: 'μ΅œμ ν™”λœ μ„±λŠ₯κ³Ό μ‚¬μš©μž κ²½ν—˜', included: true }, { name: 'ν‘Έμ‹œ μ•Œλ¦Ό', description: 'μ‹€μ‹œκ°„ ν‘Έμ‹œ μ•Œλ¦Ό μ‹œμŠ€ν…œ', included: true }, { name: 'μ˜€ν”„λΌμΈ 지원', description: '인터넷 μ—°κ²° 없이도 κΈ°λ³Έ κΈ°λŠ₯ μ‚¬μš© κ°€λŠ₯', included: false }, { name: 'μ•±μŠ€ν† μ–΄ 등둝', description: 'μ•±μŠ€ν† μ–΄ 및 ν”Œλ ˆμ΄μŠ€ν† μ–΄ 등둝 지원', included: true } ], pricing: { basePrice: 800000, currency: 'KRW', priceType: 'project', priceRange: { min: 800000, max: 8000000 } }, estimatedTime: { min: 4, max: 16, unit: 'weeks' }, featured: true, isActive: true, order: 2, tags: ['React Native', 'Flutter', 'iOS', 'Android', 'Swift', 'Kotlin', 'JavaScript'] }, { name: 'UI/UX λ””μžμΈ', description: 'μ‚¬μš©μž μ€‘μ‹¬μ˜ 직관적이고 μ•„λ¦„λ‹€μš΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό λ””μžμΈν•©λ‹ˆλ‹€. μ‚¬μš©μž κ²½ν—˜ 연ꡬ와 ν”„λ‘œν† νƒ€μ΄ν•‘μ„ 톡해 졜적의 λ””μžμΈ μ†”λ£¨μ…˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.', shortDescription: 'μ‚¬μš©μž μ€‘μ‹¬μ˜ 직관적이고 μ•„λ¦„λ‹€μš΄ μΈν„°νŽ˜μ΄μŠ€ λ””μžμΈ', icon: 'fas fa-palette', category: 'design', features: [ { name: 'μ‚¬μš©μž κ²½ν—˜ 연ꡬ', description: 'νƒ€κ²Ÿ μ‚¬μš©μž 뢄석 및 페λ₯΄μ†Œλ‚˜ μ„€μ •', included: true }, { name: 'μ™€μ΄μ–΄ν”„λ ˆμž„', description: '정보 ꡬ쑰와 λ ˆμ΄μ•„μ›ƒ 섀계', included: true }, { name: 'ν”„λ‘œν† νƒ€μ΄ν•‘', description: 'μΈν„°λž™ν‹°λΈŒ ν”„λ‘œν† νƒ€μž… μ œμž‘', included: true }, { name: 'λΉ„μ£Όμ–Ό λ””μžμΈ', description: 'λΈŒλžœλ“œμ— λ§žλŠ” μ‹œκ°μ  λ””μžμΈ', included: true }, { name: 'λ””μžμΈ μ‹œμŠ€ν…œ', description: 'μΌκ΄€λœ λ””μžμΈμ„ μœ„ν•œ κ°€μ΄λ“œλΌμΈ', included: false } ], pricing: { basePrice: 300000, currency: 'KRW', priceType: 'project', priceRange: { min: 300000, max: 2000000 } }, estimatedTime: { min: 1, max: 6, unit: 'weeks' }, featured: true, isActive: true, order: 3, tags: ['Figma', 'Sketch', 'Adobe XD', 'Photoshop', 'Illustrator', 'Prototyping'] }, { name: 'λ””μ§€ν„Έ λ§ˆμΌ€νŒ…', description: 'SEO, μ†Œμ…œλ―Έλ””μ–΄ λ§ˆμΌ€νŒ…, 온라인 κ΄‘κ³ λ₯Ό 톡해 λ””μ§€ν„Έ λ§ˆμΌ€νŒ… μ „λž΅μ„ μˆ˜λ¦½ν•˜κ³  μ‹€ν–‰ν•©λ‹ˆλ‹€. 데이터 뢄석을 ν†΅ν•œ 지속적인 μ΅œμ ν™”λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.', shortDescription: 'SEO, μ†Œμ…œλ―Έλ””μ–΄, 온라인 κ΄‘κ³ λ₯Ό ν†΅ν•œ λ””μ§€ν„Έ λ§ˆμΌ€νŒ…', icon: 'fas fa-chart-line', category: 'marketing', features: [ { name: 'SEO μ΅œμ ν™”', description: '검색엔진 μƒμœ„ λ…ΈμΆœμ„ μœ„ν•œ μ΅œμ ν™”', included: true }, { name: 'μ†Œμ…œλ―Έλ””μ–΄ 관리', description: '페이슀뢁, μΈμŠ€νƒ€κ·Έλž¨, 유튜브 관리', included: true }, { name: 'ꡬ글 κ΄‘κ³ ', description: 'ꡬ글 μ• μ¦ˆλ₯Ό ν†΅ν•œ νƒ€κ²Ÿ κ΄‘κ³ ', included: true }, { name: 'μ½˜ν…μΈ  λ§ˆμΌ€νŒ…', description: 'λΈ”λ‘œκ·Έ 및 μ½˜ν…μΈ  μ œμž‘', included: false }, { name: '뢄석 및 λ¦¬ν¬νŒ…', description: 'λ§ˆμΌ€νŒ… μ„±κ³Ό 뢄석 및 λ³΄κ³ μ„œ', included: true } ], pricing: { basePrice: 200000, currency: 'KRW', priceType: 'project', priceRange: { min: 200000, max: 1500000 } }, estimatedTime: { min: 2, max: 12, unit: 'weeks' }, featured: true, isActive: true, order: 4, tags: ['SEO', 'Google Ads', 'Facebook Ads', 'Analytics', 'Social Media', 'Content Marketing'] }, { name: 'λΈŒλžœλ”©', description: 'κΈ°μ—…μ˜ 정체성을 λ°˜μ˜ν•˜λŠ” 둜고, λΈŒλžœλ“œ κ°€μ΄λ“œλΌμΈ, λ§ˆμΌ€νŒ… 자료λ₯Ό λ””μžμΈν•©λ‹ˆλ‹€. μΌκ΄€λœ λΈŒλžœλ“œ μ΄λ―Έμ§€λ‘œ λΈŒλžœλ“œ κ°€μΉ˜λ₯Ό λ†’μž…λ‹ˆλ‹€.', shortDescription: '둜고, λΈŒλžœλ“œ κ°€μ΄λ“œλΌμΈ, λ§ˆμΌ€νŒ… 자료 λ””μžμΈ', icon: 'fas fa-copyright', category: 'design', features: [ { name: '둜고 λ””μžμΈ', description: 'κΈ°μ—… 정체성을 λ°˜μ˜ν•œ 둜고 μ œμž‘', included: true }, { name: 'λΈŒλžœλ“œ κ°€μ΄λ“œλΌμΈ', description: '색상, 폰트, μ‚¬μš©λ²• κ°€μ΄λ“œ', included: true }, { name: 'λͺ…함 λ””μžμΈ', description: 'λΈŒλžœλ“œμ— λ§žλŠ” λͺ…함 λ””μžμΈ', included: true }, { name: 'λΈŒλ‘œμŠˆμ–΄ λ””μžμΈ', description: 'νšŒμ‚¬ μ†Œκ°œ λΈŒλ‘œμŠˆμ–΄ μ œμž‘', included: false }, { name: 'μ›Ή λΈŒλžœλ”©', description: 'μ›Ήμ‚¬μ΄νŠΈ λΈŒλžœλ”© μš”μ†Œ 적용', included: false } ], pricing: { basePrice: 400000, currency: 'KRW', priceType: 'project', priceRange: { min: 400000, max: 2500000 } }, estimatedTime: { min: 2, max: 8, unit: 'weeks' }, featured: false, isActive: true, order: 5, tags: ['Logo Design', 'Brand Identity', 'Graphic Design', 'Corporate Design'] }, { name: '기술 μ»¨μ„€νŒ…', description: 'κΈ°μ—…μ˜ λ””μ§€ν„Έ μ „ν™˜κ³Ό 기술 λ„μž…μ„ μœ„ν•œ 전문적인 μ»¨μ„€νŒ…μ„ μ œκ³΅ν•©λ‹ˆλ‹€. 기술 μ•„ν‚€ν…μ²˜ 섀계뢀터 κ΅¬ν˜„ μ „λž΅κΉŒμ§€ ν¬κ΄„μ μœΌλ‘œ μ§€μ›ν•©λ‹ˆλ‹€.', shortDescription: 'λ””μ§€ν„Έ μ „ν™˜ 및 기술 λ„μž…μ„ μœ„ν•œ μ „λ¬Έ μ»¨μ„€νŒ…', icon: 'fas fa-lightbulb', category: 'consulting', features: [ { name: '기술 뢄석', description: 'ν˜„μž¬ 기술 μŠ€νƒ 뢄석 및 κ°œμ„ μ•ˆ μ œμ‹œ', included: true }, { name: 'μ•„ν‚€ν…μ²˜ 섀계', description: 'ν™•μž₯ κ°€λŠ₯ν•œ μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜ 섀계', included: true }, { name: '개발 ν”„λ‘œμ„ΈμŠ€ κ°œμ„ ', description: '효율적인 개발 μ›Œν¬ν”Œλ‘œμš° ꡬ좕', included: true }, { name: 'νŒ€ ꡐ윑', description: 'κ°œλ°œνŒ€ λŒ€μƒ 기술 ꡐ윑', included: false }, { name: '지속적인 지원', description: 'ν”„λ‘œμ νŠΈ μ™„λ£Œ ν›„ 지속적인 기술 지원', included: false } ], pricing: { basePrice: 150000, currency: 'KRW', priceType: 'hourly', priceRange: { min: 150000, max: 500000 } }, estimatedTime: { min: 1, max: 4, unit: 'weeks' }, featured: false, isActive: true, order: 6, tags: ['Architecture', 'Strategy', 'Process', 'Training', 'Consultation'] } ]; await Service.bulkCreate(services); console.log('βœ… Sample services created successfully'); } catch (error) { console.error('❌ Error creating sample services:', error); throw error; } } async function createSamplePortfolio() { try { const existingPortfolio = await Portfolio.count(); if (existingPortfolio > 0) { console.log('🎨 Portfolio items already exist, skipping...'); return; } const portfolioItems = [ { title: 'E-commerce ν”Œλž«νΌ', description: 'ν˜„λŒ€μ μΈ 온라인 μ‡Όν•‘λͺ° ν”Œλž«νΌμ„ κ°œλ°œν–ˆμŠ΅λ‹ˆλ‹€. React와 Node.jsλ₯Ό ν™œμš©ν•˜μ—¬ 높은 μ„±λŠ₯κ³Ό μ‚¬μš©μž κ²½ν—˜μ„ μ œκ³΅ν•˜λ©°, 결제 μ‹œμŠ€ν…œκ³Ό 재고 관리 κΈ°λŠ₯을 ν¬ν•¨ν•©λ‹ˆλ‹€.', shortDescription: 'λ°˜μ‘ν˜• 온라인 μ‡Όν•‘λͺ° ν”Œλž«νΌ 개발', category: 'web-development', technologies: ['React', 'Node.js', 'MongoDB', 'Express', 'Stripe', 'AWS'], images: [ { url: '/images/portfolio/ecommerce-1.jpg', alt: 'E-commerce λ©”μΈνŽ˜μ΄μ§€', isPrimary: true }, { url: '/images/portfolio/ecommerce-2.jpg', alt: 'μƒν’ˆ μƒμ„ΈνŽ˜μ΄μ§€', isPrimary: false }, { url: '/images/portfolio/ecommerce-3.jpg', alt: 'μž₯λ°”κ΅¬λ‹ˆ νŽ˜μ΄μ§€', isPrimary: false } ], clientName: 'νŒ¨μ…˜ λΈŒλžœλ“œ ABC', projectUrl: 'https://example-ecommerce.com', status: 'completed', featured: true, publishedAt: new Date('2024-01-15'), completedAt: new Date('2024-01-10'), isPublished: true, viewCount: 150, likes: 25, order: 1, seo: { metaTitle: 'E-commerce ν”Œλž«νΌ 개발 ν”„λ‘œμ νŠΈ', metaDescription: 'ν˜„λŒ€μ μΈ 온라인 μ‡Όν•‘λͺ° ν”Œλž«νΌ 개발 사둀', keywords: ['E-commerce', 'React', 'Node.js', 'μ˜¨λΌμΈμ‡Όν•‘λͺ°'] } }, { title: 'λͺ¨λ°”일 ν”ΌνŠΈλ‹ˆμŠ€ μ•±', description: 'React Nativeλ₯Ό μ‚¬μš©ν•˜μ—¬ ν¬λ‘œμŠ€ν”Œλž«νΌ ν”ΌνŠΈλ‹ˆμŠ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν–ˆμŠ΅λ‹ˆλ‹€. μš΄λ™ κ³„νš, 칼둜리 좔적, μ†Œμ…œ κΈ°λŠ₯을 ν¬ν•¨ν•˜μ—¬ μ‚¬μš©μžλ“€μ˜ κ±΄κ°•ν•œ λΌμ΄ν”„μŠ€νƒ€μΌμ„ μ§€μ›ν•©λ‹ˆλ‹€.', shortDescription: '건강 관리λ₯Ό μœ„ν•œ ν¬λ‘œμŠ€ν”Œλž«νΌ λͺ¨λ°”일 μ•±', category: 'mobile-app', technologies: ['React Native', 'Redux', 'Firebase', 'Node.js', 'PostgreSQL'], images: [ { url: '/images/portfolio/fitness-1.jpg', alt: 'ν”ΌνŠΈλ‹ˆμŠ€ μ•± 메인화면', isPrimary: true }, { url: '/images/portfolio/fitness-2.jpg', alt: 'μš΄λ™ κ³„νš ν™”λ©΄', isPrimary: false }, { url: '/images/portfolio/fitness-3.jpg', alt: '톡계 ν™”λ©΄', isPrimary: false } ], clientName: 'ν—¬μŠ€μΌ€μ–΄ μŠ€νƒ€νŠΈμ—… FIT', status: 'completed', featured: true, publishedAt: new Date('2024-02-20'), completedAt: new Date('2024-02-15'), isPublished: true, viewCount: 200, likes: 35, order: 2, seo: { metaTitle: 'λͺ¨λ°”일 ν”ΌνŠΈλ‹ˆμŠ€ μ•± 개발 ν”„λ‘œμ νŠΈ', metaDescription: 'React Native둜 κ°œλ°œν•œ ν¬λ‘œμŠ€ν”Œλž«νΌ ν”ΌνŠΈλ‹ˆμŠ€ μ•±', keywords: ['Mobile App', 'React Native', 'Fitness', 'ν—¬μŠ€μΌ€μ–΄'] } }, { title: 'κΈ°μ—… μ›Ήμ‚¬μ΄νŠΈ 리뉴얼', description: 'κΈ°μ—…μ˜ λΈŒλžœλ“œ 아이덴티티λ₯Ό λ°˜μ˜ν•œ μ›Ήμ‚¬μ΄νŠΈ 리뉴얼 ν”„λ‘œμ νŠΈμž…λ‹ˆλ‹€. μ‚¬μš©μž κ²½ν—˜μ„ κ°œμ„ ν•˜κ³  λͺ¨λ˜ν•œ λ””μžμΈμ„ μ μš©ν•˜μ—¬ λΈŒλžœλ“œ κ°€μΉ˜λ₯Ό λ†’μ˜€μŠ΅λ‹ˆλ‹€.', shortDescription: 'λΈŒλžœλ“œ 아이덴티티λ₯Ό λ°˜μ˜ν•œ κΈ°μ—… μ›Ήμ‚¬μ΄νŠΈ 리뉴얼', category: 'ui-ux-design', technologies: ['Figma', 'React', 'Sass', 'Framer Motion', 'Contentful'], images: [ { url: '/images/portfolio/corporate-1.jpg', alt: 'κΈ°μ—… μ›Ήμ‚¬μ΄νŠΈ λ©”μΈνŽ˜μ΄μ§€', isPrimary: true }, { url: '/images/portfolio/corporate-2.jpg', alt: 'νšŒμ‚¬μ†Œκ°œ νŽ˜μ΄μ§€', isPrimary: false }, { url: '/images/portfolio/corporate-3.jpg', alt: 'μ„œλΉ„μŠ€ νŽ˜μ΄μ§€', isPrimary: false } ], clientName: '기술 κΈ°μ—… TechCorp', projectUrl: 'https://example-corp.com', status: 'completed', featured: true, publishedAt: new Date('2024-03-10'), completedAt: new Date('2024-03-05'), isPublished: true, viewCount: 120, likes: 18, order: 3, seo: { metaTitle: 'κΈ°μ—… μ›Ήμ‚¬μ΄νŠΈ 리뉴얼 ν”„λ‘œμ νŠΈ', metaDescription: 'λͺ¨λ˜ν•œ λ””μžμΈκ³Ό ν–₯μƒλœ UX의 κΈ°μ—… μ›Ήμ‚¬μ΄νŠΈ', keywords: ['Web Design', 'Corporate', 'UI/UX', 'μ›Ήμ‚¬μ΄νŠΈλ¦¬λ‰΄μ–Ό'] } }, { title: 'λ ˆμŠ€ν† λž‘ μ˜ˆμ•½ μ‹œμŠ€ν…œ', description: 'λ ˆμŠ€ν† λž‘μ„ μœ„ν•œ 온라인 μ˜ˆμ•½ μ‹œμŠ€ν…œμ„ κ°œλ°œν–ˆμŠ΅λ‹ˆλ‹€. μ‹€μ‹œκ°„ ν…Œμ΄λΈ” ν˜„ν™©, μ˜ˆμ•½ 관리, 고객 관리 κΈ°λŠ₯을 ν¬ν•¨ν•˜μ—¬ λ ˆμŠ€ν† λž‘ 운영 νš¨μœ¨μ„±μ„ λ†’μ˜€μŠ΅λ‹ˆλ‹€.', shortDescription: 'μ‹€μ‹œκ°„ ν…Œμ΄λΈ” μ˜ˆμ•½ 및 관리 μ‹œμŠ€ν…œ', category: 'web-development', technologies: ['Vue.js', 'Laravel', 'MySQL', 'Socket.io', 'Bootstrap'], images: [ { url: '/images/portfolio/restaurant-1.jpg', alt: 'μ˜ˆμ•½ μ‹œμŠ€ν…œ 메인', isPrimary: true }, { url: '/images/portfolio/restaurant-2.jpg', alt: 'μ˜ˆμ•½ ν˜„ν™© 관리', isPrimary: false } ], clientName: 'λ ˆμŠ€ν† λž‘ λΈλ¦¬μ…”μŠ€', status: 'completed', featured: false, publishedAt: new Date('2024-04-05'), completedAt: new Date('2024-04-01'), isPublished: true, viewCount: 85, likes: 12, order: 4, seo: { metaTitle: 'λ ˆμŠ€ν† λž‘ μ˜ˆμ•½ μ‹œμŠ€ν…œ 개발', metaDescription: 'μ‹€μ‹œκ°„ ν…Œμ΄λΈ” μ˜ˆμ•½ 및 관리 μ›Ή μ‹œμŠ€ν…œ', keywords: ['Reservation System', 'Vue.js', 'Laravel', 'μ˜ˆμ•½μ‹œμŠ€ν…œ'] } }, { title: 'ꡐ윑 ν”Œλž«νΌ μ•±', description: '온라인 κ΅μœ‘μ„ μœ„ν•œ λͺ¨λ°”일 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μž…λ‹ˆλ‹€. λ™μ˜μƒ κ°•μ˜, ν€΄μ¦ˆ, 진도 관리 κΈ°λŠ₯을 ν¬ν•¨ν•˜μ—¬ 효과적인 ν•™μŠ΅ ν™˜κ²½μ„ μ œκ³΅ν•©λ‹ˆλ‹€.', shortDescription: '온라인 ν•™μŠ΅μ„ μœ„ν•œ ꡐ윑 ν”Œλž«νΌ λͺ¨λ°”일 μ•±', category: 'mobile-app', technologies: ['Flutter', 'Dart', 'Firebase', 'FFmpeg', 'AWS S3'], images: [ { url: '/images/portfolio/education-1.jpg', alt: 'ꡐ윑 μ•± 메인화면', isPrimary: true }, { url: '/images/portfolio/education-2.jpg', alt: 'κ°•μ˜ μž¬μƒ ν™”λ©΄', isPrimary: false } ], clientName: '온라인 ꡐ윑 κΈ°μ—… EduTech', status: 'completed', featured: false, publishedAt: new Date('2024-05-12'), completedAt: new Date('2024-05-08'), isPublished: true, viewCount: 95, likes: 20, order: 5, seo: { metaTitle: 'ꡐ윑 ν”Œλž«νΌ λͺ¨λ°”일 μ•± 개발', metaDescription: 'Flutter둜 κ°œλ°œν•œ 온라인 ꡐ윑 λͺ¨λ°”일 μ•±', keywords: ['Education App', 'Flutter', 'E-learning', 'κ΅μœ‘μ•±'] } }, { title: 'IoT λŒ€μ‹œλ³΄λ“œ', description: 'IoT λ””λ°”μ΄μŠ€λ“€μ„ λͺ¨λ‹ˆν„°λ§ν•˜κ³  μ œμ–΄ν•  수 μžˆλŠ” μ›Ή λŒ€μ‹œλ³΄λ“œλ₯Ό κ°œλ°œν–ˆμŠ΅λ‹ˆλ‹€. μ‹€μ‹œκ°„ 데이터 μ‹œκ°ν™”μ™€ μ•Œλ¦Ό κΈ°λŠ₯을 ν¬ν•¨ν•©λ‹ˆλ‹€.', shortDescription: 'IoT λ””λ°”μ΄μŠ€ λͺ¨λ‹ˆν„°λ§ 및 μ œμ–΄ μ›Ή λŒ€μ‹œλ³΄λ“œ', category: 'web-development', technologies: ['React', 'D3.js', 'Node.js', 'MQTT', 'InfluxDB', 'Docker'], images: [ { url: '/images/portfolio/iot-1.jpg', alt: 'IoT λŒ€μ‹œλ³΄λ“œ 메인', isPrimary: true } ], clientName: 'IoT μ†”λ£¨μ…˜ κΈ°μ—… SmartDevice', status: 'in-progress', featured: false, publishedAt: new Date('2024-06-01'), isPublished: true, viewCount: 45, likes: 8, order: 6, seo: { metaTitle: 'IoT λŒ€μ‹œλ³΄λ“œ 개발 ν”„λ‘œμ νŠΈ', metaDescription: 'μ‹€μ‹œκ°„ IoT λ””λ°”μ΄μŠ€ λͺ¨λ‹ˆν„°λ§ μ›Ή λŒ€μ‹œλ³΄λ“œ', keywords: ['IoT', 'Dashboard', 'Real-time', 'Monitoring'] } } ]; await Portfolio.bulkCreate(portfolioItems); console.log('βœ… Sample portfolio items created successfully'); } catch (error) { console.error('❌ Error creating sample portfolio:', error); throw error; } } async function createSiteSettings() { try { const existingSettings = await SiteSettings.findOne(); if (existingSettings) { console.log('βš™οΈ Site settings already exist, skipping...'); return; } const settings = await SiteSettings.create({ siteName: 'SmartSolTech', siteDescription: 'ν˜μ‹ μ μΈ 기술 μ†”λ£¨μ…˜μœΌλ‘œ λΉ„μ¦ˆλ‹ˆμŠ€μ˜ μ„±μž₯을 μ§€μ›ν•©λ‹ˆλ‹€', logo: '/images/logo.png', favicon: '/images/favicon.ico', contact: { email: 'info@smartsoltech.kr', phone: '+82-10-1234-5678', address: 'Seoul, South Korea' }, social: { facebook: 'https://facebook.com/smartsoltech', twitter: 'https://twitter.com/smartsoltech', linkedin: 'https://linkedin.com/company/smartsoltech', instagram: 'https://instagram.com/smartsoltech', github: 'https://github.com/smartsoltech' }, telegram: { isEnabled: false }, seo: { metaTitle: 'SmartSolTech - ν˜μ‹ μ μΈ 기술 μ†”λ£¨μ…˜', metaDescription: 'μ›Ή 개발, λͺ¨λ°”일 μ•±, UI/UX λ””μžμΈ, λ””μ§€ν„Έ λ§ˆμΌ€νŒ… μ „λ¬Έ κΈ°μ—…. ν•œκ΅­μ—μ„œ 졜고의 기술 μ†”λ£¨μ…˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.', keywords: 'μ›Ή 개발, λͺ¨λ°”일 μ•±, UI/UX λ””μžμΈ, λ””μ§€ν„Έ λ§ˆμΌ€νŒ…, 기술 μ†”λ£¨μ…˜, ν•œκ΅­, SmartSolTech' }, hero: { title: 'Smart Technology Solutions', subtitle: 'ν˜μ‹ μ μΈ μ›Ή 개발, λͺ¨λ°”일 μ•±, UI/UX λ””μžμΈμœΌλ‘œ λΉ„μ¦ˆλ‹ˆμŠ€μ˜ λ””μ§€ν„Έ μ „ν™˜μ„ μ΄λŒμ–΄κ°‘λ‹ˆλ‹€', backgroundImage: '/images/hero-bg.jpg', ctaText: 'ν”„λ‘œμ νŠΈ μ‹œμž‘ν•˜κΈ°', ctaLink: '/contact' }, about: { title: 'SmartSolTech μ†Œκ°œ', description: 'μš°λ¦¬λŠ” μ΅œμ‹  기술과 창의적인 μ•„μ΄λ””μ–΄λ‘œ 고객의 λΉ„μ¦ˆλ‹ˆμŠ€ μ„±μž₯을 μ§€μ›ν•˜λŠ” μ „λ¬Έ κ°œλ°œνŒ€μž…λ‹ˆλ‹€. μ›Ή κ°œλ°œλΆ€ν„° λͺ¨λ°”일 μ•±, UI/UX λ””μžμΈκΉŒμ§€ 포괄적인 λ””μ§€ν„Έ μ†”λ£¨μ…˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€.', image: '/images/about.jpg' }, maintenance: { isEnabled: false, message: 'ν˜„μž¬ μ‹œμŠ€ν…œ 점검 μ€‘μž…λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ 접속해 μ£Όμ„Έμš”.' } }); console.log('βœ… Site settings created successfully'); } catch (error) { console.error('❌ Error creating site settings:', error); throw error; } } // Run the initialization if (require.main === module) { initializeDatabase(); } module.exports = { initializeDatabase, createAdminUser, createSampleServices, createSamplePortfolio, createSiteSettings };