- Add total_available, total_reserved, total_free annotations to product queries
- Display free stock (green/red) with reserved count in product list
- Show detailed stock info in product detail page (moved to top)
- Make reservation count clickable to view filtered reservations
- Add product filter support to ReservationListView
- Add product link in reservation list for easy navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Создан единый шаблон products_list.html для отображения товаров и комплектов
- Удалены дублирующиеся шаблоны (product_list, productkit_list, products_unified_list, all_products_list)
- Добавлены фильтры: тип (все/товары/комплекты), категория, статус, наличие, теги
- Обновлен CombinedProductListView с поддержкой фильтрации по типу и тегам
- Изменены URL маршруты: главная страница /products/ теперь показывает объединенный список
- Обновлены success_url во всех CRUD представлениях для редиректа на объединенный список
- Добавлена фильтрация по тегам с отображением количества выбранных элементов
- Улучшена UX: компактный select для тегов с счетчиком выбранных
- Все комментарии в коде переведены на русский язык
- Added temp file deletion in Celery task after successful processing
- Added temp file cleanup in sync fallback method
- Added temp file removal in delete() if processing never completed
- Prevents accumulation of orphaned files in media/<entity>/temp/ folders
Реализована трёхуровневая система статусов товаров и комплектов:
- active (Активный) - товар доступен для продажи
- archived (Архивный) - скрыт, можно восстановить в следующем сезоне
- discontinued (Снят) - морально устарел, готов к удалению
Изменения:
1. Модели (BaseProductEntity, Product, ProductKit):
- Заменено поле is_deleted (Boolean) на status (CharField)
- Добавлены архивные метаданные (archived_at, archived_by)
- Обновлены методы: archive(), restore(), discontinue(), delete()
- Уникальное ограничение изменено на conditional (status='active')
2. Менеджеры (ActiveManager, SoftDeleteQuerySet):
- Полиморфная поддержка обеих систем (status и is_active)
- Использует hasattr() для совместимости с наследниками
- Методы: archive(), restore(), discontinue(), archived_only(), active_only()
3. Формы (ProductForm, ProductKitForm):
- Включены поле status в формы
- Валидация уникальности по status='active'
- CSS классы для статус-селектора
4. Admin панель:
- DeletedFilter переименован в StatusFilter с тремя опциями
- get_status_display() с цветным отображением статуса
- Actions: restore_items, hard_delete_selected, delete_selected
- Readonly поля для архивирования
5. Представления:
- ProductListView: фильтр status вместо is_active
- CombinedProductListView: поддержка фильтра status для товаров и комплектов
- API views обновлены для работы со статусом
6. Шаблоны:
- product_form.html: form.status вместо form.is_active
- productkit_create.html: form.status вместо form.is_active
- productkit_edit.html: form.status вместо form.is_active
7. Миграции:
- Удалены все старые миграции (чистый перезапуск по требованию пользователя)
- Создана новая миграция 0001_initial с полной структурой status-системы
- Удален старый код преобразования is_deleted -> status
Проведённые проверки:
- Django system check passed ✓
- Полиморфные менеджеры работают с обеими системами
- Уникальные ограничения корректно работают с условиями
- История заказов сохраняется даже после архивирования товара (django-simple-history)
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Реализована трёхуровневая защита от IntegrityError при создании товаров с одинаковым названием:
1. SlugService улучшен:
- Добавлен метод _get_base_queryset() для работы с мягким удалением
- Проверка всех объектов включая удалённые (all_objects)
- Новый метод get_next_available_slug() для retry обработки
- Максимум 100 попыток поиска уникального slug
2. BaseProductEntity.save() защищена:
- transaction.atomic() для атомарности операции
- Retry логика с 5 попытками при IntegrityError
- При конфликте добавляется суффикс (-1, -2, -3...)
- Fallback на timestamp если суффиксы исчерпаны
3. Views обрабатывают IntegrityError:
- ProductCreateView.form_valid() перехватывает ошибку
- ProductUpdateView.form_valid() перехватывает ошибку
- Пользователю показывается дружелюбное сообщение об ошибке
- Нет 500 ошибок - вместо этого form_invalid() с сообщением
Эффект:
- До: User создаёт товар "Роза красная" 2 раза → IntegrityError → 500 ошибка
- После: User создаёт товар "Роза красная" 2 раза → slug автоматически становится "roza-krasnaya-1"
Протестировано на Django shell и синтаксис проверен.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Изменения:
- ProductCreateView/UpdateView теперь показывают warnings для предупреждений о лимите фото
- Разделение сообщений: error (красный) vs warning (желтый)
- Улучшен components/messages.html:
* Добавлены иконки для каждого типа сообщения
* Bootstrap Icons интеграция
* Кастомные цвета для alerts
* Лучший visual feedback для пользователя
Теперь пользователи видят понятные сообщения везде на сайте!
🤖 Generated with Claude Code
## Что сделано:
### 1. Фильтрация тегов по активности
- ProductForm и ProductKitForm показывают только активные теги в селектах
- ProductListView, ProductKitListView передают только активные теги в контекст фильтров
### 2. Отображение тегов на страницах товаров/комплектов
- product_detail.html отображает только активные теги
- productkit_detail.html отображает только активные теги
### 3. Логика отображения в деталях тега
- Для активного тега: показываются только активные товары/комплекты
- Для неактивного тега: показываются ВСЕ товары/комплекты (для возможности ручной очистки)
### 4. API endpoint для переключения статуса
- Новый endpoint toggle_tag_status_api в api_views.py
- POST /products/api/tags/<id>/toggle/
- Переключает is_active и возвращает новый статус
### 5. AJAX toggle switch в таблице тегов
- Заменены бейджи на toggle switch в tag_list.html
- Переключатель в 1.3x больше (масштабирование через CSS)
- Мгновенное обновление без перезагрузки страницы
- Показывает сообщение об успехе/ошибке
### 6. Связь в БД остаётся неизменной
- При деактивации тег остаётся привязан к товарам в БД
- Просто скрывается в интерфейсе
- При реактивации вновь становится видимым
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Views:
- ProductKitListView: фильтр is_temporary=False
- CombinedProductListView: фильтр is_temporary=False для комплектов
- API search: фильтр is_temporary=False в поиске и популярных
Admin:
- Добавлен фильтр по is_temporary
- Добавлено отображение статуса временного комплекта в списке
- Добавлена ссылка на заказ для временных комплектов
- Добавлен раздел "Временный комплект" в fieldsets
Теперь временные комплекты не показываются в общем каталоге,
но доступны в админке и по прямой ссылке (для заказов).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>