feat(orders): add recipient management and enhance order forms

- Introduced Recipient model to manage order recipients separately from customers.
- Updated Order model to link to Recipient, replacing recipient_name and recipient_phone fields.
- Enhanced OrderForm to include recipient selection modes: customer, history, and new.
- Added AJAX endpoint to fetch recipient history for customers.
- Updated admin interface to manage recipients and display recipient information in order details.
- Refactored address handling to accommodate new recipient logic.
- Improved demo order creation to include random recipients.
This commit is contained in:
2025-12-23 00:08:41 +03:00
parent 483f150e7a
commit 6669d47cdf
15 changed files with 559 additions and 110 deletions

View File

@@ -97,6 +97,17 @@ def order_create(request):
# Сохраняем форму БЕЗ commit, чтобы не вызывать reset_delivery_cost() до сохранения items
order = form.save(commit=False)
# Обрабатываем получателя
recipient = AddressService.process_recipient_from_form(order, form.cleaned_data)
if recipient:
# Если получатель не существует в БД, сохраняем его
if not recipient.pk:
recipient.save()
order.recipient = recipient
else:
# Если покупатель является получателем
order.recipient = None
# Обрабатываем адрес доставки
if order.is_delivery:
address = AddressService.process_address_from_form(order, form.cleaned_data)
@@ -211,6 +222,17 @@ def order_update(request, order_number):
with transaction.atomic():
order = form.save(commit=False)
# Обрабатываем получателя
recipient = AddressService.process_recipient_from_form(order, form.cleaned_data)
if recipient:
# Если получатель не существует в БД, сохраняем его
if not recipient.pk:
recipient.save()
order.recipient = recipient
else:
# Если покупатель является получателем
order.recipient = None
# Обрабатываем адрес доставки
if order.is_delivery:
address = AddressService.process_address_from_form(order, form.cleaned_data)
@@ -220,21 +242,11 @@ def order_update(request, order_number):
address.save()
order.delivery_address = address
else:
# Если режим "без адреса", удаляем существующий адрес
if order.delivery_address:
old_address = order.delivery_address
order.delivery_address = None
# Удаляем старый адрес, если он больше не используется
if old_address and not old_address.order:
old_address.delete()
else:
# Если не доставка, удаляем адрес если он был
if order.delivery_address:
old_address = order.delivery_address
# Если режим "без адреса", очищаем адрес
order.delivery_address = None
# Удаляем старый адрес
if old_address and not old_address.order:
old_address.delete()
else:
# Если не доставка, очищаем адрес
order.delivery_address = None
order.modified_by = request.user
order.save()
@@ -460,8 +472,6 @@ def get_customer_address_history(request):
'entrance': addr.entrance,
'floor': addr.floor,
'intercom_code': addr.intercom_code,
'recipient_name': addr.recipient_name,
'recipient_phone': addr.recipient_phone,
}
for addr in addresses
]
@@ -479,6 +489,71 @@ def get_customer_address_history(request):
}, status=500)
@require_http_methods(["GET"])
@login_required
def get_customer_recipient_history(request):
"""
AJAX endpoint для получения истории получателей клиента.
GET параметры:
- customer_id: ID клиента
Возвращает JSON со списком получателей из истории заказов клиента.
"""
try:
customer_id = request.GET.get('customer_id')
if not customer_id:
return JsonResponse({
'success': False,
'error': 'customer_id не указан'
}, status=400)
from customers.models import Customer
from .models import Recipient
try:
customer = Customer.objects.get(pk=customer_id)
except Customer.DoesNotExist:
return JsonResponse({
'success': False,
'error': 'Клиент не найден'
}, status=404)
# Получаем получателей из истории заказов
customer_orders = Order.objects.filter(
customer=customer,
recipient__isnull=False
).order_by('-created_at')
recipients = Recipient.objects.filter(
orders__in=customer_orders
).distinct().order_by('-created_at')
# Форматируем для отправки клиенту
recipients_data = [
{
'id': recipient.id,
'name': recipient.name,
'phone': recipient.phone,
'display': f"{recipient.name} ({recipient.phone})",
}
for recipient in recipients
]
return JsonResponse({
'success': True,
'recipients': recipients_data,
'count': len(recipients_data)
})
except Exception as e:
return JsonResponse({
'success': False,
'error': f'Ошибка сервера: {str(e)}'
}, status=500)
# === УПРАВЛЕНИЕ СТАТУСАМИ ЗАКАЗОВ ===
@login_required