Phase 4 Advanced Features complete!
- Created BulkActionsToolbar component with features:
* Multi-select documents with checkboxes
* Batch actions: move to folder, add tags, change status, delete
* Real-time progress tracking for batch operations
* Undo notification with 5-second timeout
* useDocumentSelection hook for state management
- Created DocumentsDashboard component with features:
* Statistics cards: total docs, my docs, approved, activity
* Line chart: uploads over last 30 days (recharts)
* Pie chart: document type distribution
* Bar chart: document status distribution
* Activity feed: recent uploads, edits, status changes
* Quick access sections: Recent, Favorites, My Documents
* Responsive grid layout
Total Phase 4 Deliverables:
1. ✅ Client-side processing integration into upload form
2. ✅ Enhanced PDF Viewer with zoom, rotate, page navigation
3. ✅ Advanced Search with filters and saved searches
4. ✅ Batch Operations with progress tracking
5. ✅ Dashboard & Analytics with charts
- Updated DocumentUploadForm to use processDocument utility
- Added real-time progress tracking with visual feedback
- Display extracted text in editable textarea
- Support compressed file upload
- Added extracted_text field to API client and backend serializer
- Auto-process PDFs, DOCX, and images on file selection
Created comprehensive document processing library:
� src/lib/document-utils/
├── processor.ts - Главный процессор (интеллектуальная обработка)
├── ocr.ts - OCR через Tesseract.js (rus+eng)
├── pdf.ts - PDF операции (extract text, thumbnail, split, merge, rotate)
├── docx.ts - DOCX извлечение текста (mammoth.js)
├── image.ts - Image processing (compress, crop, rotate, thumbnail)
└── index.ts - Экспорты
Возможности:
✅ Автоматическое определение типа файла
✅ OCR для изображений (client-side, не нагружает сервер)
✅ Извлечение текста из PDF и DOCX
✅ Сжатие изображений перед загрузкой
✅ Генерация thumbnails
✅ Progress callbacks для UI
✅ Оценка времени обработки
✅ TypeScript типы для всех функций
Преимущества перед server-side:
- Моментальная обратная связь
- Не нагружает backend
- Приватность (файл не уходит на сервер до загрузки)
- Экономия трафика (сжатие до отправки)
- Можно показать preview extracted text ДО upload
Phase 2 & 3 Complete!
- Добавлены расширенные модели для Mayan-level DMS:
* DocumentType - типы документов с JSON schema
* DocumentTag - теги для категоризации
* Cabinet - виртуальные коллекции
* DocumentMetadata - динамические key-value метаданные
* DocumentAuditLog - полный аудит действий
- Расширена модель Document:
* extracted_text - для полнотекстового поиска
* document_type - FK к типу
* modified_by, modified_at - audit trail
- Интегрирован django-watson для full-text search:
* Регистрация с extracted_text
* Кастомный adapter с URL
* Обновлен индекс (22 документа)
- API Serializers:
* DocumentTypeSerializer
* DocumentTagSerializer
* CabinetSerializer
* FolderSerializer расширен
* DocumentReadSerializer обновлен с новыми полями
Следующий этап: Phase 2 Frontend Foundation
- Добавлена закрывающая скобка } в onClick handler
- Добавлено содержимое кнопки с иконкой Eye
- Удален блок отображения document_type (поле не существует в модели)
- Убраны поля document_type и tags из DocumentUploadForm
- Обновлен API клиент: createDocument и updateDocument без этих полей
- Обновлены TypeScript типы в api.ts
- Убраны document_type и tags из отображения в documents/page.tsx
- Форма теперь принимает только: title, description, file
- Создана management команда fix_filer_polymorphic
- Использует прямой SQL для обновления polymorphic_ctype_id
- Исправляет ошибку PolymorphicTypeUndefined при GET /api/v1/documents/
- Обработано 22 файла в базе данных
Установлен и настроен django-fsm==3.0.1 для управления жизненным циклом документов.
Изменения в модели (documents/models.py):
- Добавлено FSM поле 'status' с 6 состояниями:
* draft (черновик) - по умолчанию
* in_review (на рассмотрении)
* approved (одобрен)
* published (опубликован)
* archived (архивирован)
* rejected (отклонен)
- Созданы transitions (переходы между состояниями):
* submit_for_review(): draft → in_review
* approve(): in_review → approved
* reject(): in_review → rejected
* publish(): approved → published (с отправкой уведомлений)
* return_to_draft(): draft/in_review → draft
* archive(): published → archived
* unarchive(): archived → published
Изменения в админке (documents/admin.py):
- Добавлен status_badge() с цветовыми индикаторами статусов
- Добавлен available_transitions() - список доступных переходов
- Поле status добавлено в list_display и fieldsets
- Фильтрация по статусам в list_filter
Изменения в API (api/v1/documents/):
- Добавлены поля status и status_code в DocumentReadSerializer
- Созданы actions для всех FSM transitions:
* POST /api/v1/documents/{id}/submit-for-review/
* POST /api/v1/documents/{id}/approve/
* POST /api/v1/documents/{id}/reject/
* POST /api/v1/documents/{id}/publish/
* POST /api/v1/documents/{id}/return-to-draft/
* POST /api/v1/documents/{id}/archive/
* POST /api/v1/documents/{id}/unarchive/
Миграция:
- Создана 0006_add_fsm_status.py
- Применена успешно
- Все 16 юнит-тестов проходят
Зависимости:
- Добавлен django-fsm==3.0.1 в requirements.txt
- Создан FilerFileField для сериализации filer.File объектов
- При чтении: возвращает URL файла через filer.url
- При записи: создает filer.File из UploadedFile с валидацией размера
- Обновлены serializers для работы с FilerFileField
- Обновлены тесты API: _filer_file() helper, mak_document() использует filer
- Удален устаревший mock documents.notification
- Удален validate_file() (валидация перенесена в FilerFileField)
WIP: Некоторые тесты не проходят, требуется отладка permissions
- Fixed TypeError in create_notification_async() call
- Removed send_immediately parameter (only supported by create_notification)
- All 16 tests now pass
Подробный отчет о выполненной работе по интеграции django-filer:
- Установленные пакеты и зависимости
- Изменения в конфигурации
- Описание созданных файлов
- Статистика кода и сокращение
- План миграции (6 фаз)
- Преимущества решения
- Проверка работоспособности
Файл: docs/in-progress/DJANGO_FILER_INTEGRATION.md (550+ строк)
Добавлена поддержка django-filer для профессионального управления файлами в приложении documents.
Что добавлено:
- models_v2.py: Новые модели DocumentV2 и DocumentAcknowledgementV2 с FilerFileField
- admin_v2.py: Django admin с drag & drop загрузкой и превью thumbnails
- rules_v2.py: Правила доступа django-rules для новых моделей
- tests_v2.py: Юнит-тесты для моделей и правил доступа
- management/commands/migrate_to_filer.py: Команда для миграции данных из старых моделей
Настройки:
- settings.py: Добавлены filer, easy_thumbnails, mptt, reversion в INSTALLED_APPS
- settings.py: Настроены THUMBNAIL_PROCESSORS и THUMBNAIL_ALIASES
- requirements.txt: Добавлены django-filer==3.4.4, easy-thumbnails==2.10.1, django-mptt==0.18.0, django-reversion==6.1.0
Документация:
- docs/reports/DOCUMENTS_REPLACEMENT_ANALYSIS.md: Анализ вариантов замены приложения documents
Преимущества:
- Поддержка папок и вложенной структуры файлов
- Автоматическая генерация thumbnails для изображений и PDF
- Полнотекстовый поиск по содержимому файлов
- Информация о размере, MIME-типе, метаданные
- История версий через django-reversion
- Сокращение кода с 1180 → ~580 строк (50%)
Миграция:
- Старые модели Document и DocumentAcknowledgement оставлены для совместимости
- Миграция данных: python manage.py migrate_to_filer
- После проверки старые модели можно удалить
Связанные issues: #N/A
Тип изменений: Feature
Область: documents, file management
- requests_app/rules.py: 8 предикатов + 10 правил
* Предикаты: is_request_author, is_request_assignee, can_manage_requests и др.
* Правила: view/change/delete/assign/approve requests, комментирование, статистика
- communications/rules.py: 9 предикатов + 15 правил
* Предикаты: is_chat_member, is_chat_owner, is_chat_admin, is_message_author и др.
* Правила: view/send/change/delete чаты и сообщения, управление участниками, закрепление
* Включены примеры для WebSocket consumers
- calendar_app/rules.py: 9 предикатов + 12 правил
* Предикаты: is_calendar_owner, is_personal_calendar, has_calendar_access и др.
* Правила: view/change/delete календари и события, подписки, экспорт iCal, приглашения
- procurement/rules.py: 8 предикатов + 13 правил
* Предикаты: is_procurement_manager, is_purchase_request_author, can_approve_purchases и др.
* Правила: view/change/delete заявки на закупку, управление поставщиками и договорами
- feed/rules.py: 8 предикатов + 11 правил
* Предикаты: is_post_author, can_publish_posts, can_moderate_posts и др.
* Правила: view/create/change/delete посты, публикация, закрепление, комментирование, реакции
Во всех apps.py добавлен импорт rules для автозагрузки правил при старте Django
- Установлен пакет rules==3.5
- Добавлен ObjectPermissionBackend в AUTHENTICATION_BACKENDS
- Созданы базовые правила для employees:
* Предикаты: is_hr_staff, is_department_head, is_own_profile и др.
* Правила: view/change/delete employee, view reports и контакты
- Созданы базовые правила для documents:
* Предикаты: is_document_owner, has_document_access, can_approve и др.
* Правила: view/change/delete/approve/publish/share documents
- Правила регистрируются в apps.py (ready() метод)
- Создана подробная документация с примерами использования
* В views, templates, DRF permissions, Django Admin
* Сценарии: многоуровневое согласование, временные ограничения
* Сравнение с django-guardian, отладка, тестирование
Документация: docs/guides/DJANGO_RULES_INTEGRATION.md
- Добавлен django-service-objects==0.7.1 в requirements.txt
- Создан отчёт LIBRARY_REPLACEMENT_ANALYSIS.md с рекомендациями:
* django-cacheops → замена common/cache_decorators.py
* django-post-office → замена common/emails.py
* easy-thumbnails → замена common/image_utils.py
* django-rules → улучшение permissions
* requests-cache → кэширование внешних API
План внедрения по фазам с метриками и приоритетами.
Impact: снижение кастомного кода с ~360 до ~50 строк.
Refs: #tech-debt #modernization
- Интегрирован django-service-objects 0.7.1 для Service Layer Pattern
- Перенесена вся логика дней рождения из calendar_app → employees:
* UpsertBirthdayEventService - создание/обновление событий ДР
* DeleteBirthdayEventService - удаление событий ДР
* BulkSyncBirthdaysService - массовая синхронизация
* signals_birthday.py - автосинхронизация через post_save/post_delete
* management command sync_birthdays - CLI команда синхронизации
* тесты (11 tests, 6 passing)
- Обновлена миграция 0013_migrate_to_django_scheduler:
* Добавлен ШАГ 5: автоматическая синхронизация дней рождения (131 событие)
* Исключены старые события ДР из миграции (source.endswith(':birthday'))
* Исправлены имена сотрудников (f'{last_name} {first_name}' вместо get_full_name())
* Добавлен цвет #FFC107 для событий дней рождения
- Очищен calendar_app от birthday сервисов:
* Удалены calendar_app/services/birthday_events.py
* Удалены calendar_app/signals_scheduler.py
* Удалены calendar_app/management/commands/sync_birthdays.py
* Удалены calendar_app/tests/test_services.py
* Обновлен apps.py - удалены ссылки на signals_scheduler
- API улучшения:
* Добавлен api/v1/schedule/permissions.py (IsCalendarOwnerOrAdmin)
* Обновлен views.py с правильными permissions
- Документация:
* DJANGO_SERVICE_OBJECTS_INTEGRATION.md - руководство по Service Layer
* CALENDAR_MIGRATION_ANALYSIS.md - анализ миграции
* MODERNIZATION_ANALYSIS.md - анализ модернизации кодовой базы
Цель: подготовка к будущему удалению calendar_app, централизация
логики сотрудников в employees приложении.
Refs: #birthday-refactoring
- Добавлена проверка Array.isArray() в NotificationCenter
- Добавлена защита от non-array в useNotifications хук
- Исправлен импорт date-fns/locale для версии 4+
- В случае ошибки API устанавливается пустой массив []
Frontend:
- Установлен Sonner для toast уведомлений
- Создан Service Worker (public/sw.js) для Web Push
- Реализован хук useWebPush для управления подписками
- Добавлены утилиты Web Push (lib/push.ts)
- Создан компонент NotificationCenter с UI
- Интегрирован в AppShell (header desktop + mobile)
- Добавлен Toaster в Providers
API методы:
- getVapidPublicKey() - получение VAPID ключа
- subscribePush() - создание подписки
- unsubscribePush() - удаление подписки
- getPushSubscriptions() - список подписок
Возможности:
- � Web Push (работают даже когда вкладка закрыта)
- � NotificationCenter с badge и историей
- � Toast уведомления (Sonner)
- ⚙️ Настройки push подписок
- � Респонсивный дизайн
Документация: frontend/NOTIFICATIONS_IMPLEMENTATION.md
- Добавлен 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
Расширение поиска: добавлены модели procurement, documents, notifications, schedule.
Всего 12 моделей доступны для полнотекстового поиска через django-watson.
- Добавлены 5 новых моделей в watson search:
* ProcurementRequest (заявки на закупку)
* Equipment (оборудование)
* Document (документы)
* Notification (уведомления)
* Event из django-scheduler (расписание)
- Backend API: форматтеры для новых типов моделей
- Frontend: добавлены иконки и названия для новых типов
- Тесты: исправлены фикстуры, все 13 тестов проходят
- Индексы: 3895 записей проиндексировано
Итого: 12 моделей доступны для полнотекстового поиска
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)
- Удалено поле 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)
- Добавлены API методы в api.ts:
* getChats, getChat, createChat
* getChatMessages, sendMessage, sendMessageWithFiles
* updateMessage, deleteMessage
* markChatAsRead, togglePinChat, toggleChatNotifications
- Создан компонент NewChatModal:
* Поиск и выбор сотрудников
* Поддержка приватных и групповых чатов
* Автоматическое название для групп
- Интегрирована кнопка 'Новый чат' в Chatscope UI
- При создании чата автоматически открывается диалог
- Установлены пакеты @chatscope/chat-ui-kit-react и @chatscope/chat-ui-kit-styles
- Создана новая страница /messages-chatscope с полнофункциональным мессенджером
- Добавлен пункт 'Мессенджер (NEW)' в навигационное меню
- Реализована интеграция с существующим Django API
- Добавлена поддержка WebSocket для real-time сообщений
- Список чатов с поиском и аватарами
- Отображение сообщений с датами и вложениями
- Индикатор 'печатает...' через WebSocket
- Extract CalendarCard to separate component (467 lines)
- Create calendarService for API and caching (156 lines)
- Add useCalendarEvents hook (96 lines)
- Create CalendarSidebar wrapper component (29 lines)
- Reduce AppShell.tsx from 1277 to 634 lines (-50%)
- Implement proper separation of concerns
- Move global cache to service layer
- Improve code maintainability and testability
- Реализована возможность конвертации повторяющегося события в обычное:
* При снятии галочки 'Повторяющееся событие' rule_id сбрасывается в null
* Событие становится одиночным, все occurrence исчезают
- Добавлен метод updateRule() в apiClient:
* Позволяет обновлять существующие правила повторения
* Изменения применяются ко всем occurrence события
* Использует PUT запрос к /api/v1/schedule/rules/{id}/
- Исправлено использование repeatMode:
* Заменен устаревший useCount на repeatMode ('until' | 'count' | 'forever')
* Корректная обработка end_recurring_period только для режима 'until'
- Добавлена универсальная функция normalizeByweekday():
* Решена проблема с разными форматами byweekday с backend:
- Массив: [0, 4] ✓
- Строка: '0,4' ✓
- Число: 4 ✓
* Функция используется во всех компонентах:
- EventModal: авто-выбор дней, отображение кнопок, сохранение
- ViewEventDetailsModal: отображение дней недели
* Исправлены ошибки '.map is not a function' и '.includes is not a function'
- Улучшена логика handleSave() в EventModal:
* Проверка необходимости сброса rule при снятии галочки
* Разделение логики создания и обновления правил
* Нормализация byweekday перед отправкой на backend
Closes: полная поддержка CRUD операций для повторяющихся событий
- Заменен boolean useCount на enum repeatMode: 'until' | 'count' | 'forever'
- Добавлен третий radio button 'Бесконечно' в UI
- При выборе 'forever' count и end_recurring_period = undefined
- Для бесконечного режима показывается пояснение вместо input
- loadRule() правильно определяет repeatMode при загрузке правила
- При включении isRecurring по умолчанию repeatMode = 'until'
Проблема: нельзя было создать событие без ограничений по дате или количеству.
Решение: RFC 5545 RRULE поддерживает бесконечное повторение (без count/until).
- Убрана блокировка редактирования для существующих повторяющихся событий
- loadRule() теперь заполняет поля формы параметрами из Rule:
* frequency, interval, byweekday, count
* isRecurring = true
* useCount устанавливается если есть count
- Удален readonly блок с информацией о повторении
- Редактируемые поля теперь доступны для всех событий
- При сохранении будет обновлен Rule через API
Проблема: нельзя было изменять параметры повторения (частота, дни недели, count).
Решение: все occurrences используют общий Rule - просто редактируем его параметры.