551 Commits

Author SHA1 Message Date
051c9ae887 feat: интегрирован django-push-notifications для Web Push
- Добавлен django-push-notifications==3.1.0 в requirements.txt
- Настроен PUSH_NOTIFICATIONS_SETTINGS в settings.py
- Создана миграция данных 0008_migrate_webpush_to_library.py (9 подписок)
- Обновлен send_web_push_notification() в services.py (150→25 строк)
- Обновлены API endpoints: subscribe_push, unsubscribe_push, get_push_subscriptions
- Ожидается 10-50x ускорение при отправке push уведомлений
- Обратная совместимость: API не изменилось, старая модель сохранена
- Полный отчет: backend/docs/reports/DJANGO_PUSH_NOTIFICATIONS_INTEGRATION.md
2026-02-27 19:30:51 +03:00
1bd470c6a8 feat: расширен поиск - добавлены модели procurement, documents, notifications, schedule
- Добавлены 5 новых моделей в watson search:
  * ProcurementRequest (заявки на закупку)
  * Equipment (оборудование)
  * Document (документы)
  * Notification (уведомления)
  * Event из django-scheduler (расписание)

- Backend API: форматтеры для новых типов моделей
- Frontend: добавлены иконки и названия для новых типов
- Тесты: исправлены фикстуры, все 13 тестов проходят
- Индексы: 3895 записей проиндексировано

Итого: 12 моделей доступны для полнотекстового поиска
2026-02-27 19:02:15 +03:00
735babbd46 feat: Add frontend integration for watson search API
Backend:
- Created REST API endpoint /api/v1/search/
- Added SearchResultSerializer and SearchResponseSerializer
- Implemented search_api_view with model formatters (employee, department, post, request, chat, message, event)
- Registered search endpoint in api/v1/urls.py
- Added permission check for requests (HR can see all, users only their own)

Frontend:
- Added SearchResponse, SearchResult, SearchModelType types
- Added apiClient.search() method in lib/api.ts
- Completely rewrote search/page.tsx:
  * Single API call instead of 6 parallel requests
  * Cleaner UI with icons for each result type
  * Real-time search with loading states
  * Meta information display (email, phone, status, etc.)
  * Better performance and UX

Benefits:
- Frontend: 220 lines → 178 lines (19% reduction)
- 1 API request instead of 6 (83% less network calls)
- Server-side full-text search via watson (better relevance)
- Unified search results with metadata

Testing:
- API endpoint verified at /api/v1/search/?q=test
- Returns JSON with query, results, counts, total
- Requires authentication (IsAuthenticated decorator)
2026-02-27 18:27:36 +03:00
3aa0dadf2e feat: Replace custom search with django-watson
- Installed django-watson 1.6.3
- Added watson to INSTALLED_APPS
- Created search_indexes.py with model registrations:
  * Post (title, body)
  * Employee (name, email, phone)
  * Department (name, description)
  * Request (title, comment)
  * Chat (name, description)
  * Message (content)
  * CalendarEvent (title, description)
- Replaced search/views.py (484 lines → 158 lines)
- Applied watson migrations and built search indexes (1015 entries)
- Tested search functionality

