From eca5cba85806b4cf855d16d8a7a40bf160a25850 Mon Sep 17 00:00:00 2001 From: innoavvlasov Date: Mon, 27 Oct 2025 19:37:21 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BC=D0=B8=D0=B3=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/routers/procurement/index.js | 31 ++++- server/routers/procurement/routes/search.js | 14 +- .../procurement/scripts/init-database.js | 74 +++++++++++ .../procurement/scripts/migrate-companies.js | 124 ++++++++++++++++++ .../procurement/scripts/migrate-messages.js | 12 +- .../procurement/scripts/recreate-test-user.js | 72 +++++----- .../procurement/scripts/run-migrations.js | 105 +++++++++++++++ .../procurement/scripts/test-logging.js | 61 --------- .../procurement/scripts/validate-companies.js | 93 +++++++++++++ 9 files changed, 477 insertions(+), 109 deletions(-) create mode 100644 server/routers/procurement/scripts/init-database.js create mode 100644 server/routers/procurement/scripts/migrate-companies.js create mode 100644 server/routers/procurement/scripts/run-migrations.js delete mode 100644 server/routers/procurement/scripts/test-logging.js create mode 100644 server/routers/procurement/scripts/validate-companies.js diff --git a/server/routers/procurement/index.js b/server/routers/procurement/index.js index e08a238..1f29b3d 100644 --- a/server/routers/procurement/index.js +++ b/server/routers/procurement/index.js @@ -2,6 +2,7 @@ const express = require('express'); const cors = require('cors'); const dotenv = require('dotenv'); const connectDB = require('./config/db'); +const { runMigrations } = require('./scripts/run-migrations'); // Загрузить переменные окружения dotenv.config(); @@ -29,11 +30,32 @@ const homeRoutes = require('./routes/home'); const app = express(); -// Подключить MongoDB при инициализации +// Подключить MongoDB и запустить миграции при инициализации let dbConnected = false; -connectDB().then(() => { - dbConnected = true; -}); +let migrationsCompleted = false; + +const initializeApp = async () => { + try { + await connectDB().then(() => { + dbConnected = true; + }); + + // Запустить миграции после успешного подключения + if (dbConnected) { + try { + await runMigrations(); + migrationsCompleted = true; + } catch (migrationError) { + console.error('⚠️ Migrations failed but app will continue:', migrationError.message); + } + } + } catch (err) { + console.error('Error during app initialization:', err); + } +}; + +// Запустить инициализацию +initializeApp(); // Middleware app.use(cors()); @@ -68,6 +90,7 @@ app.get('/health', (req, res) => { status: 'ok', api: 'running', database: dbConnected ? 'mongodb' : 'mock', + migrations: migrationsCompleted ? 'completed' : 'pending', timestamp: new Date().toISOString() }); }); diff --git a/server/routers/procurement/routes/search.js b/server/routers/procurement/routes/search.js index 84e38e6..b983e7f 100644 --- a/server/routers/procurement/routes/search.js +++ b/server/routers/procurement/routes/search.js @@ -127,8 +127,14 @@ router.get('/', verifyToken, async (req, res) => { log('[Search] Industry codes:', industryList, 'Mapped to:', dbIndustries); if (dbIndustries.length > 0) { - filters.push({ industry: { $in: dbIndustries } }); - log('[Search] Added industry filter:', { industry: { $in: dbIndustries } }); + // Handle both string and array industry values + filters.push({ + $or: [ + { industry: { $in: dbIndustries } }, + { industry: { $elemMatch: { $in: dbIndustries } } } + ] + }); + log('[Search] Added industry filter:', { $or: [{ industry: { $in: dbIndustries } }, { industry: { $elemMatch: { $in: dbIndustries } } }] }); } else { log('[Search] No industries mapped! Codes were:', industryList); } @@ -213,8 +219,10 @@ router.get('/', verifyToken, async (req, res) => { page: pageNum, totalPages: Math.ceil(total / limitNum), _debug: { + requestParams: { query, industries, companySize, geography, minRating, hasReviews, hasAcceptedDocs, sortBy, sortOrder }, filter: JSON.stringify(filter), - industriesReceived: industries + filtersCount: filters.length, + appliedFilters: filters.map(f => JSON.stringify(f)) } }); } catch (error) { diff --git a/server/routers/procurement/scripts/init-database.js b/server/routers/procurement/scripts/init-database.js new file mode 100644 index 0000000..819bbff --- /dev/null +++ b/server/routers/procurement/scripts/init-database.js @@ -0,0 +1,74 @@ +const mongoose = require('mongoose'); +const { migrateCompanies } = require('./migrate-companies'); +require('dotenv').config({ path: '../../.env' }); + +const mongoUrl = process.env.MONGODB_URI || 'mongodb://localhost:27017/procurement_db'; + +// Migration history model +const migrationSchema = new mongoose.Schema({ + name: { type: String, unique: true, required: true }, + executedAt: { type: Date, default: Date.now }, + status: { type: String, enum: ['completed', 'failed'], default: 'completed' }, + message: String +}, { collection: 'migrations' }); + +const Migration = mongoose.model('Migration', migrationSchema); + +async function initializeDatabase() { + try { + console.log('[Init] Connecting to MongoDB...'); + await mongoose.connect(mongoUrl, { + useNewUrlParser: true, + useUnifiedTopology: true, + serverSelectionTimeoutMS: 5000, + connectTimeoutMS: 5000, + }); + console.log('[Init] Connected to MongoDB\n'); + + // Check if migrations already ran + const migrateCompaniesRan = await Migration.findOne({ name: 'migrate-companies' }); + + if (!migrateCompaniesRan) { + console.log('[Init] Running migrate-companies migration...'); + try { + await migrateCompanies(); + + // Record successful migration + await Migration.create({ + name: 'migrate-companies', + status: 'completed', + message: 'Company data migration completed successfully' + }); + + console.log('[Init] ✅ migrate-companies recorded in database\n'); + } catch (err) { + // Record failed migration + await Migration.create({ + name: 'migrate-companies', + status: 'failed', + message: err.message + }); + console.error('[Init] ❌ migrate-companies failed:', err.message); + } + } else { + console.log('[Init] ℹ️ migrate-companies already executed:', migrateCompaniesRan.executedAt); + console.log('[Init] Skipping migration...\n'); + } + + await mongoose.connection.close(); + console.log('[Init] Database initialization complete\n'); + } catch (err) { + console.error('[Init] ❌ Error during database initialization:', err.message); + process.exit(1); + } +} + +module.exports = initializeDatabase; + +// Run directly if called as script +if (require.main === module) { + initializeDatabase().catch(err => { + console.error('Initialization failed:', err); + process.exit(1); + }); +} diff --git a/server/routers/procurement/scripts/migrate-companies.js b/server/routers/procurement/scripts/migrate-companies.js new file mode 100644 index 0000000..dd4cf64 --- /dev/null +++ b/server/routers/procurement/scripts/migrate-companies.js @@ -0,0 +1,124 @@ +const mongoose = require('mongoose'); +const Company = require('../models/Company'); +require('dotenv').config({ path: '../../.env' }); + +const industryMap = { + 'it': 'IT', + 'finance': 'Финансы', + 'manufacturing': 'Производство', + 'construction': 'Строительство', + 'retail': 'Розничная торговля', + 'wholesale': 'Оптовая торговля', + 'logistics': 'Логистика', + 'healthcare': 'Здравоохранение', + 'education': 'Образование', + 'consulting': 'Консалтинг', + 'marketing': 'Маркетинг', + 'realestate': 'Недвижимость', + 'food': 'Пищевая промышленность', + 'agriculture': 'Сельское хозяйство', + 'energy': 'Энергетика', + 'telecom': 'Телекоммуникации', + 'media': 'Медиа', + 'tourism': 'Туризм', + 'legal': 'Юридические услуги', + 'other': 'Другое' +}; + +const validIndustries = Object.values(industryMap); + +const industryAliases = { + 'Торговля': 'Розничная торговля', + 'торговля': 'Розничная торговля', + 'Trade': 'Розничная торговля' +}; + +async function migrateCompanies() { + try { + const allCompanies = await Company.find().exec(); + console.log(`[Migration] Found ${allCompanies.length} companies to process`); + + let fixedCount = 0; + let errorCount = 0; + + for (const company of allCompanies) { + let needsUpdate = false; + let updates = {}; + + // Check and fix industry field + if (company.industry) { + if (Array.isArray(company.industry)) { + console.log(`[FIX] ${company.fullName}: industry is array, converting to string`); + updates.industry = company.industry[0] || 'Другое'; + needsUpdate = true; + } else if (!validIndustries.includes(company.industry)) { + const mapped = industryAliases[company.industry]; + if (mapped) { + console.log(`[FIX] ${company.fullName}: "${company.industry}" → "${mapped}"`); + updates.industry = mapped; + needsUpdate = true; + } else { + console.log(`[WARN] ${company.fullName}: unknown industry "${company.industry}"`); + } + } + } + + // Check and fix companySize field + if (company.companySize && Array.isArray(company.companySize)) { + console.log(`[FIX] ${company.fullName}: companySize is array, converting to string`); + updates.companySize = company.companySize[0] || ''; + needsUpdate = true; + } + + if (needsUpdate) { + try { + await Company.updateOne({ _id: company._id }, { $set: updates }); + fixedCount++; + console.log(` ✅ Updated`); + } catch (err) { + console.error(` ❌ Error: ${err.message}`); + errorCount++; + } + } + } + + console.log('\n[Migration] === MIGRATION SUMMARY ==='); + console.log(`[Migration] Total companies: ${allCompanies.length}`); + console.log(`[Migration] Fixed: ${fixedCount}`); + console.log(`[Migration] Errors: ${errorCount}`); + + if (fixedCount === 0 && errorCount === 0) { + console.log('[Migration] ✅ No migration needed - all data is valid!'); + } else if (errorCount === 0) { + console.log('[Migration] ✅ Migration completed successfully!'); + } else { + console.log('[Migration] ⚠️ Migration completed with errors.'); + } + } catch (err) { + console.error('[Migration] ❌ Error:', err.message); + throw err; + } +} + +module.exports = { + migrateCompanies: migrateCompanies +}; + +// Run directly if called as script +if (require.main === module) { + const mongoUrl = process.env.MONGODB_URI || 'mongodb://admin:password@localhost:27017/procurement_db?authSource=admin'; + + mongoose.connect(mongoUrl, { + useNewUrlParser: true, + useUnifiedTopology: true, + serverSelectionTimeoutMS: 5000, + connectTimeoutMS: 5000, + }).then(async () => { + console.log('[Migration] Connected to MongoDB\n'); + await migrateCompanies(); + await mongoose.connection.close(); + }).catch(err => { + console.error('[Migration] ❌ Error:', err.message); + process.exit(1); + }); +} diff --git a/server/routers/procurement/scripts/migrate-messages.js b/server/routers/procurement/scripts/migrate-messages.js index d342f44..56a877e 100644 --- a/server/routers/procurement/scripts/migrate-messages.js +++ b/server/routers/procurement/scripts/migrate-messages.js @@ -86,8 +86,16 @@ async function migrateMessages() { console.log('[Migration] Disconnected from MongoDB'); } catch (err) { console.error('[Migration] ❌ Error:', err.message); - process.exit(1); + throw err; } } -migrateMessages(); +module.exports = { migrateMessages }; + +// Run directly if called as script +if (require.main === module) { + migrateMessages().catch(err => { + console.error('Migration failed:', err); + process.exit(1); + }); +} diff --git a/server/routers/procurement/scripts/recreate-test-user.js b/server/routers/procurement/scripts/recreate-test-user.js index a641bb5..211b8a6 100644 --- a/server/routers/procurement/scripts/recreate-test-user.js +++ b/server/routers/procurement/scripts/recreate-test-user.js @@ -7,32 +7,25 @@ const Company = require('../models/Company'); const recreateTestUser = async () => { try { - const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/procurement_db'; - - console.log('\n🔄 Подключение к MongoDB...'); - await mongoose.connect(mongoUri, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); - console.log('✅ Подключено к MongoDB\n'); + console.log('[Migration] Processing test user creation...'); // Удалить старого тестового пользователя - console.log('🗑️ Удаление старого тестового пользователя...'); + console.log('[Migration] Removing old test user...'); const oldUser = await User.findOne({ email: 'admin@test-company.ru' }); if (oldUser) { // Удалить связанную компанию if (oldUser.companyId) { await Company.findByIdAndDelete(oldUser.companyId); - console.log(' ✓ Старая компания удалена'); + console.log('[Migration] ✓ Old company removed'); } await User.findByIdAndDelete(oldUser._id); - console.log(' ✓ Старый пользователь удален'); + console.log('[Migration] ✓ Old user removed'); } else { - console.log(' ℹ️ Старый пользователь не найден'); + console.log('[Migration] ℹ️ Old user not found'); } // Создать новую компанию с правильной кодировкой UTF-8 - console.log('\n🏢 Создание тестовой компании...'); + console.log('[Migration] Creating test company...'); const company = await Company.create({ fullName: 'ООО "Тестовая Компания"', inn: '1234567890', @@ -47,10 +40,10 @@ const recreateTestUser = async () => { reviewsCount: 10, dealsCount: 25, }); - console.log(' ✓ Компания создана:', company.fullName); + console.log('[Migration] ✓ Company created:', company.fullName); // Создать нового пользователя с правильной кодировкой UTF-8 - console.log('\n👤 Создание тестового пользователя...'); + console.log('[Migration] Creating test user...'); const user = await User.create({ email: 'admin@test-company.ru', password: 'SecurePass123!', @@ -60,24 +53,10 @@ const recreateTestUser = async () => { phone: '+7 (999) 123-45-67', companyId: company._id, }); - console.log(' ✓ Пользователь создан:', user.firstName, user.lastName); - - // Проверка что данные сохранены правильно - console.log('\n✅ Проверка данных:'); - console.log(' Email:', user.email); - console.log(' Имя:', user.firstName); - console.log(' Фамилия:', user.lastName); - console.log(' Компания:', company.fullName); - console.log(' Должность:', user.position); - - console.log('\n✅ ГОТОВО! Тестовый пользователь создан с правильной кодировкой UTF-8'); - console.log('\n📋 Данные для входа:'); - console.log(' Email: admin@test-company.ru'); - console.log(' Пароль: SecurePass123!'); - console.log(''); + console.log('[Migration] ✓ User created:', user.firstName, user.lastName); // Обновить существующие mock компании - console.log('\n🔄 Обновление существующих mock компаний...'); + console.log('[Migration] Updating existing companies...'); const updates = [ { inn: '7707083894', updates: { companySize: '51-250', partnerGeography: ['moscow', 'russia_all'] } }, { inn: '7707083895', updates: { companySize: '500+', partnerGeography: ['moscow', 'russia_all'] } }, @@ -88,18 +67,33 @@ const recreateTestUser = async () => { for (const item of updates) { await Company.updateOne({ inn: item.inn }, { $set: item.updates }); - console.log(` ✓ Компания обновлена: INN ${item.inn}`); + console.log(`[Migration] ✓ Company updated: INN ${item.inn}`); } - await mongoose.connection.close(); - process.exit(0); + console.log('[Migration] ✅ Test user migration completed!'); } catch (error) { - console.error('\n❌ Ошибка:', error.message); - console.error(error); - process.exit(1); + console.error('[Migration] ❌ Error:', error.message); + throw error; } }; -// Запуск -recreateTestUser(); +module.exports = { recreateTestUser }; + +// Run directly if called as script +if (require.main === module) { + const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/procurement_db'; + + mongoose.connect(mongoUri, { + useNewUrlParser: true, + useUnifiedTopology: true, + }).then(async () => { + console.log('[Migration] Connected to MongoDB\n'); + await recreateTestUser(); + await mongoose.connection.close(); + process.exit(0); + }).catch(err => { + console.error('[Migration] ❌ Error:', err.message); + process.exit(1); + }); +} diff --git a/server/routers/procurement/scripts/run-migrations.js b/server/routers/procurement/scripts/run-migrations.js new file mode 100644 index 0000000..39a99c9 --- /dev/null +++ b/server/routers/procurement/scripts/run-migrations.js @@ -0,0 +1,105 @@ +const mongoose = require('mongoose'); +const { migrateCompanies } = require('./migrate-companies'); +const { migrateMessages } = require('./migrate-messages'); +const { recreateTestUser } = require('./recreate-test-user'); +require('dotenv').config(); + +const mongoUrl = process.env.MONGODB_URI || 'mongodb://localhost:27017/procurement_db'; + +// Migration history model +const migrationSchema = new mongoose.Schema({ + name: { type: String, unique: true, required: true }, + executedAt: { type: Date, default: Date.now }, + status: { type: String, enum: ['completed', 'failed'], default: 'completed' }, + message: String +}, { collection: 'migrations' }); + +const Migration = mongoose.model('Migration', migrationSchema); + +const migrations = [ + { name: 'migrate-companies', fn: migrateCompanies }, + { name: 'migrate-messages', fn: migrateMessages }, + { name: 'recreate-test-user', fn: recreateTestUser } +]; + +async function runMigrations() { + let mongooseConnected = false; + + try { + console.log('\n' + '='.repeat(60)); + console.log('🚀 Starting Database Migrations'); + console.log('='.repeat(60) + '\n'); + + console.log('[Migrations] Connecting to MongoDB...'); + await mongoose.connect(mongoUrl, { + useNewUrlParser: true, + useUnifiedTopology: true, + serverSelectionTimeoutMS: 5000, + connectTimeoutMS: 5000, + }); + mongooseConnected = true; + console.log('[Migrations] ✅ Connected to MongoDB\n'); + + for (const migration of migrations) { + console.log(`[${migration.name}] Starting...`); + + try { + // Check if already executed + const existing = await Migration.findOne({ name: migration.name }); + + if (existing) { + console.log(`[${migration.name}] ℹ️ Already executed at: ${existing.executedAt.toISOString()}`); + console.log(`[${migration.name}] Status: ${existing.status}`); + if (existing.message) console.log(`[${migration.name}] Message: ${existing.message}`); + console.log(''); + continue; + } + + // Run migration + await migration.fn(); + + // Record successful migration + await Migration.create({ + name: migration.name, + status: 'completed', + message: `${migration.name} executed successfully` + }); + + console.log(`[${migration.name}] ✅ Completed and recorded\n`); + } catch (error) { + console.error(`[${migration.name}] ❌ Error: ${error.message}\n`); + + // Record failed migration + await Migration.create({ + name: migration.name, + status: 'failed', + message: error.message + }); + } + } + + console.log('='.repeat(60)); + console.log('✅ All migrations processed'); + console.log('='.repeat(60) + '\n'); + + } catch (error) { + console.error('\n❌ Fatal migration error:', error.message); + console.error(error); + process.exit(1); + } finally { + if (mongooseConnected) { + await mongoose.connection.close(); + console.log('[Migrations] Disconnected from MongoDB\n'); + } + } +} + +module.exports = { runMigrations, Migration }; + +// Run directly if called as script +if (require.main === module) { + runMigrations().catch(err => { + console.error('Migration failed:', err); + process.exit(1); + }); +} diff --git a/server/routers/procurement/scripts/test-logging.js b/server/routers/procurement/scripts/test-logging.js deleted file mode 100644 index e914f23..0000000 --- a/server/routers/procurement/scripts/test-logging.js +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env node - -/** - * Скрипт для тестирования логирования - * - * Использование: - * node stubs/scripts/test-logging.js # Логи скрыты (DEV не установлена) - * DEV=true node stubs/scripts/test-logging.js # Логи видны - */ - -// Функция логирования из маршрутов -const log = (message, data = '') => { - if (process.env.DEV === 'true') { - if (data) { - console.log(message, data); - } else { - console.log(message); - } - } -}; - -console.log(''); -console.log('='.repeat(60)); -console.log('TEST: Логирование с переменной окружения DEV'); -console.log('='.repeat(60)); -console.log(''); - -console.log('Значение DEV:', process.env.DEV || '(не установлена)'); -console.log(''); - -// Тестируем различные логи -log('[Auth] Token verified - userId: 68fe2ccda3526c303ca06799 companyId: 68fe2ccda3526c303ca06796'); -log('[Auth] Generating token for userId:', '68fe2ccda3526c303ca06799'); -log('[BuyProducts] Found', 0, 'products for company 68fe2ccda3526c303ca06796'); -log('[Products] GET Fetching products for companyId:', '68fe2ccda3526c303ca06799'); -log('[Products] Found', 1, 'products'); -log('[Reviews] Returned', 0, 'reviews for company 68fe2ccda3526c303ca06796'); -log('[Messages] Fetching threads for companyId:', '68fe2ccda3526c303ca06796'); -log('[Messages] Found', 4, 'messages for company'); -log('[Messages] Returned', 3, 'unique threads'); -log('[Search] Request params:', { query: '', page: 1 }); - -console.log(''); -console.log('='.repeat(60)); -console.log('РЕЗУЛЬТАТ:'); -console.log('='.repeat(60)); - -if (process.env.DEV === 'true') { - console.log('✅ DEV=true - логи ВИДНЫ выше'); -} else { - console.log('❌ DEV не установлена или != "true" - логи СКРЫТЫ'); - console.log(''); - console.log('Для включения логов запустите:'); - console.log(' export DEV=true && npm start (Linux/Mac)'); - console.log(' $env:DEV = "true"; npm start (PowerShell)'); - console.log(' set DEV=true && npm start (CMD)'); -} - -console.log(''); -console.log('='.repeat(60)); -console.log(''); diff --git a/server/routers/procurement/scripts/validate-companies.js b/server/routers/procurement/scripts/validate-companies.js new file mode 100644 index 0000000..cbf1147 --- /dev/null +++ b/server/routers/procurement/scripts/validate-companies.js @@ -0,0 +1,93 @@ +const mongoose = require('mongoose'); +const Company = require('../models/Company'); +require('dotenv').config({ path: '../../.env' }); + +const mongoUrl = process.env.MONGODB_URI || 'mongodb://admin:password@localhost:27017/procurement_db?authSource=admin'; + +const industryMap = { + 'it': 'IT', + 'finance': 'Финансы', + 'manufacturing': 'Производство', + 'construction': 'Строительство', + 'retail': 'Розничная торговля', + 'wholesale': 'Оптовая торговля', + 'logistics': 'Логистика', + 'healthcare': 'Здравоохранение', + 'education': 'Образование', + 'consulting': 'Консалтинг', + 'marketing': 'Маркетинг', + 'realestate': 'Недвижимость', + 'food': 'Пищевая промышленность', + 'agriculture': 'Сельское хозяйство', + 'energy': 'Энергетика', + 'telecom': 'Телекоммуникации', + 'media': 'Медиа', + 'tourism': 'Туризм', + 'legal': 'Юридические услуги', + 'other': 'Другое' +}; + +async function validateCompanies() { + try { + console.log('[Validation] Connecting to MongoDB...'); + await mongoose.connect(mongoUrl, { + useNewUrlParser: true, + useUnifiedTopology: true, + serverSelectionTimeoutMS: 5000, + connectTimeoutMS: 5000, + }); + console.log('[Validation] Connected to MongoDB\n'); + + const allCompanies = await Company.find().exec(); + console.log(`Found ${allCompanies.length} total companies\n`); + + console.log('=== COMPANY DATA VALIDATION REPORT ===\n'); + + let issuesFound = 0; + let validCompanies = 0; + + for (const company of allCompanies) { + console.log(`📋 Company: ${company.fullName}`); + console.log(` ID: ${company._id}`); + console.log(` Industry: ${company.industry} (type: ${typeof company.industry})`); + console.log(` Company Size: ${company.companySize}`); + + let hasIssues = false; + + if (company.industry) { + if (Array.isArray(company.industry)) { + console.log(` ⚠️ WARNING: industry is array!`); + issuesFound++; + hasIssues = true; + } else if (!Object.values(industryMap).includes(company.industry)) { + console.log(` ⚠️ industry value unknown: "${company.industry}"`); + issuesFound++; + hasIssues = true; + } else { + console.log(` ✅ industry OK`); + } + } + + if (!hasIssues) validCompanies++; + console.log(''); + } + + console.log('\n=== SUMMARY ==='); + console.log(`Total: ${allCompanies.length}`); + console.log(`Valid: ${validCompanies}`); + console.log(`Issues: ${issuesFound}`); + + if (issuesFound === 0) { + console.log('\n✅ All data OK. No migration needed.'); + } else { + console.log('\n⚠️ Migration recommended.'); + } + + await mongoose.connection.close(); + } catch (err) { + console.error('❌ Error:', err.message); + process.exit(1); + } +} + +validateCompanies();