refactor: rename primary_category to external_category

This commit is contained in:
2026-01-14 02:59:11 +03:00
parent 1fb280607a
commit e7672588c6
12 changed files with 306 additions and 85 deletions

View File

@@ -1581,7 +1581,8 @@ def bulk_update_categories(request):
{"type": "kit", "id": 456}
],
"category_ids": [5, 12, 18],
"action_mode": "add" // "add" или "replace"
"action_mode": "add", // "add", "replace" или "clear"
"external_category_id": 7 // опционально, для установки внешней категории
}
Response JSON:
@@ -1615,6 +1616,8 @@ def bulk_update_categories(request):
items = data.get('items', [])
category_ids = data.get('category_ids', [])
action_mode = data.get('action_mode', 'add')
external_category_id = data.get('external_category_id') # Может быть null для очистки
should_clear_external = data.get('clear_external_category', False)
if not items:
return JsonResponse({
@@ -1622,8 +1625,8 @@ def bulk_update_categories(request):
'message': 'Не выбраны товары для обновления'
}, status=400)
# Для режима 'clear' категории не обязательны
if action_mode != 'clear' and not category_ids:
# Для режима 'clear' категории не обязательны, но нужна либо M2M категория, либо внешняя
if action_mode != 'clear' and not category_ids and external_category_id is None and not should_clear_external:
return JsonResponse({
'success': False,
'message': 'Не выбраны категории'
@@ -1635,7 +1638,7 @@ def bulk_update_categories(request):
'message': 'Неверный режим действия (должен быть add, replace или clear)'
}, status=400)
# Проверка существования категорий (только если они указаны)
# Проверка существования M2M категорий (только если они указаны)
categories = []
if category_ids:
categories = ProductCategory.objects.filter(id__in=category_ids, is_active=True)
@@ -1645,6 +1648,24 @@ def bulk_update_categories(request):
'message': 'Некоторые категории не найдены или неактивны'
}, status=400)
# Проверка существования внешней категории (если указана)
external_category = None
if external_category_id is not None:
try:
external_category = ProductCategory.objects.get(id=external_category_id, is_active=True)
except ProductCategory.DoesNotExist:
return JsonResponse({
'success': False,
'message': 'Главная категория не найдена или неактивна'
}, status=400)
# Проверка: нельзя одновременно устанавливать и очищать внешнюю категорию
if external_category and should_clear_external:
return JsonResponse({
'success': False,
'message': 'Нельзя одновременно установить и очистить главную категорию'
}, status=400)
# Обработка товаров в транзакции
updated_count = 0
skipped_count = 0
@@ -1681,7 +1702,7 @@ def bulk_update_categories(request):
skipped_count += 1
continue
# Применяем изменения категорий
# Применяем изменения M2M категорий
if action_mode == 'add':
# Добавляем категории к существующим
obj.categories.add(*categories)
@@ -1692,6 +1713,14 @@ def bulk_update_categories(request):
# Очищаем все категории
obj.categories.clear()
# Применяем изменения внешней категории
if external_category:
obj.external_category = external_category
obj.save(update_fields=['external_category'])
elif should_clear_external:
obj.external_category = None
obj.save(update_fields=['external_category'])
updated_count += 1
except (Product.DoesNotExist, ProductKit.DoesNotExist):
@@ -1706,19 +1735,36 @@ def bulk_update_categories(request):
# Формируем сообщение результата
if updated_count > 0:
message_parts = []
# Сообщение про M2M категории
if action_mode == 'clear':
message = f'Категории удалены у {updated_count} товаров'
if categories or action_mode == 'clear':
message_parts.append(f'Категории удалены')
else:
category_names = ', '.join([c.name for c in categories[:3]])
if len(categories) > 3:
category_names += f' и ещё {len(categories) - 3}'
if action_mode == 'add':
action_text = 'добавлены'
else:
action_text = 'установлены'
message = f'Категории "{category_names}" {action_text} для {updated_count} товаров'
if categories:
category_names = ', '.join([c.name for c in categories[:3]])
if len(categories) > 3:
category_names += f' и ещё {len(categories) - 3}'
if action_mode == 'add':
action_text = 'добавлены'
else:
action_text = 'установлены'
message_parts.append(f'Категории "{category_names}" {action_text}')
# Сообщение про внешнюю категорию
if external_category:
message_parts.append(f'Внешняя категория "{external_category.name}" установлена')
elif should_clear_external:
message_parts.append('Внешняя категория очищена')
# Собираем финальное сообщение
if message_parts:
message = f'{", ".join(message_parts)} для {updated_count} товаров'
else:
message = f'Обновлено {updated_count} товаров'
if skipped_count > 0:
message += f'. Пропущено: {skipped_count}'