Benefits:
- 67% code reduction (326 lines removed)
- Better search relevance with full-text indexing
- Automatic ranking and highlighting
- Less maintenance burden
2026-02-27 18:12:21 +03:00
8ff3ffcd67 feat: Add procurement refactoring plan and merge migrations 2026-02-27 17:55:42 +03:00
ce69498db2 merge: frontend/Igor2 into feature/procurement-module with Igor2 priority 2026-02-27 16:36:16 +03:00
8596b82726 feat: add auto token refresh and increase refresh token lifetime to 90 days 2026-02-27 16:35:36 +03:00
82c85b15c6 Обновление requirements.txt: добавлены недостающие зависимости
- django-scheduler==0.12.0 - календарное приложение
- pytz==2025.2 - поддержка часовых поясов
- icalendar==7.0.1 - работа с iCalendar
- cron-descriptor==2.0.6 - описание cron выражений
- django-timezone-field==7.2.1 - временные зоны в моделях
- python-crontab==3.3.0 - управление crontab
- humanize==4.15.0 - читаемое форматирование
- prometheus-client==0.23.1 - метрики Prometheus
- tornado==6.5.4 - веб-сервер для Flower
- pytest-asyncio==1.3.0 - асинхронные тесты
2026-02-27 11:44:01 +03:00
8a7810431d Fix WebSocket URL handling and simplify .env.local setup 2026-02-26 20:18:37 +03:00
bc20d7e61e fix: Исправлена система автоотметки прочитанных сообщений
- Удалено поле last_read_at из ChatReadState, используется только last_read_message FK
- Исправлена логика автоотметки: отмечается последнее ЗАГРУЖЕННОЕ сообщение, а не последнее в чате
- Убран вызов chat.mark_read() при WebSocket open_chat (отмечал последнее в чате вместо загруженного)
- Добавлен signal для мониторинга изменений ChatReadState
- Исправлена логика скролла: убран автоскролл при дозагрузке вниз
- Добавлена проверка разрывов при WebSocket сообщениях (предотвращает пропуск сообщений)
- Реализована автоотметка WebSocket сообщений (только если пользователь внизу)
- Асимметричная загрузка: 24 контекста + 6 новых сообщений
- Добавлен ScrollableMessageList компонент для корректной работы скролла
- Миграции: 0028 (удаление last_read_at), 0029 (индекс на last_read_message)
2026-02-25 20:29:00 +03:00
cb46d869d6 Удалён режим 'до даты' для повторяемых событий, исправлен патч django-scheduler, фронт теперь только 'count' и 'forever' 2026-02-25 11:13:20 +03:00
e7e0e2e290 feat: детальное отображение параметров повторяющихся событий
Backend:
- Добавлено поле rule_data в EventSerializer
- get_rule_data() возвращает частоту, параметры и описание правила
- Использует rule.get_params() для получения распарсенных параметров

Frontend:
- Добавлены константы FREQUENCY_LABELS и WEEKDAY_LABELS для русификации
- Новый блок с детальной информацией о повторении в синем фоне
- Отображается частота (WEEKLY, MONTHLY и т.д.)
- Дни недели для еженедельных событий (ПН, ВТ, СР...)
- Количество повторений (count)
- Дата окончания повторения (end_recurring_period)
- Подсказка о невозможности редактирования параметров

Проблема: пользователь не видел детали повторяющихся событий.
Решение: красивый информационный блок с полной информацией о правиле.
2026-02-25 02:20:24 +03:00
d53414aedc fix: исправлена работа повторяющихся событий с django-scheduler
- Исправлен RuleSerializer для корректной конвертации params между форматами:
  * Frontend отправляет dict/JSON: {"byweekday": [0, 4], "interval": 1}
  * Backend сохраняет в формате django-scheduler: "byweekday:0,4;interval:1"
  * Добавлен универсальный парсер _parse_params_input() для всех форматов

- Добавлен UX в стиле Apple Calendar для еженедельных событий:
  * Авто-выбор дня начала при включении WEEKLY
  * Информационный баннер с датой первого события если начальный день не выбран
  * Защита от перезаписи выбора пользователя через useRef

- Рефакторинг и очистка кода:
  * Удалены все отладочные console.log() и print()
  * Улучшены docstrings с примерами
  * Добавлена константа VALID_FREQUENCIES

- Исправлена загрузка событий в режиме "Все события":
  * Убрана блокировка для selectedCalendarId === null
  * События и occurrences загружаются корректно для всех календарей

