setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo "✅ Подключение к БД установлено\n\n"; // Находим все файлы контрагентов в старой структуре $sql = " SELECT n.notesid, n.title, n.filename, n.s3_key, a.accountid, a.accountname FROM vtiger_notes n INNER JOIN vtiger_senotesrel sr ON n.notesid = sr.notesid INNER JOIN vtiger_account a ON sr.crmid = a.accountid WHERE n.filelocationtype = 'E' AND n.s3_key IS NOT NULL AND n.s3_key LIKE '%/Documents/%' AND n.s3_key NOT LIKE '%/Project/%' AND n.s3_key NOT LIKE '%/Contacts/%' AND n.s3_key NOT LIKE '%/Accounts/%' ORDER BY a.accountid, n.notesid "; $stmt = $pdo->prepare($sql); $stmt->execute(); $files = $stmt->fetchAll(PDO::FETCH_ASSOC); echo "📊 Найдено файлов контрагентов для обновления: " . count($files) . "\n\n"; if (empty($files)) { echo "✅ Все файлы контрагентов уже обновлены!\n"; exit(0); } $updatedCount = 0; $errorCount = 0; $currentAccountId = null; $accountCount = 0; foreach ($files as $file) { $notesId = $file['notesid']; $title = $file['title']; $oldS3Key = $file['s3_key']; $accountId = $file['accountid']; $accountName = $file['accountname']; // Считаем контрагентов if ($currentAccountId !== $accountId) { $currentAccountId = $accountId; $accountCount++; } echo "📁 Контрагент: {$accountName} (ID: {$accountId})\n"; echo " 📄 Файл: {$title} (ID: {$notesId})\n"; echo " 🔄 Старый путь: {$oldS3Key}\n"; try { // Простая нормализация имени контрагента $normalizedName = preg_replace('/[^a-zA-Zа-яА-Я0-9\s\-_]/u', '', $accountName); $normalizedName = preg_replace('/\s+/', '_', trim($normalizedName)); $normalizedName = preg_replace('/_+/', '_', $normalizedName); $normalizedName = trim($normalizedName, '_'); if (empty($normalizedName)) { $normalizedName = "account_{$accountId}"; } // Простая нормализация имени файла $normalizedTitle = preg_replace('/[^a-zA-Zа-яА-Я0-9\s\-_\.]/u', '', $title); $normalizedTitle = preg_replace('/\s+/', '_', trim($normalizedTitle)); $normalizedTitle = preg_replace('/_+/', '_', $normalizedTitle); $normalizedTitle = trim($normalizedTitle, '_'); if (empty($normalizedTitle)) { $normalizedTitle = "file_{$notesId}"; } // Формируем новый путь $newS3Key = "crm2/CRM_Active_Files/Documents/Accounts/{$normalizedName}_{$accountId}/{$normalizedTitle}_{$notesId}.pdf"; $newFilename = "https://s3.twcstorage.ru/f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c/{$newS3Key}"; echo " ✅ Новый путь: {$newS3Key}\n"; // Обновляем записи в БД $updateSql = " UPDATE vtiger_notes SET s3_key = ?, filename = ? WHERE notesid = ? "; $updateStmt = $pdo->prepare($updateSql); $updateStmt->execute([$newS3Key, $newFilename, $notesId]); echo " ✅ Записи в БД обновлены\n"; $updatedCount++; } catch (Exception $e) { echo " ❌ Ошибка: " . $e->getMessage() . "\n"; $errorCount++; } echo "\n"; } echo "🎉 ОБНОВЛЕНИЕ ЗАВЕРШЕНО!\n"; echo "📊 Статистика:\n"; echo " • Контрагентов обработано: {$accountCount}\n"; echo " • Записей обновлено: {$updatedCount}\n"; echo " • Ошибок: {$errorCount}\n"; echo " • Всего файлов: " . count($files) . "\n"; if ($errorCount > 0) { echo "\n⚠️ Некоторые записи не удалось обновить.\n"; } } catch (Exception $e) { echo "❌ КРИТИЧЕСКАЯ ОШИБКА: " . $e->getMessage() . "\n"; echo "Стек вызовов:\n" . $e->getTraceAsString() . "\n"; exit(1); }