Добавлена поддержка черновиков заказов (Этап 2/3): AJAX endpoints и views
Добавлены AJAX endpoints: - autosave_draft_order: endpoint для автосохранения черновиков Модифицированы views: - order_create: поддержка создания черновиков через кнопку 'save_as_draft' - order_update: поддержка обновления и финализации черновиков через DraftOrderService Добавлены URL: - /orders/<pk>/autosave/ для автосохранения черновиков Следующий этап: JavaScript модуль автосохранения и UI 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,9 @@ urlpatterns = [
|
||||
path('<int:pk>/edit/', views.order_update, name='order-update'),
|
||||
path('<int:pk>/delete/', views.order_delete, name='order-delete'),
|
||||
|
||||
# AJAX endpoints
|
||||
path('<int:pk>/autosave/', views.autosave_draft_order, name='order-autosave'),
|
||||
|
||||
# Временные комплекты
|
||||
path('temporary-kits/create/', views.create_temporary_kit, name='temporary-kit-create'),
|
||||
]
|
||||
|
||||
@@ -5,10 +5,14 @@ from django.core.paginator import Paginator
|
||||
from django.http import JsonResponse
|
||||
from django.db import transaction
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import ValidationError
|
||||
from .models import Order, OrderItem
|
||||
from .forms import OrderForm, OrderItemFormSet
|
||||
from .filters import OrderFilter
|
||||
from .services import DraftOrderService
|
||||
from products.models import ProductKit, KitItem, Product
|
||||
import json
|
||||
|
||||
|
||||
def order_list(request):
|
||||
@@ -64,6 +68,12 @@ def order_create(request):
|
||||
|
||||
if form.is_valid() and formset.is_valid():
|
||||
order = form.save(commit=False)
|
||||
|
||||
# Если нажата кнопка "Сохранить как черновик", создаем черновик
|
||||
if 'save_as_draft' in request.POST:
|
||||
order.status = 'draft'
|
||||
order.modified_by = request.user
|
||||
|
||||
order.save()
|
||||
|
||||
# Сохраняем позиции заказа
|
||||
@@ -74,7 +84,10 @@ def order_create(request):
|
||||
order.calculate_total()
|
||||
order.save()
|
||||
|
||||
messages.success(request, f'Заказ #{order.order_number} успешно создан!')
|
||||
if order.is_draft():
|
||||
messages.success(request, f'Черновик #{order.order_number} успешно создан!')
|
||||
else:
|
||||
messages.success(request, f'Заказ #{order.order_number} успешно создан!')
|
||||
return redirect('orders:order-detail', pk=order.pk)
|
||||
else:
|
||||
messages.error(request, 'Пожалуйста, исправьте ошибки в форме.')
|
||||
@@ -101,15 +114,32 @@ def order_update(request, pk):
|
||||
formset = OrderItemFormSet(request.POST, instance=order)
|
||||
|
||||
if form.is_valid() and formset.is_valid():
|
||||
order = form.save()
|
||||
formset.save()
|
||||
order = form.save(commit=False)
|
||||
|
||||
# Пересчитываем итоговую сумму
|
||||
order.calculate_total()
|
||||
order.save()
|
||||
# Если черновик финализируется
|
||||
if 'finalize_draft' in request.POST and order.is_draft():
|
||||
try:
|
||||
order = DraftOrderService.finalize_draft(order.pk, request.user)
|
||||
messages.success(request, f'Черновик #{order.order_number} успешно завершен и переведен в статус "Новый"!')
|
||||
return redirect('orders:order-detail', pk=order.pk)
|
||||
except ValidationError as e:
|
||||
messages.error(request, f'Ошибка финализации: {str(e)}')
|
||||
form = OrderForm(instance=order)
|
||||
formset = OrderItemFormSet(instance=order)
|
||||
else:
|
||||
order.modified_by = request.user
|
||||
order.save()
|
||||
formset.save()
|
||||
|
||||
messages.success(request, f'Заказ #{order.order_number} успешно обновлен!')
|
||||
return redirect('orders:order-detail', pk=order.pk)
|
||||
# Пересчитываем итоговую сумму
|
||||
order.calculate_total()
|
||||
order.save()
|
||||
|
||||
if order.is_draft():
|
||||
messages.success(request, f'Черновик #{order.order_number} успешно обновлен!')
|
||||
else:
|
||||
messages.success(request, f'Заказ #{order.order_number} успешно обновлен!')
|
||||
return redirect('orders:order-detail', pk=order.pk)
|
||||
else:
|
||||
messages.error(request, 'Пожалуйста, исправьте ошибки в форме.')
|
||||
else:
|
||||
@@ -120,8 +150,9 @@ def order_update(request, pk):
|
||||
'form': form,
|
||||
'formset': formset,
|
||||
'order': order,
|
||||
'title': f'Редактирование заказа #{order.order_number}',
|
||||
'title': f'Редактирование {"черновика" if order.is_draft() else "заказа"} #{order.order_number}',
|
||||
'button_text': 'Сохранить изменения',
|
||||
'is_draft': order.is_draft(),
|
||||
}
|
||||
|
||||
return render(request, 'orders/order_form.html', context)
|
||||
@@ -144,6 +175,115 @@ def order_delete(request, pk):
|
||||
return render(request, 'orders/order_confirm_delete.html', context)
|
||||
|
||||
|
||||
# === AJAX ENDPOINTS ===
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
@login_required
|
||||
def autosave_draft_order(request, pk):
|
||||
"""
|
||||
AJAX endpoint для автосохранения черновика заказа.
|
||||
|
||||
Принимает JSON с данными формы и обновляет черновик.
|
||||
Возвращает статус сохранения и время последнего сохранения.
|
||||
|
||||
Пример запроса:
|
||||
{
|
||||
"customer": 1,
|
||||
"is_delivery": true,
|
||||
"delivery_address": 5,
|
||||
"delivery_date": "2024-01-15",
|
||||
"special_instructions": "Позвонить за час",
|
||||
"items": [
|
||||
{"product_id": 10, "quantity": "2", "price": "500"},
|
||||
{"product_kit_id": 5, "quantity": "1", "price": "1500"}
|
||||
]
|
||||
}
|
||||
|
||||
Ответ при успехе:
|
||||
{
|
||||
"success": true,
|
||||
"last_saved": "2024-01-10T15:30:45.123456",
|
||||
"order_id": 123,
|
||||
"order_number": "ORD-000123"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
data = json.loads(request.body)
|
||||
|
||||
# Проверяем существование заказа
|
||||
try:
|
||||
order = Order.objects.get(pk=pk)
|
||||
except Order.DoesNotExist:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': 'Заказ не найден'
|
||||
}, status=404)
|
||||
|
||||
# Проверяем, что это черновик
|
||||
if not order.is_draft():
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': 'Можно автосохранять только черновики'
|
||||
}, status=400)
|
||||
|
||||
# Используем DraftOrderService для обновления
|
||||
order = DraftOrderService.update_draft(
|
||||
order_id=pk,
|
||||
user=request.user,
|
||||
data=data
|
||||
)
|
||||
|
||||
# Обрабатываем позиции заказа, если они переданы
|
||||
if 'items' in data:
|
||||
# Удаляем существующие позиции
|
||||
order.items.all().delete()
|
||||
|
||||
# Создаем новые позиции
|
||||
for item_data in data['items']:
|
||||
product_id = item_data.get('product_id')
|
||||
product_kit_id = item_data.get('product_kit_id')
|
||||
quantity = item_data.get('quantity')
|
||||
price = item_data.get('price')
|
||||
|
||||
if product_id:
|
||||
DraftOrderService.add_item_to_draft(
|
||||
order_id=order.pk,
|
||||
product_id=product_id,
|
||||
quantity=quantity,
|
||||
price=price
|
||||
)
|
||||
elif product_kit_id:
|
||||
DraftOrderService.add_item_to_draft(
|
||||
order_id=order.pk,
|
||||
product_kit_id=product_kit_id,
|
||||
quantity=quantity,
|
||||
price=price
|
||||
)
|
||||
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'last_saved': order.last_autosave_at.isoformat() if order.last_autosave_at else None,
|
||||
'order_id': order.pk,
|
||||
'order_number': order.order_number
|
||||
})
|
||||
|
||||
except ValidationError as e:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': str(e)
|
||||
}, status=400)
|
||||
except json.JSONDecodeError:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': 'Некорректный JSON'
|
||||
}, status=400)
|
||||
except Exception as e:
|
||||
return JsonResponse({
|
||||
'success': False,
|
||||
'error': f'Ошибка сервера: {str(e)}'
|
||||
}, status=500)
|
||||
|
||||
|
||||
# === ВРЕМЕННЫЕ КОМПЛЕКТЫ ===
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
|
||||
Reference in New Issue
Block a user