Closes: повторяющиеся события теперь генерируются только в выбранные дни недели
2026-02-25 01:55:51 +03:00
898ed6fec1 feat(calendar): доступ к событиям для участников + UX улучшения
Backend:
- Расширен get_queryset в ScheduleEventViewSet: теперь пользователь видит события где он участник (EventRelation), даже если не имеет доступа к календарю
- Добавлен action my-events для получения только событий участника
- Исправлена архитектурная проблема: участники событий теперь могут видеть свои события

Frontend:
- Добавлен метод apiClient.getMyEvents() для получения событий пользователя
- Добавлена подсказка в EventModal о логике начала/конца для повторяющихся событий
- Улучшен UX: пользователи понимают что начало/конец применяются ко всем повторениям
2026-02-25 00:47:45 +03:00
16b11b5401 fix(calendar): timezone handling для datetime-local inputs
- Добавлена функция toLocalDateTimeString для корректной конвертации UTC в локальное время
- Исправлено отображение времени в модальном окне событий (было 21:00 UTC вместо 00:00 MSK)
- Упрощена логика datetime-local inputs (удалена сложная условная логика)
- Добавлен allDayAccessor в react-big-calendar для корректного отображения событий
- Унифицирован EventModal для обоих календарей (~718 строк удалено)
2026-02-25 00:38:54 +03:00
f09ae3996c Реализация системы schedule (django-scheduler) с тестовыми данными
- Добавлен CustomToolbar для BigCalendar со стрелками навигации
- Выпадающий список для выбора вида календаря
- Management command для создания тестовых пользователей и календарей
- Создано 3 тестовых пользователя (anna_ivanova, petr_petrov, maria_sidorova)
- Создано 5 календарей с 11 событиями
- Убраны подписки (они для старой системы calendar_app)
- Исправлены стили тулбара BigCalendar
- Модалы календаря рендерятся на корневом уровне AppShell
2026-02-24 20:24:39 +03:00
dd64d5f540 feat: replace old calendar with django-scheduler in frontend
- Removed legacy calendar with department_id/employee_id filters
- New CalendarCard loads calendars from django-scheduler API
- Events filtered by calendar ID instead of legacy params
- Removed unused SidebarCalendarOption type
2026-02-24 18:12:28 +03:00
01b35c3b83 fix: correct imports after frontend/Igor merge
- Fixed PHONE_FIELD import from _helpers module
- Fixed _normalize_phone import from employees.utils
2026-02-24 18:04:05 +03:00
4f5d6767dc Merge branch 'frontend/Igor' into feature/django-scheduler-integration 2026-02-24 17:59:17 +03:00
63b6fff1ef feat: migrate frontend to django-scheduler API
- Updated API endpoints from /api/v1/calendar/ to /api/v1/schedule/
- Removed subscriptions concept (django-scheduler uses simpler approach)
- Adapted CalendarSerializer to accept 'title' field for EUSRR compatibility
- All calendar visibility now stored in localStorage
- Removed deprecated subscribe/unsubscribe functions
2026-02-24 17:54:46 +03:00
d94e82d313 feat: add django-scheduler API v1 endpoints
New clean API alongside old calendar_app:

API endpoints:
- /api/v1/schedule/calendars/ - Calendar CRUD
- /api/v1/schedule/events/ - Event CRUD (with timezone)
- /api/v1/schedule/rules/ - rrule RFC 5545 rules
- /api/v1/schedule/occurrences/ - materialized recurrences
- /api/v1/schedule/relations/ - meeting attendees

Features:
- Timezone support (pytz)
- RFC 5545 rrule for recurring events
- EventRelation for meeting participants
- Clean, tested code (django-scheduler)
- Parallel work with old /api/v1/calendar/

Old API untouched, works as before.
Gradual migration approach (Strangler Fig Pattern).
2026-02-24 17:35:30 +03:00
f67e625c14 feat: add django-scheduler alongside calendar_app
- Install django-scheduler 0.12.0 (parallel to existing calendar_app)
- Add 'schedule' to INSTALLED_APPS
- Create integration plan documentation
- Old calendar_app remains untouched (works as before)
- New django-scheduler for gradual migration
- API v2 will be created next for testing

