# 🛡️ Защита от дубликатов в системе парсинга судов ## 📋 Обзор Система имеет **3 уровня защиты** от создания дубликатов: ### 1️⃣ Уровень событий в таблице `subject` **Файл:** `parsers/BaseCourtParser.php` (метод `saveEvent`) **Логика:** - Проверяет наличие события по 3 полям: `event_name`, `event_date`, `publication_date` - Если событие найдено → **НЕ сохраняет** в БД и возвращает `false` - Если `skip_duplicate_check=true` → пропускает проверку (только для тестов!) **SQL запрос:** ```sql SELECT COUNT(*) FROM subject WHERE event_name = ? AND event_date = ? AND publication_date = ? ``` ### 2️⃣ Уровень уведомлений в `vtiger_vdnotifierpro` **Файлы:** - `parsers/MoscowCourtParser.php` (метод `createCourtEventNotification`) - `parsers/RegionalCourtParser.php` (метод `createCourtEventNotification`) **Логика:** - Проверяет наличие уведомления по: `userid`, `crmid` (project_id), точное совпадение `title` - Если уведомление **непрочитано** (status=5) → **обновляет время** (modifiedtime) - Если уведомление **прочитано** (status≠5) → **НЕ создаёт дубликат** - Если уведомления нет → **создаёт новое** **SQL запросы:** ```sql -- Проверка существующего уведомления SELECT id, status FROM vtiger_vdnotifierpro WHERE userid = ? AND crmid = ? AND title = ? ORDER BY id DESC LIMIT 1 -- Обновление времени (если непрочитано) UPDATE vtiger_vdnotifierpro SET modifiedtime = NOW() WHERE id = ? -- Создание нового (если не найдено) INSERT INTO vtiger_vdnotifierpro (userid, modulename, crmid, modiuserid, link, title, action, modifiedtime, status) VALUES (?, 'Project', ?, 0, ?, ?, '', NOW(), 5) ``` ### 3️⃣ Уровень событий в CRM календаре **Файл:** `CreateCourtEvent_v2.php` **Логика:** - Не проверяет дубликаты напрямую - Полагается на защиту уровня 1 (таблица `subject`) --- ## ✅ Что нужно сделать для продакшена ### **1. НЕ передавать параметр `skip_duplicate_check=true`** ❌ **ПЛОХО (для тестов):** ```php $params = [ 'project_id' => 364118, 'case_number' => '02-1182/312/2025', 'skip_duplicate_check' => 'true' // ← УБРАТЬ ЭТО! ]; ``` ✅ **ХОРОШО (для продакшена):** ```php $params = [ 'project_id' => 364118, 'case_number' => '02-1182/312/2025', 'skip_duplicate_check' => 'false' // ← или не передавать вообще (по умолчанию false) ]; ``` ### **2. Убедиться, что параметр по умолчанию `false`** В файле `ParseAndCreateEvent.php` (строка 58): ```php 'skip_duplicate_check' => $params['skip_duplicate_check'] ?? 'false' ``` ✅ Это уже настроено правильно! ### **3. Убедиться, что в CRM workflow не передаётся `skip_duplicate_check=true`** Проверьте ваши workflow, которые вызывают `ParseAndCreateEvent.php` или `parscourt.php`. --- ## 🧪 Тестирование защиты от дубликатов ### Тест 1: События в таблице `subject` ```bash # Запустить парсинг 2 раза подряд curl "https://crm.clientright.ru/parscourt.php" \ -d "project_id=364118" \ -d "case_number=02-1182/312/2025" \ -d "link1=https://mos-sud.ru/..." \ -d "status=test" # Проверить, что в таблице subject только 1 запись mysql -u ci20465_72new -p -D ci20465_72new \ -e "SELECT COUNT(*) FROM subject WHERE case_number = '02-1182/312/2025'" ``` ### Тест 2: Уведомления в `vtiger_vdnotifierpro` ```bash # Запустить парсинг 2 раза подряд curl "https://crm.clientright.ru/ParseAndCreateEvent.php?project_id=364118&..." # Проверить, что создано только 1 уведомление mysql -u ci20465_72new -p -D ci20465_72new \ -e "SELECT id, title, status, modifiedtime FROM vtiger_vdnotifierpro WHERE crmid = 364118 ORDER BY id DESC LIMIT 5" ``` **Ожидаемый результат:** - При первом запуске: создаётся уведомление (status=5) - При втором запуске (если не прочитано): обновляется `modifiedtime`, status остаётся 5 - При втором запуске (если прочитано): ничего не происходит, дубликат НЕ создаётся --- ## 📊 Статусы уведомлений в VDNotifierPro | Status | Значение | Действие при повторном парсинге | |--------|-----------------|---------------------------------------| | 5 | Непрочитано | Обновить время (`modifiedtime`) | | 6 | Прочитано | Не создавать дубликат | | Другое | Удалено/Архив | Не создавать дубликат | --- ## 🔍 Отладка ### Проверить логи парсера ```bash tail -50 /var/www/fastuser/data/www/crm.clientright.ru/logs/parser.log ``` **Что искать:** - `Дубликат найден для события:` - событие не сохранено (защита работает) - `Обновлено время непрочитанного уведомления ID:` - уведомление обновлено (защита работает) - `Уведомление ID: X уже существует (статус: Y), дубликат не создан` - дубликат предотвращён (защита работает) - `⚠️ ТЕСТОВЫЙ РЕЖИМ: Проверка дубликатов отключена` - защита ОТКЛЮЧЕНА (только для тестов!) ### Проверить существующие уведомления ```sql SELECT id, userid, crmid, title, status, modifiedtime FROM vtiger_vdnotifierpro WHERE crmid = 364118 -- ваш project_id AND title LIKE '%Событие суда%' ORDER BY id DESC LIMIT 10; ``` --- ## ⚠️ ВАЖНО! ### ❌ **НЕ ДЕЛАТЬ:** 1. Не передавать `skip_duplicate_check=true` в продакшене 2. Не удалять проверки дубликатов из кода 3. Не изменять логику проверки без тестирования ### ✅ **РЕКОМЕНДУЕТСЯ:** 1. Использовать `skip_duplicate_check=false` (по умолчанию) 2. Регулярно проверять логи на наличие `⚠️ ТЕСТОВЫЙ РЕЖИМ` 3. Мониторить количество уведомлений для одного проекта --- ## 🎯 Итог При правильной настройке (`skip_duplicate_check=false` или не передавать вообще) система: - ✅ **НЕ создаёт** дубликаты событий в таблице `subject` - ✅ **НЕ создаёт** дубликаты уведомлений в `vtiger_vdnotifierpro` - ✅ **Обновляет время** непрочитанных уведомлений - ✅ **Игнорирует** повторные запуски для прочитанных уведомлений **Защита работает на всех трёх уровнях!** 🛡️