Fix: Implement proper deletion of order items with confirmation dialog

Fixes deletion functionality for order items across frontend and backend:
- Remove restriction preventing deletion of last item
- Add confirmation dialog before deletion
- Properly track and send deleted item IDs to backend via autosave
- Update backend to handle item deletion by ID instead of index
- Fix visual feedback: deleted items are hidden immediately
- Auto-recalculate total sum after deletion

Technical changes:
- order_form.html: Add confirmation dialog, trigger autosave on delete
- autosave.js: Collect deleted item IDs, send to backend
- draft_service.py: Process deleted_item_ids, update items by ID

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-26 06:27:27 +03:00
parent 5df182e030
commit 3b4785e2ad
4 changed files with 98 additions and 52 deletions

View File

@@ -73,7 +73,7 @@ def search_products_and_variants(request):
numeric_id = int(item_id)
if item_type == 'product':
product = Product.objects.get(id=numeric_id, is_active=True)
product = Product.objects.get(id=numeric_id, status='active')
return JsonResponse({
'results': [{
'id': f'product_{product.id}',
@@ -89,7 +89,7 @@ def search_products_and_variants(request):
elif item_type == 'kit':
# Для комплектов: временные комплекты можно получать по ID (для заказов)
# но не показываем их в общем поиске
kit = ProductKit.objects.get(id=numeric_id, is_active=True)
kit = ProductKit.objects.get(id=numeric_id, status='active')
return JsonResponse({
'results': [{
'id': f'kit_{kit.id}',
@@ -170,7 +170,7 @@ def search_products_and_variants(request):
if search_type in ['all', 'kit']:
# Показываем последние добавленные активные комплекты (только постоянные)
kits = ProductKit.objects.filter(is_active=True, is_temporary=False)\
kits = ProductKit.objects.filter(status='active', is_temporary=False)\
.order_by('-created_at')[:page_size]\
.values('id', 'name', 'sku', 'price', 'sale_price')
@@ -244,7 +244,7 @@ def search_products_and_variants(request):
models.Q(name_lower__contains=query_lower) |
models.Q(sku_lower__contains=query_lower) |
models.Q(description_lower__contains=query_lower),
is_active=True
status='active'
).annotate(
relevance=Case(
When(name_lower=query_lower, then=3),
@@ -259,7 +259,7 @@ def search_products_and_variants(request):
models.Q(name__icontains=query_normalized) |
models.Q(sku__icontains=query_normalized) |
models.Q(description__icontains=query_normalized),
is_active=True
status='active'
).annotate(
relevance=Case(
When(name__iexact=query_normalized, then=3),
@@ -310,7 +310,7 @@ def search_products_and_variants(request):
models.Q(name_lower__contains=query_lower) |
models.Q(sku_lower__contains=query_lower) |
models.Q(description_lower__contains=query_lower),
is_active=True,
status='active',
is_temporary=False
).annotate(
relevance=Case(
@@ -325,7 +325,7 @@ def search_products_and_variants(request):
models.Q(name__icontains=query_normalized) |
models.Q(sku__icontains=query_normalized) |
models.Q(description__icontains=query_normalized),
is_active=True,
status='active',
is_temporary=False
).annotate(
relevance=Case(
@@ -498,7 +498,7 @@ def validate_kit_cost(request):
elif variant_group_id:
try:
variant_group = ProductVariantGroup.objects.get(id=variant_group_id)
product = variant_group.products.filter(is_active=True).first()
product = variant_group.products.filter(status='active').first()
if variant_group:
product_name = f"[Варианты] {variant_group.name}"
except ProductVariantGroup.DoesNotExist: