Реализовано управление активностью тегов товаров и комплектов

## Что сделано:

### 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>
This commit is contained in:
2025-11-12 11:33:12 +03:00
parent a1f5733fde
commit 77064a274f
9 changed files with 252 additions and 20 deletions

View File

@@ -98,7 +98,27 @@ def search_products_and_variants(request):
}],
'pagination': {'more': False}
})
except (Product.DoesNotExist, ProductKit.DoesNotExist, ValueError):
elif item_type == 'variant':
# Для групп вариантов: получаем по ID с prefetch приоритетов
variant = ProductVariantGroup.objects.prefetch_related(
'items__product'
).get(id=numeric_id)
variant_price = variant.price or 0
count = variant.items.count()
return JsonResponse({
'results': [{
'id': variant.id,
'text': f"{variant.name} ({count} вариантов)",
'price': str(variant_price),
'actual_price': str(variant_price),
'type': 'variant',
'count': count
}],
'pagination': {'more': False}
})
except (Product.DoesNotExist, ProductKit.DoesNotExist, ProductVariantGroup.DoesNotExist, ValueError):
return JsonResponse({'results': [], 'pagination': {'more': False}})
query = request.GET.get('q', '').strip()
@@ -337,15 +357,18 @@ def search_products_and_variants(request):
variants = ProductVariantGroup.objects.filter(
models.Q(name__icontains=query) |
models.Q(description__icontains=query)
).prefetch_related('products')[:page_size]
).prefetch_related('items__product')[:page_size]
for variant in variants:
count = variant.products.filter(is_active=True).count()
count = variant.items.count()
variant_price = variant.price or 0
variant_results.append({
'id': variant.id,
'text': f"{variant.name} ({count} вариантов)",
'type': 'variant',
'count': count
'count': count,
'price': str(variant_price),
'actual_price': str(variant_price)
})
# Формируем финальный результат с группировкой или без
@@ -711,3 +734,59 @@ def create_tag_api(request):
'success': False,
'error': f'Ошибка при создании тега: {str(e)}'
}, status=500)
def toggle_tag_status_api(request, pk):
"""
AJAX endpoint для переключения статуса активности тега.
Принимает POST запрос и переключает is_active на противоположное значение.
Возвращает JSON:
{
"success": true,
"is_active": true/false,
"message": "Тег активирован" / "Тег деактивирован"
}
Или при ошибке:
{
"success": false,
"error": "Описание ошибки"
}
"""
if request.method != 'POST':
return JsonResponse({
'success': False,
'error': 'Метод не поддерживается'
}, status=405)
try:
from ..models import ProductTag
# Получаем тег
tag = ProductTag.objects.get(pk=pk)
# Переключаем статус
tag.is_active = not tag.is_active
tag.save()
# Определяем сообщение
message = "Тег активирован" if tag.is_active else "Тег деактивирован"
return JsonResponse({
'success': True,
'is_active': tag.is_active,
'message': message
})
except ProductTag.DoesNotExist:
return JsonResponse({
'success': False,
'error': 'Тег не найден'
}, status=404)
except Exception as e:
return JsonResponse({
'success': False,
'error': f'Ошибка при обновлении тега: {str(e)}'
}, status=500)