Related: Strangler Fig Pattern for clean code migration
2026-02-24 17:29:15 +03:00
a590acb762 feat(frontend): добавлен API клиент и восстановлен backend из master
- Создан frontend/src/lib/api.ts с 43 методами для всех API endpoint'ов
- Создан frontend/src/lib/permissions.ts для проверки прав доступа
- Исправлен URL в getChatMessagesAround: /messages/around/ → /messages-around/
- Исправлен параметр: message_id → around_id
- Восстановлен backend из ветки master для стабильности
- Удалены конфликтующие файлы Pages Router (src/pages, App.tsx, providers)
- Оставлена только чистая структура Next.js App Router
- Добавлена документация по миграции API v2
2026-02-24 15:40:50 +03:00
38ab1afa7c Альфа версия 2026-02-24 13:11:32 +03:00
e44bfd4755 fix: добавлено поле calendar_title в CalendarEventSerializer 2026-02-23 13:11:54 +03:00
10a1c210a3 fix: исправлено отображение календаря vs контекста в деталях события 2026-02-23 13:07:59 +03:00
abc7f96902 fix: добавлено отображение создателя и календаря в деталях события + исправлен calendarId string→number 2026-02-23 13:02:38 +03:00
705fa39052 - 2026-02-23 12:56:23 +03:00
8c3c4119af - 2026-02-23 12:56:11 +03:00
d31e8cd064 fix: can_user_edit теперь проверяет default_can_edit даже если есть подписка с can_edit=False 2026-02-23 12:47:17 +03:00
8825434b7a fix: can_user_edit теперь учитывает default_can_edit
Проблема: даже после включения default_can_edit=True обычные
пользователи не могли создавать события в календаре.

Причина: метод Calendar.can_user_edit() проверял только:
- is_superuser/is_staff
- is_owner()
- subscription.can_edit
НО НЕ проверял default_can_edit для случая когда подписки нет.

Решение: добавлена проверка default_can_edit после проверки подписки.
Теперь если подписки нет, но default_can_edit=True, пользователь
может редактировать.

Это позволяет создавать публичные календари, где ВСЕ пользователи
могут создавать события без явных подписок.
2026-02-23 12:38:14 +03:00
2c70730a17 fix: добавлено поле default_can_edit в CalendarWriteSerializer
Проблема: настройка 'Подписчики могут редактировать по умолчанию'
не сохранялась при создании/редактировании календаря.

Причина: поле default_can_edit отсутствовало в fields
CalendarWriteSerializer.

Решение: добавлено поле default_can_edit в список полей сериализатора.

Теперь можно включить эту настройку для глобального календаря,
и обычные пользователи смогут создавать события.
2026-02-23 12:33:27 +03:00
7a055c79cb fix: исправлены JS ошибки в календаре и emoji-picker
- Создана заглушка для calendarEventDragDrop.js с экспортом initCalendarEventDragDrop
- Закомментирован импорт несуществующего database.js в emoji-picker/index.js
- Исправлена ошибка 'does not provide an export named initCalendarEventDragDrop'
- Исправлена ошибка 404 для emoji-picker/database.js
2026-02-23 12:26:03 +03:00
ffd3e469a1 фикс календаря 2026-02-23 12:20:18 +03:00
c39d73963b chore: удаление временных тестовых файлов оптимизации
- backend/test_message_optimization.py
- backend/test_refactored_notifications.py
2026-02-17 18:34:25 +03:00
5266e56676 feat(tools): добавление инструмента анализа DB запросов и package-lock
- backend/scripts/analyze_queries.py - автоматизированный анализ запросов
  * count_queries context manager для подсчета запросов
  * Тестирование ViewSet'ов с разными методами (list, retrieve, create)
  * Детальный вывод с количеством запросов на эндпоинт
  * Утилита для выявления N+1 проблем

