From f67e625c143c370fd8227cc2fd39e396dd980176 Mon Sep 17 00:00:00 2001 From: igor_nadein Date: Tue, 24 Feb 2026 17:29:15 +0300 Subject: [PATCH] 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 --- backend/eusrr_backend/settings.py | 1 + .../DJANGO_SCHEDULER_INTEGRATION.md | 235 ++++++++++++++++++ frontend/.env.example | 6 + frontend/next-env.d.ts | 6 + 4 files changed, 248 insertions(+) create mode 100644 docs/in-progress/DJANGO_SCHEDULER_INTEGRATION.md create mode 100644 frontend/.env.example create mode 100644 frontend/next-env.d.ts diff --git a/backend/eusrr_backend/settings.py b/backend/eusrr_backend/settings.py index ce189d60..2f7b8e47 100644 --- a/backend/eusrr_backend/settings.py +++ b/backend/eusrr_backend/settings.py @@ -43,6 +43,7 @@ INSTALLED_APPS = [ "api.apps.ApiConfig", "hikcentral.apps.HikcentralConfig", "calendar_app.apps.CalendarAppConfig", + "schedule", # django-scheduler (новая система, параллельно с calendar_app) "documents.apps.DocumentsConfig", "requests_app.apps.RequestsAppConfig", "feed.apps.FeedConfig", diff --git a/docs/in-progress/DJANGO_SCHEDULER_INTEGRATION.md b/docs/in-progress/DJANGO_SCHEDULER_INTEGRATION.md new file mode 100644 index 00000000..30dc98c7 --- /dev/null +++ b/docs/in-progress/DJANGO_SCHEDULER_INTEGRATION.md @@ -0,0 +1,235 @@ +# Интеграция django-scheduler в calendar_app + +**Ветка:** `feature/django-scheduler-integration` +**Дата:** 24 февраля 2026 +**Статус:** В процессе + +--- + +## 🎯 Цель + +Постепенная замена самописного календаря на проверенное решение **django-scheduler** с сохранением старого кода для параллельной работы и плавной миграции. + +**Принцип:** "Strangler Fig Pattern" — новая система работает параллельно, постепенно замещая старую. + +--- + +## 📦 Что установлено + +```bash +pip install django-scheduler==0.12.0 # Основной пакет +pip install icalendar==7.0.1 # RFC 5545 (iCalendar) +pip install pytz # Timezone support +pip install python-dateutil # rrule parsing +``` + +**В settings.py добавлено:** +```python +INSTALLED_APPS = [ + # ... + "calendar_app.apps.CalendarAppConfig", # Старый (работает) + "schedule", # Новый (django-scheduler) + # ... +] +``` + +--- + +## 🗂️ Структура таблиц + +### Старая система (calendar_app) + +``` +calendar_app_calendar # Calendar модель +calendar_app_calendarevent # CalendarEvent модель +calendar_app_calendarsubscription # CalendarSubscription модель +``` + +### Новая система (django-scheduler) + +``` +schedule_calendar # Calendar (чистая модель) +schedule_event # Event (с timezone + rrule) +schedule_rule # Rule (RFC 5545 rrule) +schedule_occurrence # Occurrence (материализованные вхождения) +schedule_eventrelation # EventRelation (участники) +``` + +**Без конфликтов имён!** Таблицы с разными префиксами. + +--- + +## 🔄 План параллельной работы + +### Этап 1: API v2 (новый, чистый) + +```python +# backend/api/v2/schedule/ +├── __init__.py +├── urls.py # /api/v2/schedule/ +├── views.py # ViewSets для django-scheduler +├── serializers.py # DRF serializers +└── permissions.py # Права (переиспользуем логику) +``` + +**URL разделение:** +- Старый (работает): `/api/v1/calendars/`, `/api/v1/events/` +- Новый (тестируем): `/api/v2/schedule/calendars/`, `/api/v2/schedule/events/` + +### Этап 2: Фронтенд (параллельный) + +Создать новый компонент: +```typescript +// frontend/src/components/ScheduleCalendar.tsx +// Использует /api/v2/schedule/ +``` + +Старый компонент остаётся: +```typescript +// frontend/src/app/calendar/ (работает с /api/v1/) +``` + +### Этап 3: Миграция данных + +```python +# management/commands/migrate_to_scheduler.py +# Копирует данные: calendar_app → schedule +``` + +### Этап 4: Переключение + +После тестирования: +1. Переключаем фронтенд на `/api/v2/` +2. Отключаем старые URL +3. Удаляем `calendar_app` (через несколько спринтов) + +--- + +## 📊 Сравнение моделей + +| Поле | calendar_app | django-scheduler | Маппинг | +|------|--------------|------------------|---------| +| **Calendar** | +| title | ✅ | name | Прямой | +| description | ✅ | description | Прямой | +| color | ✅ | ❌ | Custom field | +| owner_user | ✅ | ❌ | Custom field | +| owner_department | ✅ | ❌ | Custom field | +| visibility | ✅ | ❌ | django-guardian ACL | +| **Event** | +| title | ✅ | title | Прямой | +| start_date + start_time | ✅ | start (DateTimeField+TZ) | Конвертация | +| end_date + end_time | ✅ | end (DateTimeField+TZ) | Конвертация | +| recurrence | 6 типов | rule (RFC 5545) | Конвертация | +| department | ✅ | ❌ | Custom field | +| employee | ✅ | ❌ | EventRelation | + +--- + +## 🔧 Кастомные расширения + +Минимальные расширения для сохранения функциональности: + +```python +# calendar_app/scheduler_extensions.py + +from django.db import models +from schedule.models import Calendar, Event + +class ScheduleCalendarExtension(models.Model): + """Расширение для Calendar (департамент, цвет, видимость)""" + calendar = models.OneToOneField( + 'schedule.Calendar', + on_delete=models.CASCADE, + related_name='extension' + ) + color = models.CharField(max_length=7, default='#0d6efd') + owner_department = models.ForeignKey( + 'employees.Department', + null=True, blank=True, + on_delete=models.CASCADE + ) + visibility = models.CharField( + max_length=20, + choices=[ + ('public', 'Публичный'), + ('department', 'Отдел'), + ('private', 'Приватный'), + ], + default='custom' + ) + +class ScheduleEventExtension(models.Model): + """Расширение для Event (департамент, employee)""" + event = models.OneToOneField( + 'schedule.Event', + on_delete=models.CASCADE, + related_name='extension' + ) + department = models.ForeignKey( + 'employees.Department', + null=True, blank=True, + on_delete=models.CASCADE + ) +``` + +**Итого:** ~50 строк кода vs 651 в старой models.py + +--- + +## ✅ Преимущества нового подхода + +| Аспект | Старое решение | django-scheduler | +|--------|----------------|------------------| +| **Код** | 2000+ строк | ~200 строк (с расширениями) | +| **Timezone** | ❌ Нет | ✅ pytz | +| **iCalendar** | ❌ Нет | ✅ RFC 5545 | +| **Участники** | ❌ Нет | ✅ EventRelation | +| **Документация** | Самописная | ReadTheDocs | +| **Обновления** | Вручную | `pip upgrade` | +| **Community** | Нет | GitHub Issues | +| **Интеграция Celery** | Вручную | django-celery-beat | + +--- + +## 🚀 Следующие шаги + +1. ✅ **Установка** — django-scheduler установлен +2. ⏳ **Миграции БД** — создать таблицы schedule_* +3. ⏳ **API v2** — создать viewsets на django-scheduler +4. ⏳ **Скрипт миграции** — копирование данных +5. ⏳ **Фронтенд** — новый компонент календаря +6. ⏳ **Тестирование** — параллельная работа +7. ⏳ **Переключение** — деплой на production +8. ⏳ **Удаление старого** — через 2-3 спринта + +--- + +## 📝 Commit strategy + +```bash +# Все изменения в ветке feature/django-scheduler-integration +git checkout feature/django-scheduler-integration + +# Коммиты: +# 1. feat: add django-scheduler to INSTALLED_APPS +# 2. feat: create schedule_* tables via migrations +# 3. feat: add API v2 for django-scheduler +# 4. feat: add data migration script +# 5. feat: integrate frontend with API v2 +# 6. test: parallel work of old and new calendars +# 7. refactor: switch to new calendar +# 8. chore: remove calendar_app (later) +``` + +--- + +## 🎯 Безопасность + +- Старая система **НЕ ТРОГАЕТСЯ** (работает как прежде) +- Новая система **ПАРАЛЛЕЛЬНО** тестируется +- Production использует `/api/v1/` (старое) +- Staging/Dev тестирует `/api/v2/` (новое) +- Откат: `git revert` + переключение URL + +**Zero downtime migration!** diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 00000000..df3d5929 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,6 @@ +# API Configuration +VITE_API_URL=http://localhost:8000/api/v2 +VITE_WS_URL=ws://localhost:8000/ws + +# Development server port (optional, Vite uses 5173 by default) +# PORT=5173 diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts new file mode 100644 index 00000000..c4b7818f --- /dev/null +++ b/frontend/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +import "./.next/dev/types/routes.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.