diff --git a/backend/communications/management/commands/migrate_participants_to_memberships.py b/backend/communications/management/commands/migrate_participants_to_memberships.py
deleted file mode 100644
index 38a3a778..00000000
--- a/backend/communications/management/commands/migrate_participants_to_memberships.py
+++ /dev/null
@@ -1,176 +0,0 @@
-"""
-Data migration: перенос участников из Chat.participants в ChatMembership
-
-Использование:
- .venv/Scripts/python manage.py migrate_participants_to_memberships
-
-Что делает:
-1. Находит все чаты с participants
-2. Для каждого participant создает ChatMembership с is_active=True
-3. Сохраняет роли (member для обычных участников)
-4. Не удаляет participants (только помечает как DEPRECATED)
-
-ВАЖНО: Запустить ДО удаления поля participants!
-"""
-
-from django.core.management.base import BaseCommand
-from django.db import transaction
-from communications.models import Chat, ChatMembership
-
-
-class Command(BaseCommand):
- help = 'Мигрирует участников из Chat.participants в ChatMembership'
-
- def add_arguments(self, parser):
- parser.add_argument(
- '--dry-run',
- action='store_true',
- help='Показать что будет сделано, без изменения БД',
- )
- parser.add_argument(
- '--verbose',
- action='store_true',
- help='Показывать детали для каждого чата',
- )
-
- def handle(self, *args, **options):
- dry_run = options['dry_run']
- verbose = options['verbose']
-
- self.stdout.write(
- self.style.WARNING('=' * 70)
- )
- self.stdout.write(
- self.style.WARNING('МИГРАЦИЯ: Chat.participants → ChatMembership')
- )
- self.stdout.write(
- self.style.WARNING('=' * 70)
- )
-
- if dry_run:
- self.stdout.write(
- self.style.NOTICE('\n[DRY RUN MODE] Изменения не будут сохранены\n')
- )
-
- # Статистика
- stats = {
- 'total_chats': 0,
- 'chats_with_participants': 0,
- 'created_memberships': 0,
- 'updated_memberships': 0,
- 'errors': 0,
- }
-
- chats = Chat.objects.all().prefetch_related('participants', 'memberships')
- stats['total_chats'] = chats.count()
-
- self.stdout.write(f"\nВсего чатов: {stats['total_chats']}\n")
-
- for chat in chats:
- participants = list(chat.participants.all())
-
- if not participants:
- continue
-
- stats['chats_with_participants'] += 1
-
- if verbose:
- self.stdout.write(
- f"\nЧат #{chat.id} ({chat.type}): {len(participants)} участников"
- )
-
- for user in participants:
- try:
- with transaction.atomic():
- # Проверяем существующий membership
- membership, created = ChatMembership.objects.get_or_create(
- chat=chat,
- user=user,
- defaults={
- 'role': 'member',
- 'is_active': True,
- 'invited_by': chat.created_by,
- }
- )
-
- if created:
- stats['created_memberships'] += 1
- if verbose:
- self.stdout.write(
- f" ✓ Создан membership для {user.get_full_name()} (role: member)"
- )
- else:
- # Обновляем существующий на is_active=True если был неактивен
- if not membership.is_active:
- if not dry_run:
- membership.is_active = True
- membership.left_at = None
- membership.save(update_fields=['is_active', 'left_at'])
-
- stats['updated_memberships'] += 1
- if verbose:
- self.stdout.write(
- f" ↻ Восстановлен membership для {user.get_full_name()}"
- )
- else:
- if verbose:
- self.stdout.write(
- f" - Membership для {user.get_full_name()} уже существует"
- )
-
- if dry_run and created:
- # Откатываем в dry-run режиме
- transaction.set_rollback(True)
-
- except Exception as e:
- stats['errors'] += 1
- self.stdout.write(
- self.style.ERROR(
- f" ✗ Ошибка для {user.get_full_name()}: {e}"
- )
- )
-
- # Итоговая статистика
- self.stdout.write('\n' + '=' * 70)
- self.stdout.write(self.style.SUCCESS('\nРЕЗУЛЬТАТЫ МИГРАЦИИ:'))
- self.stdout.write('=' * 70 + '\n')
-
- self.stdout.write(f"Всего чатов: {stats['total_chats']}")
- self.stdout.write(f"Чатов с participants: {stats['chats_with_participants']}")
- self.stdout.write(
- self.style.SUCCESS(
- f"Создано memberships: {stats['created_memberships']}"
- )
- )
- self.stdout.write(
- self.style.SUCCESS(
- f"Восстановлено memberships: {stats['updated_memberships']}"
- )
- )
-
- if stats['errors'] > 0:
- self.stdout.write(
- self.style.ERROR(f"Ошибок: {stats['errors']}")
- )
-
- self.stdout.write('\n' + '=' * 70)
-
- if dry_run:
- self.stdout.write(
- self.style.NOTICE(
- '\n[DRY RUN] Для применения изменений запустите без --dry-run\n'
- )
- )
- else:
- self.stdout.write(
- self.style.SUCCESS(
- '\n✓ Миграция завершена успешно!\n'
- )
- )
- self.stdout.write(
- self.style.WARNING(
- 'ВНИМАНИЕ: Поле Chat.participants помечено как DEPRECATED\n'
- 'но НЕ удалено для обратной совместимости.\n'
- 'После проверки работы системы можно будет удалить это поле.\n'
- )
- )
diff --git a/backend/docs/BOOTSTRAP_CARD_INTEGRATION.md b/backend/docs/BOOTSTRAP_CARD_INTEGRATION.md
deleted file mode 100644
index 816a2912..00000000
--- a/backend/docs/BOOTSTRAP_CARD_INTEGRATION.md
+++ /dev/null
@@ -1,156 +0,0 @@
-# Bootstrap Card Integration - Summary
-
-**Дата**: 29 ноября 2024
-**Контекст**: Решение конфликта между кастомными `.card` классами и нативными Bootstrap классами
-
-## Проблема
-
-После переименования `feed-*` классов в `card-*` для универсализации компонентов, возникли конфликты с нативными Bootstrap классами:
-- Bootstrap имеет встроенный компонент `.card` с собственными стилями
-- Bootstrap `.card-header`, `.card-body`, `.card-title` переопределяли кастомные стили
-- Изменились цвета, отступы, границы карточек
-
-## Решение
-
-Вместо дальнейшего переименования классов (например, `lc-card`, `list-card`), было принято решение **интегрироваться с Bootstrap** и переопределить его стили под наш дизайн.
-
-### Что сделано
-
-1. **Переопределены Bootstrap переменные** в `scss/custom-bootstrap.scss`:
- ```scss
- $card-border-radius: 18px;
- $card-box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
- $card-cap-padding-y: 1rem;
- $card-cap-padding-x: 1rem;
- ```
-
-2. **Добавлены кастомные расширения** Bootstrap карточек в `custom-bootstrap.scss`:
- - `.card` - добавлены тени, анимации, hover-эффекты
- - `.card-header` - переопределен flex-layout
- - `.card-icon` - кастомный класс для аватаров (42px круг)
- - `.card-meta` - кастомный класс для метаинформации
- - `.card-actions` - кастомный класс для кнопок
- - `.card-list` - кастомный класс для контейнера списка
- - `.section-header` - кастомный класс для заголовков секций
- - Вариации: `.card.compact`, `.card.borderless`, `.card.highlighted`
-
-3. **Создан `feed-specific.css`** для постов:
- - Выделены классы, используемые только в постах:
- - `.feed-pin` - значок закрепления
- - `.feed-title` - заголовок поста
- - `.feed-text` - текст поста
- - `.feed-img` - изображение поста
- - `.feed-action` - кнопки действий
- - `.feed-footer` - футер поста
-
-4. **Удалены устаревшие файлы**:
- - ❌ `card-list.css` - стили перенесены в `bootstrap-custom.css`
- - ❌ `request-list.css` - был уже пустым
-
-5. **Обновлены импорты** в шаблонах:
- - Удалены импорты `card-list.css` из всех шаблонов (8 файлов)
- - Добавлен импорт `feed-specific.css` в `feed_list.html`
- - `base.html` больше не импортирует `card-list.css`
-
-6. **Обновлена документация**:
- - `static/css/README.md` - новая архитектура и зависимости
- - `static/css/components/index.css` - обновлен импорт
-
-## Архитектура после рефакторинга
-
-```
-variables.css (CSS переменные)
- ↓
-bootstrap-custom.css (Bootstrap + переопределения .card)
- ↓
-common.css (общие классы)
- ↓
-├── feed-specific.css (только для постов)
-├── ios-components.css
-├── document-list.css
-├── employee-list.css
-└── другие компоненты
-```
-
-## Преимущества решения
-
-✅ **Соответствие стандартам**: Используем нативные Bootstrap классы
-✅ **Меньше кода**: Один источник стилей вместо дублирования
-✅ **Знакомая структура**: Разработчики знают Bootstrap
-✅ **Легче поддержка**: Стандартная документация Bootstrap применима
-✅ **Меньше конфликтов**: Работаем с Bootstrap, а не против него
-
-## Используемые классы
-
-### Универсальные (для всех карточек)
-- `.card` - базовая карточка
-- `.card-header` - шапка
-- `.card-body` - тело
-- `.card-title` - заголовок
-- `.card-subtitle` - подзаголовок
-- `.card-icon` - аватар/иконка (кастомный)
-- `.card-meta` - метаинформация (кастомный)
-- `.card-actions` - кнопки действий (кастомный)
-- `.card-list` - контейнер списка (кастомный)
-- `.section-header` - заголовок секции (кастомный)
-
-### Специфичные для постов
-- `.feed-pin` - значок закрепления
-- `.feed-title` - заголовок поста
-- `.feed-text` - текст поста
-- `.feed-img` - изображение
-- `.feed-action` - кнопка действия
-- `.feed-footer` - футер
-
-## Файлы
-
-### Добавлены
-- ✅ `static/css/components/feed-specific.css` (2.5KB)
-
-### Изменены
-- 📝 `static/scss/custom-bootstrap.scss` - добавлены переопределения карточек
-- 📝 `static/css/bootstrap-custom.css` - перекомпилирован
-- 📝 `static/css/components/index.css` - обновлены импорты
-- 📝 `static/css/README.md` - обновлена документация
-- 📝 8 HTML шаблонов - удалены импорты `card-list.css`
-- 📝 `templates/base.html` - удален импорт `card-list.css`
-- 📝 `templates/feed/feed_list.html` - добавлен импорт `feed-specific.css`
-
-### Удалены
-- ❌ `static/css/components/card-list.css` (7.8KB)
-- ❌ `static/css/components/request-list.css` (0.5KB)
-
-## Команды выполнения
-
-```bash
-# Компиляция SCSS
-cd backend/static
-npm run build:css
-
-# Сборка статики
-cd backend
-python manage.py collectstatic --noinput
-```
-
-## Результат
-
-- ✅ Компиляция SCSS: успешно (5 warnings о deprecated функциях Bootstrap - это нормально)
-- ✅ Сборка статики: 5 файлов обновлено, 990 без изменений
-- ✅ Размер: удалено 8.3KB CSS, добавлено 2.5KB = **-5.8KB**
-- ✅ Визуальное соответствие: карточки выглядят как задумано
-- ✅ Bootstrap интеграция: нативные классы Bootstrap работают с кастомными стилями
-
-## Следующие шаги
-
-1. Протестировать все страницы с карточками:
- - ✅ Лента новостей (`/feed/`)
- - ⏳ Заявления (`/requests/`)
- - ⏳ Документы (`/documents/`)
- - ⏳ Сотрудники (`/employees/`)
- - ⏳ Отделы (`/employees/departments/`)
- - ⏳ Чаты (`/communications/`)
- - ⏳ Поиск (`/search/`)
-
-2. Проверить адаптивность на мобильных устройствах
-
-3. Обновить остальную документацию при необходимости
diff --git a/backend/docs/CARD_LIST_REFACTORING.md b/backend/docs/CARD_LIST_REFACTORING.md
deleted file mode 100644
index 06b8a469..00000000
--- a/backend/docs/CARD_LIST_REFACTORING.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# Card List Refactoring - Универсализация стилей карточек
-
-## Что изменилось
-
-### Переименование файла CSS
-- **Было**: `cards.css` (название специфично для новостей)
-- **Стало**: `card-list.css` (универсальное название)
-
-### Назначение
-Файл `card-list.css` теперь официально документирован как **универсальный компонент** для любых типов списков:
-- ✅ Новости (feed)
-- ✅ Заявления (requests)
-- ✅ Документы (documents)
-- ✅ Сотрудники (employees)
-- ✅ Отделы (departments)
-- ✅ Чаты (communications)
-- ✅ Результаты поиска (search)
-
-### Классы остались без изменений
-Классы `feed-*` сохранены для обратной совместимости:
-- `.card` - контейнер карточки
-- `.card-header` - шапка карточки
-- `.card-icon` - аватар/иконка
-- `.card-meta` - метаинформация
-- `.card-title` - автор/заголовок
-- `.card-subtitle` - дополнительная информация
-- `.card-body` - тело карточки
-- `.card-actions` - кнопки действий
-- `.card-list` - контейнер потока карточек
-
-**Примечание**: `feed` здесь означает "поток данных" (data feed), что подходит для любых списков контента.
-
-## Изменения в файлах
-
-### HTML шаблоны (10 файлов)
-Обновлен импорт CSS:
-```diff
--
-+
-```
-
-**Затронутые файлы**:
-- `base.html`
-- `feed/feed_list.html`
-- `requests_app/request_list_full.html`
-- `documents/document_list.html`
-- `communications/chat_list.html`
-- `search/results.html`
-- `employees/employees_list.html`
-- `employees/employees_list_NEW_EXAMPLE.html`
-- `employees/department_list.html`
-
-### CSS файлы
-Обновлены ссылки и зависимости:
-- `components/index.css` - изменен импорт
-- `components/request-list.css` - обновлены комментарии
-- `components/document-list.css` - обновлены комментарии
-- `components/list-view.css` - обновлены комментарии
-
-### Документация
-- `static/css/README.md` - полностью обновлена секция о card-list.css
-- `docs/CARD_LIST_REFACTORING.md` - создан этот документ
-
-## Преимущества изменений
-
-1. **Семантика**: Название файла `card-list.css` точно отражает его назначение
-2. **Универсальность**: Явно указывает, что стили применимы для любых списков
-3. **Поддерживаемость**: Новые разработчики сразу понимают назначение файла
-4. **Обратная совместимость**: Классы не изменились, весь существующий код работает
-
-## Миграция проекта
-
-### Что НЕ требуется менять
-- ❌ HTML классы (`card`, `card-header`, и т.д.) - оставить как есть
-- ❌ JavaScript селекторы - работают без изменений
-- ❌ Существующие компоненты - не требуют рефакторинга
-
-### Что нужно обновить (уже сделано)
-- ✅ Импорты CSS в шаблонах
-- ✅ Ссылки в других CSS файлах
-- ✅ Документация
-
-## Использование
-
-### В новых шаблонах
-```html
-{% block extra_css %}
-
-{% endblock %}
-```
-
-### В новых компонентах
-```html
-
-
-
-
-
-
-
Заголовок
-
Дополнительная информация
-
-
-
- Контент карточки
-
-
-
-```
-
-## Дата изменений
-29 ноября 2025 г.
diff --git a/backend/docs/CHANGELOG.md b/backend/docs/CHANGELOG.md
deleted file mode 100644
index d6ff7ba8..00000000
--- a/backend/docs/CHANGELOG.md
+++ /dev/null
@@ -1,164 +0,0 @@
-# Changelog - EUSRR Chat Module
-
-Все значимые изменения в чат-модуле документируются в этом файле.
-
-Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.0.0/),
-и этот проект придерживается [Semantic Versioning](https://semver.org/lang/ru/).
-
----
-
-## [2.0.0] - 2026-01-13
-
-### ✨ Добавлено
-
-#### Умный автоскролл
-- **Индикатор новых сообщений** - кнопка "N новых сообщений" при чтении истории
-- **Telegram-like поведение** - автоскролл только если пользователь внизу
-- **Счетчик непрочитанных** - отслеживание количества новых сообщений
-- **Автоскрытие при скролле** - индикатор исчезает когда прокручиваем вниз вручную
-- 18 автотестов для умного автоскролла (100% pass rate)
-
-#### Производительность (MessageStoreV2)
-- **Batch операции** - отложенные уведомления для массовых операций (3x быстрее)
-- **Бинарный поиск** - O(log n) вставка в отсортированный список
-- **Оптимизация ререндеров** - меньше перерисовок при загрузке истории
-
-#### Устойчивость (MessageLoaderV2)
-- **Retry логика** - автоматические повторы при сбоях сети
-- **Exponential backoff** - умное увеличение задержки между попытками
-- **AbortController** - отмена дублирующих запросов
-- **Timeout handling** - обработка зависших запросов
-
-#### Оптимизация (ScrollManagerV2)
-- **Debounce для scroll** - 16x меньше обработок событий
-- **Throttle для загрузки** - контроль частоты запросов истории
-- **Улучшенный cleanup** - правильное удаление слушателей
-
-#### Архитектура
-- **Централизованная конфигурация** - `chatConfig.js` со всеми настройками
- - `LOADER_CONFIG` - настройки загрузчика
- - `SCROLL_CONFIG` - настройки скролла
- - `AUTOSCROLL_CONFIG` - ⭐ НОВОЕ: настройки автоскролла
- - `STORE_EVENTS`, `CHAT_EVENTS`, `WS_EVENTS` - константы событий
-- **JSDoc типизация** - полное покрытие TypeScript-like типами
-- **Модульность** - каждый компонент самостоятелен
-
-#### Миграция
-- **chatMigration.js** - утилиты для миграции со старой версии
- - `migrateToV2()` - автоматическая миграция контроллера
- - `ChatControllerCompat` - compatibility layer для плавной миграции
- - `isV2Controller()`, `getControllerVersion()` - проверка версии
-- **V2_MIGRATION_GUIDE.md** - подробное руководство по миграции
-
-#### Тестирование
-- **chatTestsV2.js** - портированные тесты для V2
-- **chatTestsV2.html** - удобный UI для запуска тестов
-- Покрытие: 8 сценариев умного автоскролла
-
-### 🔄 Изменено
-
-#### Breaking Changes
-- **chat/index.js** - V2 теперь экспортируется как основная версия
- ```javascript
- // БЫЛО:
- export { ChatController } from '../controllers/chatController.js';
-
- // СТАЛО:
- export { ChatControllerV2 as ChatController } from '../controllers/chatControllerV2.js';
- export { ChatController as ChatControllerLegacy } from '../controllers/chatController.js';
- ```
-- **Приватные свойства** - префикс `_` для внутренних свойств в V2
- - `newMessagesCount` → `_newMessagesCount`
- - `initialized` → `_initialized`
- - Решение: используйте `ChatControllerCompat` для обратной совместимости
-
-#### API Changes
-- **Опции конструктора**:
- - Удалено: `lastReadTimestamp`
- - Добавлено: `lastReadMessageId` (ID вместо timestamp)
-- **Методы Store**:
- - `addMessages()` теперь поддерживает batch режим
- - Оптимизированы уведомления (одно событие вместо N)
-
-### 🐛 Исправлено
-
-- **Scroll watcher timing** - удален debounce для мгновенной реакции в тестах
-- **Race conditions** - AbortController решает проблему дублирующих запросов
-- **Memory leaks** - правильный cleanup слушателей в destroy()
-- **Бесконечный скролл** - улучшена логика определения "внизу чата"
-
-### ⚡ Производительность
-
-- **3.3x faster** - batch загрузка 100 сообщений (50ms → 15ms)
-- **16x меньше** - обработок scroll events (100/сек → 6/сек)
-- **O(log n)** - вставка сообщений (вместо O(n))
-- **-5.7% кода** - V2 более компактен (2145 строк vs 2274)
-
-### 📚 Документация
-
-- **V2_REFACTORING_EVALUATION.md** - полная оценка рефакторинга V2
-- **V2_MIGRATION_GUIDE.md** - пошаговое руководство миграции
-- **CHANGELOG.md** - этот файл
-- Обновлены комментарии в коде - JSDoc типизация
-
-### 🧪 Тестирование
-
-- Портировано 18 тестов умного автоскролла
-- Pass rate: 100% (18/18)
-- Добавлен удобный HTML runner (chatTestsV2.html)
-
----
-
-## [1.0.0] - 2025-12-XX
-
-### Добавлено
-- Базовая версия ChatController
-- MessageStore для хранения сообщений
-- MessageLoader для загрузки через API
-- ScrollManager для управления скроллом
-- MessageRenderer для рендеринга сообщений
-
-### Функциональность
-- Загрузка начальных сообщений
-- Загрузка истории при скролле вверх
-- WebSocket для real-time обновлений
-- Оптимистичные обновления при отправке
-- Базовый автоскролл
-
----
-
-## Roadmap
-
-### [2.1.0] - Планируется
-- [ ] Виртуализация для очень длинных чатов (10000+ сообщений)
-- [ ] Оффлайн режим с кешированием в IndexedDB
-- [ ] Поиск по сообщениям чата
-- [ ] Реакции на сообщения (улучшенный UX)
-- [ ] Редактирование отправленных сообщений
-
-### [3.0.0] - Будущее
-- [ ] TypeScript миграция
-- [ ] Web Workers для обработки больших объемов данных
-- [ ] Service Worker для push-уведомлений
-- [ ] E2E шифрование сообщений
-
----
-
-## Ссылки
-
-- [V2 Migration Guide](guides/V2_MIGRATION_GUIDE.md)
-- [V2 Evaluation Report](../docs/reports/V2_REFACTORING_EVALUATION.md)
-- [Tests](../static/js/tests/chatTestsV2.html)
-- [Source Code](../static/js/)
-
----
-
-**Легенда:**
-- ✨ Добавлено - новая функциональность
-- 🔄 Изменено - изменения в существующей функциональности
-- 🗑️ Удалено - удаленная функциональность
-- 🐛 Исправлено - исправления багов
-- 🔒 Безопасность - закрытие уязвимостей
-- ⚡ Производительность - улучшения производительности
-- 📚 Документация - только документация
-- 🧪 Тестирование - добавление/изменение тестов
diff --git a/backend/docs/CHAT_MODAL_IMPROVEMENTS.md b/backend/docs/CHAT_MODAL_IMPROVEMENTS.md
deleted file mode 100644
index c35bce7c..00000000
--- a/backend/docs/CHAT_MODAL_IMPROVEMENTS.md
+++ /dev/null
@@ -1,275 +0,0 @@
-# Улучшения модала создания чатов
-
-## Что добавлено
-
-### 1. Новые типы чатов
-- **Чат отдела** (`department`) - автоматически включает всех сотрудников отдела
-- **Глобальный чат** (`global`) - для всей компании
-
-### 2. Новые поля
-
-#### Аватар чата
-- Загрузка изображения (JPG/PNG/GIF, до 5 МБ)
-- Предпросмотр перед загрузкой
-- **Автоматическое сжатие** до 512x512px (до 500KB)
-- Удаление старых файлов при замене
-
-#### Выбор отдела
-- Для типа "Чат отдела"
-- Dropdown со всеми отделами
-- Автодобавление всех сотрудников отдела
-
-#### Включить всех сотрудников
-- Для типов: `announcement`, `global`, `channel`
-- Автодобавление всех активных сотрудников компании
-- Ограниченная отправка для `channel` и `announcement`
-
-#### Основной чат
-- Для типов: `global`, `department`
-- Только 1 основной глобальный чат
-- Только 1 основной чат на отдел
-- Валидация на уровне API
-
-### 3. Улучшенный UI
-
-#### Типы чатов с подсказками
-```
-Личный: приватный чат с 1 сотрудником
-Группа: чат с несколькими участниками
-Отдел: автоматически включает всех сотрудников отдела
-Канал: для объявлений с ограниченной отправкой
-Объявления: односторонняя рассылка
-Глобальный: общий чат компании (может быть только 1 основной)
-```
-
-#### Динамическое переключение полей
-- **Private**: только выбор участника
-- **Group**: название + описание + аватар + участники
-- **Department**: название + описание + аватар + отдел + "основной"
-- **Global**: название + описание + аватар + "включить всех" + "основной"
-- **Channel/Announcement**: название + описание + аватар + "включить всех"
-
-### 4. API изменения
-
-#### FormData support
-```javascript
-// Теперь поддерживает загрузку файлов
-const formData = new FormData();
-formData.append('type', 'group');
-formData.append('name', 'Команда разработки');
-formData.append('avatar', file);
-formData.append('participant_ids', [1, 2, 3]);
-```
-
-#### Новые параметры API
-- `avatar` (file) - файл аватара
-- `department_id` (int) - ID отдела для `type=department`
-- `include_all_employees` (bool) - включить всех сотрудников
-- `is_main` (bool) - сделать основным чатом
-
-#### Валидация
-- ✅ Проверка типа чата
-- ✅ Обязательное название (кроме private)
-- ✅ Обязательный отдел для `department`
-- ✅ Уникальность основного глобального чата
-- ✅ Уникальность основного чата отдела
-
-### 5. Автоматическое сжатие аватаров
-
-#### Signal `compress_and_cleanup_chat_avatar`
-```python
-@receiver(pre_save, sender='communications.Chat')
-def compress_and_cleanup_chat_avatar(sender, instance, **kwargs):
- # 1. Сжимает новый аватар до 512x512px (макс 500KB)
- # 2. Удаляет старый файл при замене
- # 3. Использует LANCZOS для высокого качества
-```
-
-#### Параметры сжатия
-- Размер: 512x512px (оптимально для отображения)
-- Формат: JPEG (универсальный)
-- Качество: 50-85 (бинарный поиск оптимального)
-- Максимум: 500KB
-
-### 6. Автодобавление участников
-
-#### Для `include_all_employees=True`
-```python
-# Добавляются все активные сотрудники
-all_employees = Employee.objects.filter(is_active=True)
-
-# Права зависят от типа чата:
-# - channel/announcement: can_send_messages=False
-# - остальные: can_send_messages=True
-```
-
-#### Для `type=department`
-```python
-# Добавляются сотрудники отдела
-dept_employees = EmployeeDepartment.objects.filter(
- department=department,
- is_active=True
-)
-
-# Все получают can_send_messages=True
-```
-
-## Примеры использования
-
-### Создать групповой чат с аватаром
-```javascript
-const formData = new FormData();
-formData.append('type', 'group');
-formData.append('name', 'DevOps Team');
-formData.append('description', 'Обсуждение инфраструктуры');
-formData.append('avatar', avatarFile);
-formData.append('participant_ids', 5);
-formData.append('participant_ids', 12);
-formData.append('participant_ids', 23);
-
-fetch('/communications/api/chat/create/', {
- method: 'POST',
- headers: { 'X-CSRFToken': csrftoken },
- body: formData
-});
-```
-
-### Создать основной чат отдела
-```javascript
-const formData = new FormData();
-formData.append('type', 'department');
-formData.append('name', 'Отдел разработки');
-formData.append('department_id', 3);
-formData.append('is_main', 'true');
-
-fetch('/communications/api/chat/create/', {
- method: 'POST',
- headers: { 'X-CSRFToken': csrftoken },
- body: formData
-});
-```
-
-### Создать канал с аватаром для всех
-```javascript
-const formData = new FormData();
-formData.append('type', 'channel');
-formData.append('name', 'Новости компании');
-formData.append('description', 'Официальные объявления');
-formData.append('avatar', avatarFile);
-formData.append('include_all_employees', 'true');
-
-fetch('/communications/api/chat/create/', {
- method: 'POST',
- headers: { 'X-CSRFToken': csrftoken },
- body: formData
-});
-```
-
-## Технические детали
-
-### Структура модели Chat
-```python
-class Chat(models.Model):
- type = CharField(choices=[...])
- name = CharField(max_length=255)
- description = TextField()
- avatar = ImageField(upload_to='chat_avatars/%Y/%m/') # NEW
- created_by = ForeignKey(Employee)
- department = ForeignKey(Department) # NEW
- include_all_employees = BooleanField(default=False) # NEW
- is_main = BooleanField(default=False) # NEW
- participants = ManyToManyField(Employee)
- created_at = DateTimeField(auto_now_add=True)
-```
-
-### Constraints
-```python
-# Только 1 основной глобальный чат
-UniqueConstraint(
- fields=["type"],
- condition=Q(is_main=True, type="global"),
- name="unique_main_global_chat"
-)
-
-# Только 1 основной чат на отдел
-UniqueConstraint(
- fields=["type", "department"],
- condition=Q(is_main=True, type="department"),
- name="unique_main_department_chat"
-)
-```
-
-### Путь хранения аватаров
-```
-media/
- chat_avatars/
- 2024/
- 11/
- chat_avatar_abc123.jpg (сжато до 512x512, <500KB)
-```
-
-## Совместимость
-
-### Backward compatibility
-- ✅ Старые чаты без аватаров работают как прежде
-- ✅ API поддерживает JSON (legacy) и FormData (новый)
-- ✅ Все новые поля опциональные (кроме валидируемых случаев)
-
-### Frontend
-- Модал: Bootstrap 5
-- Preview: FileReader API
-- Validation: Client-side + Server-side
-- CSRF: Из cookie или hidden input
-
-## Производительность
-
-### Оптимизации
-- ✅ Сжатие аватаров на лету (JPEG quality 50-85)
-- ✅ Удаление старых файлов (нет дубликатов)
-- ✅ Batch добавление участников (без N+1 queries)
-- ✅ `select_related('employee')` для отделов
-
-### Размеры файлов
-- **До**: 8.3 MB PNG, 800+ KB JPEG
-- **После**: <500 KB JPEG, 512x512px
-- **Экономия**: ~90-95% места на диске
-
-## Тестирование
-
-### Проверить создание чатов
-1. Личный чат с 1 участником ✅
-2. Групповой чат с аватаром ✅
-3. Чат отдела с автодобавлением ✅
-4. Глобальный основной чат (только 1) ✅
-5. Канал для всех с ограниченной отправкой ✅
-
-### Проверить сжатие
-1. Загрузить PNG 5MB → сжато до <500KB JPEG ✅
-2. Заменить аватар → старый файл удален ✅
-3. Проверить preview в модале ✅
-
-### Проверить валидацию
-1. Попытка создать 2 основных глобальных чата → ошибка ✅
-2. Чат отдела без выбора отдела → ошибка ✅
-3. Файл >5MB → отклонен на клиенте ✅
-
-## Changelog
-
-### v1.0 (30 ноября 2024)
-- ✅ Добавлены поля: avatar, department, include_all_employees, is_main
-- ✅ Реализовано автосжатие аватаров (512x512, <500KB)
-- ✅ Добавлены типы: department, global
-- ✅ Динамические поля в модале
-- ✅ API поддержка FormData + файлов
-- ✅ Валидация основных чатов
-- ✅ Автодобавление участников по правилам
-- ✅ Signal для сжатия и cleanup
-
-## TODO
-
-- [ ] Crop аватара перед загрузкой (client-side)
-- [ ] Batch upload нескольких аватаров
-- [ ] История изменений аватара чата
-- [ ] Права на изменение аватара (только owner/admin)
-- [ ] Предпросмотр аватара в списке чатов
-- [ ] Поиск чатов по названию в модале
diff --git a/backend/docs/CHAT_REFACTORING_QUICKSTART.md b/backend/docs/CHAT_REFACTORING_QUICKSTART.md
deleted file mode 100644
index 16704ffb..00000000
--- a/backend/docs/CHAT_REFACTORING_QUICKSTART.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Chat Handler Refactoring - Quick Start
-
-> **Статус**: 🔴 Требуется отдельная сессия (2-3 часа)
-> **Приоритет**: Средний (после завершения можно переходить к Фазе 5)
-> **Детальный план**: [CHAT_REFACTORING_SESSION.md](./CHAT_REFACTORING_SESSION.md)
-
-## Что нужно сделать
-
-Извлечь **521 строку** встроенного JavaScript из `templates/base.html` в **6 переиспользуемых модулей**.
-
-## Структура
-
-### Текущее состояние (base.html)
-```
-📄 base.html
-├── Avatar Map (6 строк) - инициализация карты аватаров
-├── Chat Detail Handler (186 строк) - автоскролл, textarea, отметка прочитанного
-├── WebSocket Chat (161 строка) - реалтайм сообщения
-├── Chat List Filter (42 строки) - поиск и фильтрация
-├── Chat List Realtime (62 строки) - обновление списка через WS
-└── Global Badge Updater (60 строк) - счетчик непрочитанных
-```
-
-### Целевая структура
-```
-📁 static/js/components/chat/
-├── chatAvatars.js (простой, 5 минут)
-├── chatListFilter.js (простой, 15 минут)
-├── chatBadgeUpdater.js (средний, 30 минут)
-├── chatListRealtime.js (средний, 30 минут)
-├── chatDetailHandler.js (сложный, 60 минут) ⚠️
-└── chatWebSocket.js (сложный, 60 минут) ⚠️
-```
-
-## Порядок работы
-
-1. **chatAvatars.js** - быстрая победа ✅
-2. **chatListFilter.js** - независимый модуль
-3. **chatBadgeUpdater.js** - обновление бейджа
-4. **chatListRealtime.js** - WebSocket для списка
-5. **chatDetailHandler.js** - логика детального чата
-6. **chatWebSocket.js** - WebSocket для сообщений
-
-## Зависимости
-
-```
-chatAvatars.js
- ↓
-chatWebSocket.js ← chatDetailHandler.js
- ↓ ↓
-chatListRealtime.js → chatBadgeUpdater.js
- ↓
-chatListFilter.js
-```
-
-## Результат
-
-**До**: 521 строка встроенного JS
-**После**: ~40 строк инициализации + 6 модулей
-**Сокращение**: 92% 🎉
-
-## Начало работы
-
-1. Прочитать [CHAT_REFACTORING_SESSION.md](./CHAT_REFACTORING_SESSION.md)
-2. Создать директорию `static/js/components/chat/`
-3. Начать с простых модулей (chatAvatars, chatListFilter)
-4. Тестировать каждый модуль после создания
-5. Обновить base.html в конце
-
-## Чеклист тестирования
-
-- [ ] Открытие детального чата → автоскролл работает
-- [ ] Отправка сообщения → появляется в реальном времени
-- [ ] Получение сообщения → обновляется счетчик
-- [ ] Поиск в списке чатов → фильтрация работает
-- [ ] Новое сообщение → список пересортируется
-- [ ] Прочтение чата → бейдж обновляется
-
-## Потенциальные проблемы
-
-⚠️ **Порядок инициализации**: chatWebSocket зависит от chatDetailHandler
-✅ **Решение**: передавать chatDetail как параметр
-
-⚠️ **Django context**: chatId, meId нужны из шаблона
-✅ **Решение**: передавать через параметры инициализации
-
-⚠️ **Обратная совместимость**: `window.__CHAT_MARK_READ__`
-✅ **Решение**: экспортировать в window
-
----
-
-**См. также**: [Полный план рефакторинга](./CHAT_REFACTORING_SESSION.md)
diff --git a/backend/docs/CHAT_REFACTORING_SESSION.md b/backend/docs/CHAT_REFACTORING_SESSION.md
deleted file mode 100644
index 94de5125..00000000
--- a/backend/docs/CHAT_REFACTORING_SESSION.md
+++ /dev/null
@@ -1,471 +0,0 @@
-# Chat Handler Refactoring Session
-
-## Цель
-Извлечь все встроенные скрипты чата из `templates/base.html` в отдельные модули.
-
-## Анализ текущего состояния
-
-### Структура chat скриптов в base.html
-
-**Всего: 521 строка JavaScript (строки 95-624)**
-
-Разделяется на 6 логических блоков:
-
-#### 1. Avatar Map (6 строк, 96-101)
-```javascript
-window.__CHAT_AVATARS__ = {
- "{{ user.id }}": "{{ user.avatar.url }}"
-};
-```
-**Зависимости**: Django template context (user)
-**Использование**: WebSocket chat для отображения аватаров
-
----
-
-#### 2. Chat Detail Handler (186 строк, 104-289)
-**Функциональность**:
-- Автоскролл к последнему сообщению
-- Авто-рост textarea при вводе
-- Кнопка "вниз" для скролла
-- Разделитель "Новые сообщения"
-- Отметка прочитанных (localStorage + API)
-- IntersectionObserver для автоматической отметки
-
-**Ключевые элементы**:
-```javascript
-const box = document.getElementById('chatScroll');
-const ta = document.getElementById('id_content');
-const form = document.getElementById('chatForm');
-const btn = document.getElementById('scrollBtn');
-```
-
-**API endpoints**:
-- `POST /communications/chat/{id}/mark-read/` - отметка прочитанных
-
-**События**:
-- `chat:read` - CustomEvent для обновления глобального счетчика
-
-**Экспортирует**:
-```javascript
-window.__CHAT_MARK_READ__ = {
- markRead,
- observeLastForeign,
- autoscroll,
- atBottom
-};
-```
-
----
-
-#### 3. WebSocket Chat (161 строк, 291-451)
-**Функциональность**:
-- WebSocket соединение `/ws/chat/{id}/`
-- Отправка сообщений
-- Получение новых сообщений в реальном времени
-- Индикация "печатает..."
-- Рендеринг сообщений в DOM
-
-**Зависимости**:
-- `window.__CHAT_AVATARS__` - карта аватаров
-- `window.__CHAT_MARK_READ__` - методы из блока #2
-- `window.esc()` - из stringUtils.js
-- Django context: `{{ chat.id }}`, `{{ user.id }}`
-
-**HTML шаблоны**:
-- Создает `.msg` элементы динамически
-- Создает `.day-divider` разделители
-
----
-
-#### 4. Chat List Filter (42 строки, 454-495)
-**Функциональность**:
-- Поиск по названию чата
-- Фильтр по типу (all/global/department/private)
-- Скрытие пустых секций
-
-**Ключевые элементы**:
-```javascript
-const search = document.getElementById('chatSearch');
-const labels = document.querySelectorAll('[data-filter]');
-const sections = {
- global: '.chat-section[data-sec="global"]',
- department: '.chat-section[data-sec="department"]',
- private: '.chat-section[data-sec="private"]'
-};
-```
-
-**Зависимости**:
-- `window.norm()` - из stringUtils.js
-- HTML структура списка чатов
-
----
-
-#### 5. Chat List Realtime (62 строки, 498-559)
-**Функциональность**:
-- WebSocket соединение `/ws/chats/`
-- Обновление preview/времени/счетчика при новом сообщении
-- Пересортировка списка по времени последнего сообщения
-
-**Ключевые элементы**:
-```javascript
-const rows = document.querySelectorAll('.chat-row');
-// Атрибуты: data-chat-id, data-last-ts, data-type
-```
-
-**Зависимости**:
-- Django context: `{{ user.id }}`
-- HTML структура `.chat-row`
-
----
-
-#### 6. Global Badge Updater (60 строк, 560-619)
-**Функциональность**:
-- Обновление счетчика непрочитанных в сайдбаре
-- Карта непрочитанных по всем чатам
-- Подписка на WebSocket `/ws/chats/`
-- Обработка события `chat:read`
-
-**Ключевые элементы**:
-```javascript
-const badge = document.getElementById('sidebarChatBadge');
-const chatUnread = {}; // карта непрочитанных
-```
-
-**События**:
-- Слушает: `chat:read` (из блока #2)
-- Подписка на WebSocket `/ws/chats/`
-
----
-
-## План рефакторинга
-
-### Шаг 1: Подготовка
-- [x] Анализ зависимостей между блоками
-- [ ] Определение публичного API каждого модуля
-- [ ] Создание схемы взаимодействия
-
-### Шаг 2: Создание модулей
-
-#### 2.1. `chatAvatars.js` (простой)
-```javascript
-export function initChatAvatars(userId, avatarUrl) {
- window.__CHAT_AVATARS__ = window.__CHAT_AVATARS__ || {};
- if (userId && avatarUrl) {
- window.__CHAT_AVATARS__[userId] = avatarUrl;
- }
- return window.__CHAT_AVATARS__;
-}
-```
-
-#### 2.2. `chatDetailHandler.js` (сложный, 186 строк)
-**Экспорты**:
-```javascript
-export function initChatDetailHandler(options = {}) {
- // ... инициализация
- return {
- markRead,
- observeLastForeign,
- autoscroll,
- atBottom,
- destroy
- };
-}
-```
-
-**Опции**:
-```javascript
-{
- scrollContainerId: 'chatScroll',
- textareaId: 'id_content',
- formId: 'chatForm',
- scrollBtnId: 'scrollBtn',
- chatId: null,
- meId: null,
- markReadUrl: null // или авто-определение
-}
-```
-
-#### 2.3. `chatWebSocket.js` (сложный, 161 строка)
-**Экспорты**:
-```javascript
-export function initChatWebSocket(options = {}) {
- // ... WebSocket логика
- return {
- send,
- close,
- reconnect,
- ws // прямой доступ к WebSocket
- };
-}
-```
-
-**Опции**:
-```javascript
-{
- chatId: null, // REQUIRED
- meId: null, // REQUIRED
- scrollContainerId: 'chatScroll',
- formId: 'chatForm',
- textareaId: 'id_content',
- typingIndicatorId: 'typing',
- avatars: window.__CHAT_AVATARS__,
- markReadHandler: window.__CHAT_MARK_READ__ // или передать явно
-}
-```
-
-#### 2.4. `chatListFilter.js` (средний, 42 строки)
-**Экспорты**:
-```javascript
-export function initChatListFilter(options = {}) {
- return {
- applyFilter,
- setActiveType,
- destroy
- };
-}
-```
-
-#### 2.5. `chatListRealtime.js` (средний, 62 строки)
-**Экспорты**:
-```javascript
-export function initChatListRealtime(options = {}) {
- return {
- ws,
- disconnect,
- reconnect
- };
-}
-```
-
-#### 2.6. `chatBadgeUpdater.js` (средний, 60 строк)
-**Экспорты**:
-```javascript
-export function initChatBadgeUpdater(options = {}) {
- return {
- setBadge,
- recompute,
- getChatUnread,
- destroy
- };
-}
-```
-
-### Шаг 3: Интеграция в base.html
-
-Заменить все 6 блоков на:
-
-```django
-{% load static %}
-
-{# Chat functionality - только для авторизованных #}
-{% if user.is_authenticated %}
-
-{% endif %}
-```
-
-### Шаг 4: Тестирование
-
-Проверить каждый сценарий:
-
-- [ ] Открытие страницы детального чата
- - [ ] Автоскролл к последнему сообщению
- - [ ] Разделитель "Новые сообщения" появляется
- - [ ] Textarea автоматически растет при вводе
- - [ ] Ctrl+Enter отправляет сообщение
- - [ ] Кнопка "вниз" появляется при скролле вверх
-
-- [ ] Отправка сообщений
- - [ ] Сообщение отправляется через WebSocket
- - [ ] Сообщение появляется в чате
- - [ ] Аватар и имя отображаются правильно
- - [ ] Время форматируется корректно
-
-- [ ] Получение сообщений
- - [ ] Новые сообщения приходят в реальном времени
- - [ ] Автоскролл работает (если в конце списка)
- - [ ] Индикация "печатает..." работает
- - [ ] Отметка прочитанных срабатывает
-
-- [ ] Список чатов
- - [ ] Поиск работает
- - [ ] Фильтр по типу работает
- - [ ] Пустые секции скрываются
- - [ ] Preview/время обновляются при новом сообщении
- - [ ] Счетчик непрочитанных обновляется
- - [ ] Сортировка по времени работает
-
-- [ ] Глобальный счетчик
- - [ ] Бейдж обновляется при новых сообщениях
- - [ ] Бейдж обнуляется при прочтении
- - [ ] События `chat:read` обрабатываются
-
-### Шаг 5: Документация
-
-- [ ] JSDoc для всех публичных функций
-- [ ] README.md в `static/js/components/chat/`
-- [ ] Примеры использования
-- [ ] Описание событий и API
-
----
-
-## Технические детали
-
-### Зависимости между модулями
-
-```
-chatAvatars.js
- ↓
-chatWebSocket.js ← chatDetailHandler.js
- ↓ ↓
-chatListRealtime.js → chatBadgeUpdater.js
- ↓
-chatListFilter.js
-```
-
-### Глобальные объекты (для обратной совместимости)
-
-```javascript
-window.__CHAT_AVATARS__ = {}; // карта аватаров
-window.__CHAT_MARK_READ__ = {}; // методы chatDetailHandler
-```
-
-### События
-
-**Генерируются**:
-- `chat:read` - CustomEvent при отметке прочитанного
- ```javascript
- window.dispatchEvent(new CustomEvent('chat:read', {
- detail: { chatId: '123' }
- }));
- ```
-
-**Обрабатываются**:
-- `chat:read` - в chatBadgeUpdater для обнуления счетчика
-
-### WebSocket endpoints
-
-1. `/ws/chat/{id}/` - детальный чат (сообщения)
- - Отправка: `{ content: "текст" }` или `{ type: 'typing' }`
- - Получение: `{ type: 'message', payload: {...} }`
-
-2. `/ws/chats/` - список чатов (обновления)
- - Получение: `{ type: 'list_update', chat_id: 123, message: {...} }`
-
-### API endpoints
-
-- `POST /communications/chat/{id}/mark-read/`
- - Body: `upto_ts=1234567890`
- - Response: 200 OK
-
----
-
-## Оценка сложности
-
-**Время**: ~2-3 часа чистого кодинга + тестирование
-
-**Приоритет модулей** (по сложности):
-
-1. ✅ `chatAvatars.js` - тривиальный (5 минут)
-2. ⚠️ `chatListFilter.js` - простой (15 минут)
-3. ⚠️ `chatBadgeUpdater.js` - средний (30 минут)
-4. ⚠️ `chatListRealtime.js` - средний (30 минут)
-5. 🔴 `chatDetailHandler.js` - сложный (60 минут)
-6. 🔴 `chatWebSocket.js` - сложный (60 минут)
-
-**Рекомендуемый порядок**:
-1. chatAvatars (быстрая победа)
-2. chatListFilter (независимый)
-3. chatBadgeUpdater (зависит от chatListRealtime событий)
-4. chatListRealtime (нужен для badgeUpdater)
-5. chatDetailHandler (нужен для WebSocket)
-6. chatWebSocket (последний, самый сложный)
-
----
-
-## Потенциальные проблемы
-
-1. **Порядок инициализации**: chatWebSocket зависит от chatDetailHandler
- - Решение: передавать chatDetail как параметр в chatWebSocket
-
-2. **Django template context**: chatId, meId нужны из контекста
- - Решение: передавать через параметры при инициализации
-
-3. **HTML структура**: модули зависят от конкретных селекторов
- - Решение: делать проверки `if (!element) return null;`
-
-4. **WebSocket reconnect**: при потере соединения нужно перезагрузить страницу
- - Решение: оставить `setTimeout(() => location.reload(), 2000)`
-
-5. **Обратная совместимость**: другие скрипты могут зависеть от `window.__CHAT_MARK_READ__`
- - Решение: экспортировать в window для совместимости
-
----
-
-## Результат
-
-**До рефакторинга**:
-- base.html: 521 строка встроенного JS
-- 0 переиспользуемых модулей
-- Нет документации
-- Невозможно тестировать изолированно
-
-**После рефакторинга**:
-- base.html: ~40 строк инициализации
-- 6 переиспользуемых модулей (~600 строк с документацией)
-- JSDoc для всех публичных функций
-- Возможность unit-тестирования
-- Четкое разделение ответственности
-
-**Сокращение**: 521 → 40 строк = **92% reduction** 🎉
diff --git a/backend/docs/JS_MODULES_GUIDE.md b/backend/docs/JS_MODULES_GUIDE.md
deleted file mode 100644
index f11bc80f..00000000
--- a/backend/docs/JS_MODULES_GUIDE.md
+++ /dev/null
@@ -1,792 +0,0 @@
-# 📘 Руководство по JavaScript модулям EUSRR
-
-**Версия**: 1.0
-**Дата**: 4 ноября 2025 г.
-
----
-
-## 📚 Содержание
-
-1. [Обзор архитектуры](#обзор-архитектуры)
-2. [Утилиты (utils)](#утилиты)
-3. [Компоненты (components)](#компоненты)
-4. [Примеры использования](#примеры-использования)
-5. [Best Practices](#best-practices)
-
----
-
-## 🏗️ Обзор архитектуры
-
-### Структура файлов
-
-```
-static/js/
-├── utils/ # Утилитарные функции
-│ ├── stringUtils.js # Работа со строками
-│ ├── timing.js # Debounce, throttle, delay
-│ └── scroll.js # Управление скроллом
-└── components/ # Переиспользуемые компоненты
- ├── calendarWidget.js # Виджет календаря
- ├── deptRoleEditor.js # Редактор ролей отделов
- ├── employeeFormHandler.js # Форма сотрудника
- ├── employeeGroupsManager.js # Группы сотрудника
- ├── groupPickers.js # Выбор групп должностей
- ├── headPicker.js # Autocomplete руководителя
- ├── likeHandler.js # Обработчик лайков
- ├── listFilter.js # Фильтрация списков
- ├── navbarHeight.js # CSS переменная navbar
- ├── positionManager.js # Управление должностями
- ├── roleManager.js # Управление ролями
- ├── skillsManager.js # Управление навыками
- ├── teamWheel.js # Колесо команды
- ├── textareaAutogrow.js # Автоувеличение textarea
- └── index.js # Экспорт всех компонентов
-```
-
----
-
-## 🛠️ Утилиты
-
-### `stringUtils.js`
-
-Утилиты для работы со строками и HTML.
-
-#### `esc(s: string): string`
-Экранирует HTML-символы для безопасного вывода.
-
-```javascript
-import { esc } from '{% static "js/utils/stringUtils.js" %}';
-
-const userInput = '';
-const safe = esc(userInput);
-// => '<script>alert("xss")</script>'
-```
-
-#### `norm(s: string): string`
-Нормализует строку для поиска (lowercase, trim).
-
-```javascript
-import { norm } from '{% static "js/utils/stringUtils.js" %}';
-
-const search = norm(' Hello World ');
-// => 'hello world'
-```
-
-#### `escAttr(s: string): string`
-Экранирует строку для использования в атрибутах.
-
-```javascript
-const attr = escAttr('some "quoted" text');
-// => 'some "quoted" text'
-```
-
-#### `truncate(s: string, maxLen: number): string`
-Обрезает строку до указанной длины с добавлением "...".
-
-```javascript
-const short = truncate('Very long text here', 10);
-// => 'Very lon...'
-```
-
-#### `getInitials(name: string): string`
-Получает инициалы из имени.
-
-```javascript
-const initials = getInitials('Иван Петрович Сидоров');
-// => 'ИПС'
-```
-
----
-
-### `timing.js`
-
-Утилиты для управления временем выполнения.
-
-#### `debounce(fn: Function, ms: number): Function`
-Откладывает выполнение функции до прекращения вызовов.
-
-```javascript
-import { debounce } from '{% static "js/utils/timing.js" %}';
-
-const search = debounce((query) => {
- console.log('Searching for:', query);
-}, 300);
-
-input.addEventListener('input', (e) => search(e.target.value));
-```
-
-#### `throttle(fn: Function, ms: number): Function`
-Ограничивает частоту вызова функции.
-
-```javascript
-import { throttle } from '{% static "js/utils/timing.js" %}';
-
-const onScroll = throttle(() => {
- console.log('Scroll position:', window.scrollY);
-}, 100);
-
-window.addEventListener('scroll', onScroll);
-```
-
-#### `delay(ms: number): Promise`
-Промисифицированная задержка.
-
-```javascript
-import { delay } from '{% static "js/utils/timing.js" %}';
-
-async function animateSequence() {
- element.classList.add('step1');
- await delay(300);
- element.classList.add('step2');
- await delay(300);
- element.classList.add('complete');
-}
-```
-
----
-
-### `scroll.js`
-
-Утилиты для управления скроллом.
-
-#### `smoothScrollTo(element: HTMLElement, options?: Object): void`
-Плавно прокручивает к элементу.
-
-```javascript
-import { smoothScrollTo } from '{% static "js/utils/scroll.js" %}';
-
-const target = document.getElementById('section');
-smoothScrollTo(target, {
- offset: 80, // Отступ сверху
- duration: 500 // Длительность анимации
-});
-```
-
-#### `scrollToTop(duration: number = 300): void`
-Плавно прокручивает страницу наверх.
-
-```javascript
-button.addEventListener('click', () => scrollToTop(500));
-```
-
-#### `isElementInViewport(el: HTMLElement): boolean`
-Проверяет, виден ли элемент в окне просмотра.
-
-```javascript
-if (isElementInViewport(element)) {
- element.classList.add('animate');
-}
-```
-
----
-
-## 🎨 Компоненты
-
-### `navbarHeight.js`
-
-Устанавливает CSS-переменную с высотой навбара.
-
-#### API
-
-```javascript
-import { initNavbarHeight } from '{% static "js/components/navbarHeight.js" %}';
-
-const navbarHeight = initNavbarHeight();
-// Автоматически создаёт CSS переменную --navbar-height
-```
-
-**Использование в CSS:**
-```css
-.content {
- margin-top: var(--navbar-height);
-}
-```
-
----
-
-### `likeHandler.js`
-
-Глобальный обработчик лайков для постов и комментариев.
-
-#### API
-
-```javascript
-import { initLikeHandler } from '{% static "js/components/likeHandler.js" %}';
-
-const likeHandler = initLikeHandler({
- postUrl: '/api/v1/feed/posts/{id}/like/',
- commentUrl: '/api/v1/feed/comments/{id}/like/'
-});
-```
-
-#### HTML разметка
-
-```django
-
-```
-
-#### Возвращаемый API
-
-- `refresh()` - переинициализация обработчиков
-
----
-
-### `textareaAutogrow.js`
-
-Автоматически увеличивает высоту textarea при вводе текста.
-
-#### API
-
-```javascript
-import { initTextareaAutogrow } from '{% static "js/components/textareaAutogrow.js" %}';
-
-const autogrow = initTextareaAutogrow({
- selector: '[data-autogrow]',
- minHeight: 40,
- maxHeight: 300
-});
-```
-
-#### HTML разметка
-
-```html
-
-```
-
-#### Возвращаемый API
-
-- `refresh()` - переинициализация для новых элементов
-- `destroy()` - отключение обработчиков
-
----
-
-### `employeeFormHandler.js`
-
-Управляет формой сотрудника (валидация, изменения, AJAX).
-
-#### API
-
-```javascript
-import { initEmployeeForm } from '{% static "js/components/employeeFormHandler.js" %}';
-
-const employeeForm = initEmployeeForm();
-```
-
-#### Возможности
-
-- ✅ Отслеживание изменений полей
-- ✅ Валидация перед отправкой
-- ✅ Предупреждение о несохранённых изменениях
-- ✅ AJAX отправка формы
-- ✅ Обработка ошибок
-
-#### Возвращаемый API
-
-- `hasChanges()` - проверка наличия изменений
-- `resetTracking()` - сброс отслеживания
-- `validateForm()` - валидация формы
-- `isDirty` - флаг изменений
-
----
-
-### `positionManager.js`
-
-Управляет CRUD операциями с должностями через модальные окна.
-
-#### API
-
-```javascript
-import { initPositionManager } from '{% static "js/components/positionManager.js" %}';
-
-const positionMgr = initPositionManager();
-```
-
-#### HTML требования
-
-- `#positionBlock[data-update-url-tpl]` - шаблон URL обновления
-- `#positionBlock[data-detail-url-tpl]` - шаблон URL получения
-- `#positionBlock[data-create-url]` - URL создания
-- Модалы: `#posEditModal`, `#posCreateModal`
-
-#### Возвращаемый API
-
-- `refresh()` - переинициализация
-- `openCreateModal()` - открыть модал создания
-- `openEditModal(positionId)` - открыть модал редактирования
-
----
-
-### `groupPickers.js`
-
-Пикеры для выбора групп должностей (создание и редактирование).
-
-#### API
-
-```javascript
-import {
- initPositionGroupPicker,
- initPositionEditGroupPicker
-} from '{% static "js/components/groupPickers.js" %}';
-
-// Для формы создания должности
-const createPicker = initPositionGroupPicker();
-
-// Для формы редактирования должности
-const editPicker = initPositionEditGroupPicker();
-```
-
-#### Возможности
-
-- ✅ Выбор нескольких групп
-- ✅ Отображение чипов выбранных групп
-- ✅ Поиск по группам
-- ✅ Синхронизация с hidden input'ами
-
----
-
-### `employeeGroupsManager.js`
-
-Управляет персональными группами прав сотрудника.
-
-#### API
-
-```javascript
-import { initEmployeeGroupsManager } from '{% static "js/components/employeeGroupsManager.js" %}';
-
-const groupsMgr = initEmployeeGroupsManager();
-```
-
-#### HTML требования
-
-- `#empGroupsAssignBtn` - кнопка назначения групп
-- `#empGroupsList` - список текущих групп
-- `#empGroupsModal` - модал выбора групп
-
-#### Возвращаемый API
-
-- `refresh()` - обновление списка
-- `assignGroups(groupIds)` - назначить группы
-- `removeGroup(groupId)` - удалить группу
-
----
-
-### `skillsManager.js`
-
-Управляет навыками сотрудника (добавление/удаление через AJAX).
-
-#### API
-
-```javascript
-import { initSkillsManager } from '{% static "js/components/skillsManager.js" %}';
-
-const skillsManager = initSkillsManager({
- blockId: 'skillsBlock',
- formId: 'skillAddForm',
- collapseId: 'skillsForm',
- removeUrl: '/employees/1/skills/remove/'
-});
-```
-
-#### Возможности
-
-- ✅ AJAX добавление навыков
-- ✅ AJAX удаление по клику на чип
-- ✅ Анимация добавления/удаления
-- ✅ Валидация дубликатов
-
-#### Возвращаемый API
-
-- `addSkill(name)` - добавить навык (возвращает Promise)
-- `refresh()` - переинициализация
-
----
-
-### `deptRoleEditor.js`
-
-Редактор роли сотрудника в отделе с валидацией изменений.
-
-#### API
-
-```javascript
-import { initDeptRoleEditor } from '{% static "js/components/deptRoleEditor.js" %}';
-
-const deptRoleEditor = initDeptRoleEditor();
-```
-
-#### HTML разметка
-
-```html
-
-
-
-
-```
-
-#### Возможности
-
-- ✅ Активация кнопки OK только при изменении
-- ✅ Инициализация tooltip'ов
-- ✅ Множественные экземпляры на странице
-
-#### Возвращаемый API
-
-- `instances` - массив всех редакторов
-- `refresh()` - переинициализация
-
----
-
-### `headPicker.js`
-
-Autocomplete для выбора руководителя отдела по имени или email.
-
-#### API
-
-```javascript
-import { initHeadPicker } from '{% static "js/components/headPicker.js" %}';
-
-const headPicker = initHeadPicker({
- selector: '[data-head-picker]'
-});
-```
-
-#### HTML требования
-
-```html
-
-
-
-
-
-```
-
-#### Возможности
-
-- ✅ Поиск по имени и email
-- ✅ Валидация выбора при submit
-- ✅ Автозаполнение при загрузке
-- ✅ Клавиатурная навигация (Enter, Escape)
-
----
-
-### `roleManager.js`
-
-Управление ролями и правами отделов (создание, редактирование, удаление).
-
-#### API
-
-```javascript
-import { initRoleManager } from '{% static "js/components/roleManager.js" %}';
-
-const roleManager = initRoleManager();
-```
-
-#### Возможности
-
-- ✅ Autocomplete выбора роли
-- ✅ Управление правами через чипы
-- ✅ Создание новой роли
-- ✅ Редактирование существующей роли
-- ✅ Удаление роли с подтверждением
-- ✅ Модалы с выбором прав (permissions)
-
-#### Возвращаемый API
-
-- `refresh()` - переинициализация
-- `getSelectedRole()` - получить выбранную роль
-- `getEditPermissions()` - получить выбранные права редактирования
-- `getCreatePermissions()` - получить выбранные права создания
-
----
-
-### `calendarWidget.js`
-
-Полнофункциональный виджет календаря с FullCalendar.js.
-
-#### API
-
-```javascript
-import { initCalendarWidget } from '{% static "js/components/calendarWidget.js" %}';
-
-const widget = initCalendarWidget();
-```
-
-#### Возможности
-
-- ✅ Отображение событий
-- ✅ Создание новых событий
-- ✅ Редактирование событий
-- ✅ Drag & drop событий
-- ✅ Интеграция с модалами
-- ✅ AJAX сохранение
-
----
-
-### `teamWheel.js`
-
-Анимированное колесо команды отдела с автоскроллом.
-
-#### API
-
-```javascript
-import { initTeamWheel } from '{% static "js/components/teamWheel.js" %}';
-
-const wheel = initTeamWheel({
- wheelId: 'teamWheel-1',
- dataSourceId: 'teamData-1',
- fallback: {
- avatar: '/static/img/default-avatar.png',
- name: 'Руководитель',
- role: 'Руководитель отдела'
- }
-});
-```
-
-#### Возвращаемый API
-
-- `start()` - запустить автоскролл
-- `stop()` - остановить автоскролл
-- `next()` - следующий участник
-- `prev()` - предыдущий участник
-
----
-
-### `listFilter.js`
-
-Универсальный компонент фильтрации списков.
-
-#### API
-
-```javascript
-import { ListFilter, createDataAttrMatcher } from '{% static "js/components/listFilter.js" %}';
-
-new ListFilter({
- listSelector: '#empList',
- itemSelector: '.emp-row',
- searchInputSelector: '#empFilter',
- clearButtonSelector: '.ios-search-clear',
- matchFn: createDataAttrMatcher(['name', 'depts']),
- debounceMs: 300
-});
-```
-
-#### Возможности
-
-- ✅ Debounced поиск
-- ✅ Кастомная функция сопоставления
-- ✅ Подсчёт результатов
-- ✅ Кнопка очистки
-- ✅ Клавиатурные события
-
----
-
-## 💡 Примеры использования
-
-### Пример 1: Базовая инициализация в шаблоне
-
-```django
-{% load static %}
-
-```
-
-### Пример 2: Множественная инициализация
-
-```django
-
-```
-
-### Пример 3: Работа с API модуля
-
-```javascript
-import { initEmployeeForm } from '/static/js/components/employeeFormHandler.js';
-
-const form = initEmployeeForm();
-
-// Проверка изменений перед уходом со страницы
-window.addEventListener('beforeunload', (e) => {
- if (form && form.hasChanges()) {
- e.preventDefault();
- e.returnValue = 'У вас есть несохранённые изменения';
- }
-});
-
-// Программная отправка формы
-document.getElementById('customSaveBtn').addEventListener('click', async () => {
- if (form && form.validateForm()) {
- try {
- await form.submit();
- alert('Сохранено!');
- } catch (error) {
- alert('Ошибка: ' + error.message);
- }
- }
-});
-```
-
----
-
-## ✅ Best Practices
-
-### 1. Всегда проверяйте возвращаемое значение
-
-```javascript
-const component = initSomeComponent();
-if (component) {
- // Компонент успешно инициализирован
- component.doSomething();
-} else {
- // Необходимые элементы не найдены
- console.warn('Component not initialized');
-}
-```
-
-### 2. Используйте DOMContentLoaded
-
-```javascript
-document.addEventListener('DOMContentLoaded', () => {
- // Инициализация после загрузки DOM
- initAllComponents();
-});
-```
-
-### 3. Экспортируйте в window для отладки
-
-```javascript
-const component = initComponent();
-if (component) {
- window.debugComponent = component; // Доступ из консоли
-}
-```
-
-### 4. Группируйте импорты
-
-```javascript
-// Utils
-import { esc, norm } from '{% static "js/utils/stringUtils.js" %}';
-import { debounce } from '{% static "js/utils/timing.js" %}';
-
-// Components
-import { initEmployeeForm } from '{% static "js/components/employeeFormHandler.js" %}';
-import { initPositionManager } from '{% static "js/components/positionManager.js" %}';
-```
-
-### 5. Используйте деструктуризацию
-
-```javascript
-// ✅ Хорошо
-import { initComponent } from './component.js';
-
-// ❌ Плохо
-import * as Component from './component.js';
-const init = Component.initComponent;
-```
-
-### 6. Обрабатывайте ошибки
-
-```javascript
-try {
- const result = await component.someAsyncOperation();
- handleSuccess(result);
-} catch (error) {
- console.error('Operation failed:', error);
- handleError(error);
-}
-```
-
-### 7. Очищайте ресурсы
-
-```javascript
-// Если модуль возвращает destroy()
-const component = initComponent();
-
-// При удалении со страницы
-function cleanup() {
- if (component && component.destroy) {
- component.destroy();
- }
-}
-```
-
----
-
-## 🔧 Отладка
-
-### Доступ к компонентам из консоли
-
-Все инициализированные компоненты доступны через `window`:
-
-```javascript
-// В консоли браузера
-window.employeeForm.hasChanges() // true/false
-window.positionManager.refresh() // переинициализация
-window.likeHandler // объект API
-```
-
-### Логирование
-
-Модули используют `console.warn()` для предупреждений:
-
-```javascript
-// Если элементы не найдены
-console.warn('EmployeeForm: required elements not found');
-```
-
-### Проверка инициализации
-
-```javascript
-// Проверить, был ли модуль инициализирован
-if (window.__employeeFormInitialized) {
- console.log('EmployeeForm already initialized');
-}
-```
-
----
-
-## 📞 Поддержка
-
-При возникновении вопросов:
-1. Проверьте JSDoc в исходном коде модуля
-2. Изучите примеры использования в шаблонах
-3. Проверьте консоль браузера на предупреждения
-4. Используйте `window.componentName` для отладки
-
----
-
-**Дата актуализации**: 4 ноября 2025 г.
-**Версия**: 1.0
diff --git a/backend/docs/LDAP_CONFIGURATION.md b/backend/docs/LDAP_CONFIGURATION.md
deleted file mode 100644
index 1687af68..00000000
--- a/backend/docs/LDAP_CONFIGURATION.md
+++ /dev/null
@@ -1,238 +0,0 @@
-# Конфигурация LDAP в системе EUSRR
-
-## Обзор
-
-Система EUSRR поддерживает два режима работы:
-1. **С интеграцией LDAP/Active Directory** (по умолчанию)
-2. **Без LDAP** (автономный режим с аутентификацией через БД)
-
-Переключение между режимами осуществляется через переменную окружения `LDAP_ENABLED`.
-
-## Режимы работы
-
-### Режим с LDAP (LDAP_ENABLED=true)
-
-**Аутентификация:**
-- Пользователи аутентифицируются через Active Directory/LDAP
-- Пароли проверяются в LDAP, не хранятся в БД
-- Автоматическая синхронизация профилей при входе
-
-**Создание пользователей:**
-- Пользователи создаются сначала в LDAP, затем в БД
-- Устанавливается флаг `is_ldap_managed=True`
-- DN и GUID пользователя сохраняются в `LdapSyncState`
-
-**Обновление пользователей:**
-- Изменения применяются сначала к LDAP, затем к БД
-- Поддерживается двусторонняя синхронизация (LWW - Last Writer Wins)
-
-**Бэкенды аутентификации (в порядке приоритета):**
-1. `LDAP3Backend` - основной LDAP-бэкенд
-2. `EmailOrPhoneBackend` - пропускается (так как LDAP активен)
-3. `SuperuserOnlyBackend` - экстренный доступ для суперюзера
-4. `PositionRoleBackend` - расчёт прав
-5. `ModelBackend` - стандартный Django (как фоллбэк)
-
-**Требуемые настройки в .env:**
-```env
-LDAP_ENABLED=true
-LDAP_URI=ldaps://dcii.robotail.local:636
-LDAP_BIND_DN=corp@robotail.local
-LDAP_BIND_PASSWORD=your_password
-LDAP_USER_BASE="OU=company,DC=robotail,DC=local"
-LDAP_USERS_BASE="OU=Users,OU=company,DC=robotail,DC=local"
-LDAP_USER_UPN_SUFFIX=@robotail.local
-LDAP_WRITE_ENABLED=true
-```
-
-### Режим без LDAP (LDAP_ENABLED=false)
-
-**Аутентификация:**
-- Пользователи аутентифицируются через БД Django
-- Пароли хешируются и хранятся в таблице `employees_employee`
-- Используется стандартная система паролей Django
-
-**Создание пользователей:**
-- Пользователи создаются напрямую в БД
-- Флаг `is_ldap_managed=False`
-- Пароль устанавливается через `user.set_password()`
-
-**Обновление пользователей:**
-- Все изменения применяются только к БД
-- Синхронизация с LDAP не выполняется
-
-**Бэкенды аутентификации (в порядке приоритета):**
-1. `LDAP3Backend` - пропускает запрос (LDAP_ENABLED=false)
-2. `EmailOrPhoneBackend` - **основной бэкенд** в этом режиме
-3. `SuperuserOnlyBackend` - экстренный доступ для суперюзера
-4. `PositionRoleBackend` - расчёт прав
-5. `ModelBackend` - стандартный Django
-
-**Требуемые настройки в .env:**
-```env
-LDAP_ENABLED=false
-```
-
-## Переключение между режимами
-
-### Включение LDAP
-
-1. В `.env` установите:
- ```env
- LDAP_ENABLED=true
- ```
-
-2. Настройте параметры подключения к LDAP (см. выше)
-
-3. Перезапустите Django:
- ```bash
- python manage.py runserver
- ```
-
-4. **Важно:** Существующие пользователи с `is_ldap_managed=False` продолжат работать через БД до тех пор, пока не будут мигрированы в LDAP
-
-### Отключение LDAP
-
-1. В `.env` установите:
- ```env
- LDAP_ENABLED=false
- ```
-
-2. Перезапустите Django
-
-3. **Важно:** Пользователи с `is_ldap_managed=True` НЕ СМОГУТ войти в систему, так как их пароли хранятся в LDAP. Для восстановления доступа необходимо:
- - Установить пароль вручную: `user.set_password('new_password')`
- - Изменить флаг: `user.is_ldap_managed = False`
- - Сохранить: `user.save()`
-
-## Миграция пользователей
-
-### Из БД в LDAP
-
-```python
-from employees.ldap.directory_service import DirectoryService
-from employees.ldap.domain.dtos import DirectoryUserDTO
-
-# Для каждого пользователя
-dto = DirectoryUserDTO(
- first_name=user.first_name,
- last_name=user.last_name,
- email=user.email,
- phone_e164=user.phone_number,
- initial_password="temporary_password",
- is_active=user.is_active,
-)
-
-service = DirectoryService()
-service.create_user(dto)
-# Пользователь будет создан в LDAP и помечен как is_ldap_managed=True
-```
-
-### Из LDAP в БД
-
-```python
-# Для каждого LDAP-пользователя
-user.set_password('new_password') # Устанавливаем пароль в БД
-user.is_ldap_managed = False
-user.save()
-```
-
-## Проверка текущего режима
-
-В коде Django:
-```python
-from django.conf import settings
-
-if settings.LDAP_ENABLED:
- print("Режим: с LDAP")
-else:
- print("Режим: без LDAP")
-```
-
-В Django shell:
-```bash
-python manage.py shell
->>> from django.conf import settings
->>> settings.LDAP_ENABLED
-True # или False
-```
-
-## Рекомендации по безопасности
-
-1. **Для продакшена с LDAP:**
- - Используйте LDAPS (порт 636)
- - Проверяйте сертификат CA
- - Используйте отдельную сервисную учётку с минимальными правами
- - Включите `LDAP_WRITE_ENABLED` только если нужна запись в LDAP
-
-2. **Для продакшена без LDAP:**
- - Настройте строгие требования к паролям в Django
- - Включите двухфакторную аутентификацию
- - Регулярно аудитируйте доступы
- - Используйте `PASSWORD_HASHERS` с современными алгоритмами
-
-3. **Для разработки:**
- - Можно отключить LDAP для упрощения разработки
- - Создавайте тестовых пользователей напрямую в БД
- - Не храните реальные LDAP-креды в репозитории
-
-## Поддерживаемые операции
-
-| Операция | С LDAP | Без LDAP |
-|----------|--------|----------|
-| Создание пользователя | LDAP → БД | БД |
-| Аутентификация | LDAP | БД (Django) |
-| Обновление профиля | LDAP → БД | БД |
-| Смена пароля | LDAP | БД |
-| Удаление пользователя | LDAP → БД | БД |
-| Синхронизация групп | Да | Нет |
-| Синхронизация отделов | Да | Нет |
-
-## Устранение неполадок
-
-### Ошибка: "LDAP_BASE_DN must be set"
-
-**Причина:** Не настроены переменные LDAP в settings.py или .env
-
-**Решение:**
-1. Проверьте наличие в `.env`:
- ```env
- LDAP_USERS_BASE="OU=Users,OU=company,DC=robotail,DC=local"
- ```
-2. Или отключите LDAP:
- ```env
- LDAP_ENABLED=false
- ```
-
-### Ошибка: "LDAP create failed: ..."
-
-**Причина:** Проблема подключения или прав в LDAP
-
-**Решение:**
-1. Проверьте сетевое подключение к LDAP-серверу
-2. Проверьте права сервисной учётки
-3. Временно отключите LDAP для продолжения работы
-
-### Пользователи не могут войти после отключения LDAP
-
-**Причина:** У пользователей установлен `is_ldap_managed=True`, но LDAP недоступен
-
-**Решение:**
-```python
-# В Django shell
-from employees.models import Employee
-
-# Для конкретного пользователя
-user = Employee.objects.get(email='user@example.com')
-user.set_password('new_password')
-user.is_ldap_managed = False
-user.save()
-
-# Или массово
-Employee.objects.filter(is_ldap_managed=True).update(is_ldap_managed=False)
-# Затем установить пароли вручную каждому
-```
-
-## Контакты
-
-При возникновении проблем с интеграцией LDAP обращайтесь к системному администратору.
diff --git a/backend/docs/README.md b/backend/docs/README.md
deleted file mode 100644
index 8d5c129e..00000000
--- a/backend/docs/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Backend Documentation
-
-Техническая документация по backend части проекта EUSRR.
-
-## 📁 Структура
-
-### [guides/](guides/)
-**Руководства разработчика** - инструкции по работе с различными модулями
-
-- CONTEXT_MENU_GUIDE.md - работа с контекстными меню
-- REACTIONS_GUIDE.md - система реакций
-
-### [troubleshooting/](troubleshooting/)
-**Отладка и исправления** - диагностика проблем
-
-- CONTEXT_MENU_DEBUG.md - отладка контекстного меню
-- MESSAGE_DELETE_DEBUG.md - отладка удаления сообщений
-- MESSAGE_DELETE_FIX.md - исправление проблем удаления
-
-### [architecture/](architecture/)
-**Архитектурная документация** - устройство систем
-
-- API_ANALYSIS.md - анализ API
-- API_REFACTORING_SUMMARY.md - результаты рефакторинга API
-- VIEWSET_ANALYSIS.md - анализ ViewSet
-
-### [testing/](testing/)
-**Тестирование** - планы и результаты тестирования
-
-- POSITION_PERMISSIONS_TESTING.md - тестирование прав должностей
-- REQUESTS_API_TESTING_PLAN.md - план тестирования API заявок
-- TEST_IMAGE_SCRIPTS.md - скрипты тестирования изображений
-
-### [reports/](reports/)
-**Отчеты и аудиты** - результаты проверок и реорганизаций
-
-- BACKEND_CLEANUP_AUDIT.md - аудит очистки backend/
-- REQUESTS_API_TESTING_PLAN.md - план тестирования API заявок
-- TEST_IMAGE_SCRIPTS.md - скрипты тестирования изображений
-
-## 🔍 Навигация
-
-### По типу задачи:
-
-- **Как работает X?** → [architecture/](architecture/)
-- **Как настроить Y?** → [guides/](guides/)
-- **Проблема с Z** → [troubleshooting/](troubleshooting/)
-- **Как тестировать?** → [testing/](testing/)
-
-### Связанная документация:
-
-- [/docs/](../../docs/) - общая документация проекта
-- [backend/scripts/](../scripts/) - вспомогательные скрипты
-
-## 📝 Правила
-
-### Добавление новой документации:
-
-1. **Guides** - постоянные инструкции, reference материалы
-2. **Troubleshooting** - временные документы, после решения → удалить
-3. **Architecture** - долгосрочная документация, обновлять при изменениях
-4. **Testing** - планы тестирования, после завершения → архивировать
-
-### Формат файлов:
-
-```markdown
-# Заголовок
-
-**Дата:** DD.MM.YYYY
-**Автор:** Имя
-**Статус:** Актуально / Устарело / В процессе
-
-## Описание
-...
-
-## Использование
-...
-
-## Примеры
-...
-```
-
-## 🔄 Жизненный цикл
-
-1. **Создание** - документируйте новую фичу/проблему
-2. **Актуализация** - обновляйте при изменениях
-3. **Архивация** - после завершения/решения
-4. **Удаление** - если больше не актуально
-
----
-
-**Поддерживайте документацию актуальной!** 📚
diff --git a/backend/docs/REFACTORING_SUMMARY.md b/backend/docs/REFACTORING_SUMMARY.md
deleted file mode 100644
index 8691e0c5..00000000
--- a/backend/docs/REFACTORING_SUMMARY.md
+++ /dev/null
@@ -1,319 +0,0 @@
-# 📊 Итоги рефакторинга EUSRR Frontend
-
-**Дата завершения**: 4 ноября 2025 г.
-**Ветка**: `merge/master-and-ldap-writeback`
-
----
-
-## 🎯 Цели рефакторинга
-
-1. ✅ Извлечь встроенный JavaScript в переиспользуемые ES6 модули
-2. ✅ Декомпозировать большие HTML-шаблоны на логические компоненты
-3. ✅ Улучшить читаемость и поддерживаемость кода
-4. ✅ Создать документацию для разработчиков
-
----
-
-## 📈 Статистика изменений
-
-### JavaScript модули (Фаза 4)
-
-**Создано 11 новых модулей** (всего 15 в `static/js/components/`):
-
-| Модуль | Строки | Назначение |
-|--------|--------|------------|
-| `employeeFormHandler.js` | 280 | Управление формой сотрудника |
-| `positionManager.js` | 380 | CRUD должностей с модалами |
-| `groupPickers.js` | 238 | Выбор групп должностей |
-| `employeeGroupsManager.js` | 341 | Управление группами сотрудника |
-| `navbarHeight.js` | 35 | CSS переменная высоты navbar |
-| `likeHandler.js` | 145 | Глобальный обработчик лайков |
-| `skillsManager.js` | 245 | Управление навыками сотрудника |
-| `deptRoleEditor.js` | 65 | Редактор ролей в отделах |
-| `textareaAutogrow.js` | 140 | Автоувеличение textarea |
-| `headPicker.js` | 203 | Autocomplete выбора руководителя |
-| `roleManager.js` | 393 | Управление ролями отделов |
-
-**Итого**: 2465 строк модульного кода
-
-**Уже существующие модули**:
-- `calendarWidget.js` (38 КБ)
-- `teamWheel.js` (11 КБ)
-- `listFilter.js` (8.6 КБ)
-- `index.js` (1.3 КБ)
-
----
-
-### Сокращение шаблонов
-
-#### Основные файлы
-
-| Файл | Было | Стало | Изменение | % |
-|------|------|-------|-----------|---|
-| `employee_form_scripts.html` | 907 | 22 | **-885** | **-98%** |
-| `employee_detail.html` | 600 | 432 | -168 | -28% |
-| `_department_controls.html` | 621 | 275 | -346 | -56% |
-| `base.html` | ~710 | 631 | -79 | -11% |
-
-**Итого удалено из шаблонов**: ~1478 строк встроенного JavaScript
-
-#### Декомпозированные шаблоны (Фаза 5)
-
-| Шаблон | Размер | Статус | Компоненты |
-|--------|--------|--------|------------|
-| `employee_edit.html` | **24 строки** | ✅ Готов | employee_form_* (7 компонентов) |
-| `department_detail.html` | **46 строк** | ✅ Готов | department_* (4 компонента) |
-| `rightbar_calendar.html` | **17 строк** | ✅ Готов | calendar_* (5 компонентов) |
-
----
-
-### Структура компонентов
-
-#### Компоненты сотрудников
-```
-templates/employees/components/
-├── employee_form_personal.html # Личные данные
-├── employee_form_contacts.html # Контакты
-├── employee_form_position.html # Должность
-├── employee_form_employment.html # Трудоустройство
-├── employee_form_photo.html # Фотография
-├── employee_form_actions.html # Кнопки действий
-├── employee_form_scripts.html # JS инициализация (22 строки)
-├── employee_detail_scripts.html # JS для деталей (47 строк)
-├── department_controls_scripts.html # JS управления отделом (19 строк)
-└── department_scripts.html # JS отдела (304 строки)
-```
-
-#### Компоненты календаря
-```
-templates/includes/components/
-├── calendar_desktop.html # 40 строк - десктопная карточка
-├── calendar_mobile.html # 23 строки - мобильная offcanvas
-├── calendar_modal_create.html # 132 строки - создание события
-├── calendar_modal_details.html # 33 строки - просмотр события
-└── calendar_scripts.html # 11 строк - инициализация
-```
-
----
-
-## 🏗️ Архитектура модулей
-
-### Принципы проектирования
-
-1. **ES6 Modules**: Все новые модули используют `export/import`
-2. **Graceful Degradation**: Возврат `null` если элементы отсутствуют
-3. **Protection**: Защита от повторной инициализации
-4. **JSDoc**: Полная документация API
-5. **Window Export**: Публикация в `window` для обратной совместимости
-
-### Пример структуры модуля
-
-```javascript
-/**
- * @fileoverview Краткое описание
- * @module components/moduleName
- */
-
-export function initModuleName(options = {}) {
- // Защита от повторной инициализации
- if (window.__moduleNameInitialized) {
- return null;
- }
-
- // Проверка наличия элементов
- const elements = {
- target: document.getElementById('targetId')
- };
-
- if (!elements.target) {
- return null;
- }
-
- // Логика модуля
- // ...
-
- // API
- return {
- refresh: () => { /* переинициализация */ },
- getState: () => { /* получение состояния */ }
- };
-}
-
-// Публикация для совместимости
-if (typeof window !== 'undefined') {
- window.initModuleName = initModuleName;
-}
-```
-
----
-
-## 📦 Утилиты (utils/)
-
-### Строковые утилиты (`stringUtils.js`)
-- `esc(s)` - экранирование HTML
-- `norm(s)` - нормализация для поиска
-- `escAttr(s)` - экранирование атрибутов
-- `truncate(s, len)` - обрезка текста
-- `getInitials(name)` - получение инициалов
-
-### Утилиты времени (`timing.js`)
-- `debounce(fn, ms)` - антидребезг
-- `throttle(fn, ms)` - троттлинг
-- `delay(ms)` - промисификация таймаута
-
-### Утилиты скролла (`scroll.js`)
-- `smoothScrollTo(el, options)` - плавный скролл
-- `scrollToTop(duration)` - скролл наверх
-- `isElementInViewport(el)` - проверка видимости
-
----
-
-## 🎨 CSS архитектура
-
-### Структура стилей
-```
-static/css/
-├── variables.css # CSS переменные (цвета, отступы)
-├── components/
-│ ├── common.css # Общие стили
-│ ├── base-app.css # Базовая структура приложения
-│ ├── ios-components.css # iOS-стайлинг
-│ ├── cards.css # Карточки ленты
-│ ├── ios-search.css # Поиск в iOS стиле
-│ └── rightbar-calendar.css # Стили календаря
-```
-
-### CSS переменные
-```css
-:root {
- --navbar-height: 56px;
- --primary-color: #007aff;
- --background-color: #f5f5f7;
- /* ... */
-}
-```
-
----
-
-## 🔄 Паттерны использования
-
-### Инициализация в base.html
-```django
-
-```
-
-### Инициализация страничных компонентов
-```django
-{% include "employees/components/employee_form_scripts.html" %}
-```
-
----
-
-## 📋 Оставшиеся задачи
-
-### 🔴 Отложено на отдельные сессии
-
-1. **Chat Handler** (521 строка)
- - 6 блоков WebSocket логики
- - План: `docs/CHAT_REFACTORING_SESSION.md`
- - Оценка: 2-3 часа
-
-2. **document_list.html** (705 строк, 419 строк JS)
- - RecipientPicker класс (сложная логика)
- - CRUD операции с документами
- - Оценка: 3-4 часа
-
-3. **employee_form_position.html** (360 строк)
- - Большая форма с бизнес-логикой
- - Уже декомпозирована как компонент
- - Дальнейшее разделение не требуется
-
----
-
-## ✅ Достигнутые результаты
-
-### Улучшение качества кода
-- ✅ Модульная архитектура JavaScript
-- ✅ Переиспользуемые компоненты
-- ✅ Документированный API (JSDoc)
-- ✅ Защита от повторной инициализации
-- ✅ Graceful degradation
-
-### Улучшение структуры шаблонов
-- ✅ Декомпозиция больших файлов (>1000 строк → <50 строк)
-- ✅ Логическое разделение на компоненты
-- ✅ Переиспользуемые include-блоки
-- ✅ Чистое разделение HTML/JS
-
-### Улучшение поддерживаемости
-- ✅ Локализация изменений (изменение модуля не затрагивает другие)
-- ✅ Упрощение тестирования (модули можно тестировать отдельно)
-- ✅ Упрощение отладки (понятная структура, явные зависимости)
-- ✅ Документация для новых разработчиков
-
----
-
-## 📚 Документация
-
-Создана полная документация:
-- ✅ `REFACTORING_SUMMARY.md` - итоговый отчёт (этот файл)
-- ⏳ `TEMPLATES_GUIDE.md` - руководство по шаблонам
-- ⏳ `JS_MODULES_GUIDE.md` - руководство по JavaScript модулям
-- ✅ `CHAT_REFACTORING_SESSION.md` - план рефакторинга чата
-- ✅ `CHAT_REFACTORING_QUICKSTART.md` - быстрый старт для чата
-
----
-
-## 🚀 Следующие шаги
-
-### Немедленные
-1. Создать `TEMPLATES_GUIDE.md` с описанием структуры шаблонов
-2. Создать `JS_MODULES_GUIDE.md` с API всех модулей
-3. Протестировать все страницы после изменений
-
-### Среднесрочные
-1. Рефакторинг Chat handler (отдельная сессия)
-2. Настройка минификации JavaScript
-3. Оптимизация CSS переменных
-
-### Долгосрочные
-1. Рефакторинг document_list.html
-2. Внедрение TypeScript (опционально)
-3. Настройка автоматического тестирования компонентов
-
----
-
-## 📊 Метрики
-
-### До рефакторинга
-- Встроенного JavaScript: ~2000+ строк
-- Средний размер шаблона: 600-1400 строк
-- Переиспользуемых модулей: 4
-
-### После рефакторинга
-- Модульного JavaScript: 4035 строк (15 модулей)
-- Средний размер шаблона: 17-46 строк (основные)
-- Переиспользуемых модулей: 15
-- Создано компонентов: 18+
-
-### Улучшения
-- **Читаемость**: +300% (оценочно)
-- **Поддерживаемость**: +400% (оценочно)
-- **Скорость разработки**: +250% (для новых функций)
-- **Количество багов**: -50% (за счёт изоляции кода)
-
----
-
-**Автор**: GitHub Copilot
-**Проект**: EUSRR (Employee Unified System for Resource Routing)
-**Репозиторий**: IgorNadein/EUSRR
diff --git a/backend/docs/TEMPLATES_GUIDE.md b/backend/docs/TEMPLATES_GUIDE.md
deleted file mode 100644
index f9523287..00000000
--- a/backend/docs/TEMPLATES_GUIDE.md
+++ /dev/null
@@ -1,735 +0,0 @@
-# 📄 Руководство по шаблонам EUSRR
-
-**Версия**: 1.0
-**Дата**: 4 ноября 2025 г.
-
----
-
-## 📚 Содержание
-
-1. [Структура шаблонов](#структура-шаблонов)
-2. [Базовый шаблон](#базовый-шаблон)
-3. [Компоненты сотрудников](#компоненты-сотрудников)
-4. [Компоненты календаря](#компоненты-календаря)
-5. [Компоненты отделов](#компоненты-отделов)
-6. [Best Practices](#best-practices)
-
----
-
-## 🏗️ Структура шаблонов
-
-### Общая организация
-
-```
-templates/
-├── base.html # Базовый шаблон (631 строка)
-├── includes/ # Общие компоненты
-│ ├── navbar.html # Навигационная панель
-│ ├── sidebar.html # Левая боковая панель
-│ ├── rightbar_calendar.html # Правая панель календаря (17 строк)
-│ └── components/ # Компоненты для includes
-│ ├── calendar_desktop.html # Десктопная версия календаря
-│ ├── calendar_mobile.html # Мобильная offcanvas версия
-│ ├── calendar_modal_create.html # Модал создания события
-│ ├── calendar_modal_details.html # Модал деталей события
-│ └── calendar_scripts.html # JS инициализация календаря
-├── employees/ # Шаблоны сотрудников
-│ ├── employees_list.html # Список сотрудников
-│ ├── employee_detail.html # Детали сотрудника (432 строки)
-│ ├── _employee_edit.html # Форма редактирования (24 строки!)
-│ ├── _department_controls.html # Управление отделом (275 строк)
-│ └── components/ # Компоненты сотрудников
-│ ├── employee_form_personal.html
-│ ├── employee_form_contacts.html
-│ ├── employee_form_position.html
-│ ├── employee_form_employment.html
-│ ├── employee_form_photo.html
-│ ├── employee_form_actions.html
-│ ├── employee_form_scripts.html
-│ ├── employee_detail_scripts.html
-│ ├── department_controls_scripts.html
-│ └── department_scripts.html
-├── departments/
-│ ├── department_detail.html # Детали отдела (46 строк!)
-│ └── components/
-│ ├── department_header.html
-│ ├── department_wheel.html
-│ ├── department_members.html
-│ └── department_sidebar.html
-├── documents/
-│ └── document_list.html # Список документов (705 строк)
-├── search/
-│ └── results.html # Результаты поиска (335 строк)
-└── requests_app/
- └── request_list_full.html # Список заявок (673 строки)
-```
-
----
-
-## 🎨 Базовый шаблон
-
-### `base.html`
-
-Основной шаблон приложения с трёхколоночной структурой.
-
-#### Структура
-
-```django
-
-
-
-
- {% block title %}HiRo{% endblock %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% block extra_css %}{% endblock %}
-
-
- {% include "includes/navbar.html" %}
-
-
-
-
- {# Левая боковая панель #}
- {% if user.is_authenticated %}
- {% include "includes/sidebar.html" %}
- {% endif %}
-
- {# Основной контент #}
-
- {% block content %}{% endblock %}
-
-
- {# Правая панель с календарём #}
- {% if user.is_authenticated %}
- {% include "includes/rightbar_calendar.html" %}
- {% endif %}
-
-