- backend/package-lock.json - зафиксированы версии npm пакетов
  * sass@1.93.3 для компиляции CSS
  * Гарантирует идентичные сборки на разных машинах
2026-02-17 18:34:16 +03:00
d8a48d4c33 docs: добавление документации по тестированию и оптимизации
API Testing:
- docs/guides/API_TESTING_GUIDE.md - полное руководство по API тестированию
  * Использование Postman коллекции
  * Newman CLI интеграция
  * REST Client примеры
  * Pytest примеры с fixtures
- docs/reports/API_EMPLOYEES_COVERAGE.md - анализ покрытия эндпоинтов
  * Покрытие расширено с 23% до ~70%
  * Список протестированных и непокрытых эндпоинтов

Database Optimization:
- backend/docs/reports/DB_QUERIES_ANALYSIS.md - детальный анализ запросов к БД
  * 8 ViewSet'ов проанализированы
  * Найдены критические N+1 проблемы:
    - SkillViewSet.merge() делает 2N запросов в цикле
    - GroupViewSet.retrieve не использует prefetch_related
    - RegisterAPIView дважды проверяет email
  * Предложены оптимизации с raw SQL
  * Рейтинг текущего состояния: 4/5 звезд
2026-02-17 18:33:56 +03:00
0c2ad449ef feat(docker): добавление вспомогательных файлов для Docker
- .dockerignore - исключение ненужных файлов при сборке образа
- .env.example - пример переменных окружения
- backend/eusrr_backend/urls.py - добавлена раздача статических файлов в DEBUG режиме
2026-02-17 18:33:20 +03:00
025f82147c feat(logging): внедрение современной системы логирования с ротацией
Добавлена полнофункциональная система логирования:

Структура логов (backend/logs/):
- all.log - все сообщения (DEBUG+)
- error.log - ошибки и критические события (ERROR+)
- debug.log - отладочная информация (DEBUG+)
- security.log - события безопасности (аутентификация, авторизация)
- requests.log - HTTP запросы с деталями производительности

Возможности:
- Ротация файлов (10MB макс. размер, 5 бэкапов)
- 3 форматтера (verbose, simple, json_style)
- Фильтр RequireDebugFalse для production
- Раздельное логирование Django, DRF, Channels, Celery

Документация:
- LOGGING_GUIDE.md - полное руководство (400+ строк)
- logging_examples.py - примеры использования для всех компонентов
2026-02-17 18:32:30 +03:00
98104fcded refactor(settings): упрощение конфигурации и удаление дубликатов
- Упрощена инициализация DATABASES (удален пустой словарь, использован .update())
- Удалена закомментированная секция AUTH_PASSWORD_VALIDATORS
- Консолидированы дублирующиеся настройки LDAP:
  * LDAP_UPN_SUFFIX (было 2 определения)
  * LDAP_USERS_BASE / LDAP_USER_BASE (было дублирование)
- Изменены дефолтные значения с robotail.local на eusrr.local
- Расширена конфигурация логирования (см. следующий коммит)
2026-02-17 18:31:20 +03:00
8aa6d6ec87 chore: удаление устаревших тестовых и временных файлов
- Удалены старые тестовые файлы (test_*.html, test_*.py)
- Удалены временные конфиги и скрипты (.env.test, test_reply.sh)
- Удалены устаревшие документы (CELERY_NEXT_STEPS.md, FIX_INTEGRATION.md)
- Очищена папка localcerts_backup
- Удалены выводы pytest (pytest_output.txt)
- Удалены конфигурационные остатки (.gitignore.ldap, corp-ca.pem)
2026-02-17 18:29:24 +03:00
fcf4bff3a9 fix: add ensure_ldap_disabled to 71 tests to prevent LDAP sync issues 2026-02-16 21:44:53 +03:00
a335594932 fix: remove mocks from LDAP tests, use real LDAP integration, set gender default=0 2026-02-16 21:12:25 +03:00
4629a52834 fix: resolve test failures - add logger, LDAP_POSITIONS_BASE, make avatar/gender optional, add ensure_ldap_disabled fixtures 2026-02-16 17:38:00 +03:00
8b7d816390 docs: add LDAP testing infrastructure summary 2026-02-16 17:34:26 +03:00
ad8208789f feat: add LDAP testing infrastructure
- Add LDAP docker container structure (01-base-structure.ldif)
- Add .env.test with LDAP configuration for tests
- Create tests/ldap_fixtures.py with LDAP-specific fixtures
- Create tests/api/v1/employees/test_helpers.py with centralized helpers
- Add LDAP markers to pytest.ini (ldap_required, ldap_optional)
- Add comprehensive LDAP testing documentation
- Fix test_department_head_rights.py to use centralized helpers

