Реализованы следующие улучшения для формы создания/редактирования комплектов: 1. **Улучшенный API поиска товаров:** - Добавлен поиск по полю search_keywords для более точных результатов - Добавлены дополнительные поля: display_name, display_price 2. **Предпросмотр загружаемых фото:** - Миниатюры выбранных файлов перед загрузкой - Счетчик выбранных файлов - Возможность удаления отдельных фото до отправки формы 3. **Динамическое добавление товаров:** - Кнопка "Добавить товар в комплект" для создания новых строк - Автопоиск товаров при вводе текста (задержка 300мс) - Автоматическое добавление при клике на результат - Визуальные уведомления об успешном добавлении - Прокрутка к новой форме после добавления 4. **Валидация на дубликаты:** - Предупреждение при попытке добавить существующий товар - Подсветка дубликата на 2 секунды - Предложение изменить количество в существующей строке 5. **Автоматический расчет цены:** - Информационный блок с суммой товаров и их количеством - Пересчет при добавлении/удалении товаров - Пересчет при изменении количества - Асинхронная загрузка цен для существующих товаров 6. **Исправления:** - Снятие disabled с полей select перед отправкой формы - Правильное создание новых форм при добавлении товаров через поиск - Использование display_name для корректного отображения 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""
|
||
API представления для приложения products.
|
||
"""
|
||
from django.http import JsonResponse
|
||
from django.db import models
|
||
|
||
from ..models import Product, ProductVariantGroup
|
||
|
||
|
||
def search_products_and_variants(request):
|
||
"""
|
||
API endpoint для поиска товаров и групп вариантов.
|
||
Используется для автокомплита при добавлении компонентов в комплект.
|
||
|
||
Параметры GET:
|
||
- q: строка поиска
|
||
- type: 'product' или 'variant' (опционально, если не указано - поиск по обоим)
|
||
|
||
Возвращает JSON список:
|
||
[
|
||
{
|
||
"id": 1,
|
||
"name": "Роза красная Freedom 50см",
|
||
"sku": "PROD-000001",
|
||
"type": "product",
|
||
"price": "150.00"
|
||
},
|
||
{
|
||
"id": 1,
|
||
"name": "Роза красная Freedom",
|
||
"type": "variant",
|
||
"count": 3
|
||
}
|
||
]
|
||
"""
|
||
query = request.GET.get('q', '').strip()
|
||
search_type = request.GET.get('type', 'all')
|
||
|
||
if not query or len(query) < 2:
|
||
return JsonResponse({'results': []})
|
||
|
||
results = []
|
||
|
||
# Поиск товаров
|
||
if search_type in ['all', 'product']:
|
||
products = Product.objects.filter(
|
||
models.Q(name__icontains=query) |
|
||
models.Q(sku__icontains=query) |
|
||
models.Q(description__icontains=query) |
|
||
models.Q(search_keywords__icontains=query),
|
||
is_active=True
|
||
).values('id', 'name', 'sku', 'sale_price')[:10]
|
||
|
||
for product in products:
|
||
results.append({
|
||
'id': product['id'],
|
||
'name': f"{product['name']} ({product['sku']})",
|
||
'sku': product['sku'],
|
||
'type': 'product',
|
||
'price': str(product['sale_price']),
|
||
'display_name': product['name'],
|
||
'display_price': f"{product['sale_price']:.2f} ₽"
|
||
})
|
||
|
||
# Поиск групп вариантов
|
||
if search_type in ['all', 'variant']:
|
||
variants = ProductVariantGroup.objects.filter(
|
||
models.Q(name__icontains=query) |
|
||
models.Q(description__icontains=query)
|
||
).prefetch_related('products')[:10]
|
||
|
||
for variant in variants:
|
||
count = variant.products.filter(is_active=True).count()
|
||
results.append({
|
||
'id': variant.id,
|
||
'name': f"{variant.name} ({count} вариантов)",
|
||
'type': 'variant',
|
||
'count': count
|
||
})
|
||
|
||
return JsonResponse({'results': results})
|