New fixtures:
- ldap_available: checks if LDAP server is accessible
- ldap_config: returns LDAP configuration
- ensure_ldap_enabled/disabled: force LDAP state for test
- ldap_cleanup: auto-cleanup LDAP entries after test

New helpers:
- make_user(): centralized user creation
- grant_permission(): permission assignment
- make_department/position/role(): entity creation
- extract_results(): paginated response helper

Infrastructure:
- OU=Users, OU=Departments, OU=Groups, OU=Positions, OU=Dismissed
- Test groups: Developers, Managers
- Test departments: IT, HR
2026-02-16 17:31:48 +03:00
3977c99c0c test: fix tests after views split
- Remove @pytest.fixture from make_user (it's a helper function, not a fixture)
- Update _is_ldap_enabled patch paths to api.v1.employees.views._helpers
- Fixes AttributeError and fixture calling errors
2026-02-16 17:25:25 +03:00
f85b5dfa08 refactor: remove DB access from LDAP layer update method
- Move department_id to department_dn resolution to ViewSet layer
- update_user_in_ldap_only now receives ready department_dn parameter
- LDAP service no longer queries Department.objects directly
- All three *_in_ldap_only methods are now pure LDAP (no DB access)
2026-02-16 17:22:38 +03:00
4b56711636 refactor(employees): minimize ViewSet overrides - let mixin do the work
Removed unnecessary method overrides:

Deleted:
- create(): removed entirely - миксин работает через perform_create
- partial_update(): removed entirely - миксин работает автоматически
- perform_update() avatar handling: moved to perform_update

Simplified:
- perform_create(): only unusable password + skills (30 lines)
- perform_update(): only email verification (15 lines)

Benefits:
- Миксин работает "из коробки" без явных переопределений
- Меньше кода для поддержки
- create/update/destroy используют стандартный механизм DRF
- Только необходимая кастомная логика в perform_*

Теперь ViewSet минимален:
- Конфигурация миксина (get_external_sync_method, prepare_external_data)
- Только критичная логика (unusable password, email verification)
- Все остальное - автоматически через миксин

manage.py check: no issues
2026-02-16 17:16:19 +03:00
518fb6e790 refactor(employees): remove _perform_user_update, simplify me() PATCH
Removed 180+ lines of complex update logic:

Deleted:
- _perform_user_update(): 180 lines of manual LDAP/DB coordination
- Complex validation and error handling
- Manual transaction management
- Direct DirectoryService.update_user() calls

Simplified me() PATCH:
- Now uses standard perform_update() mechanism
- 4 lines instead of 15
- Consistent with partial_update()
- Миксин управляет всем автоматически

Total code reduction in employees.py: ~400 lines removed
(create: -150, partial_update: -200, _perform_user_update: -180)

File now: ~800 lines (was 1200+)

Benefits:
- Single source of truth for update logic
- No code duplication
- Automatic transaction management
- Cleaner, easier to maintain

manage.py check: no issues
2026-02-16 17:10:03 +03:00