Исправление проблем с сохранением адреса, получателя и даты доставки

- Исправлено: адрес теперь сохраняется для черновиков заказов
- Исправлено: получатель корректно предзаполняется при редактировании заказа
- Исправлено: адрес при редактировании отображается в режиме 'новый' для возможности редактирования
- Исправлено: дата доставки корректно предзаполняется при редактировании заказа
- Исправлено: при редактировании получателя обновляется существующий объект вместо создания нового
- Улучшена логика обработки Delivery для черновиков (создание с опциональными полями)
- Улучшена логика обновления получателя через загрузку заказа из БД с select_related
This commit is contained in:
2025-12-25 00:30:27 +03:00
parent 98470c83af
commit 298d797286
5 changed files with 192 additions and 91 deletions

View File

@@ -121,30 +121,53 @@ def order_create(request):
# Проверяем, является ли заказ черновиком
is_draft = order.status and order.status.code == 'draft'
# Создаем Delivery (обязательно, кроме черновиков)
if not is_draft:
# Получаем данные из формы (уже провалидированы)
delivery_type = form.cleaned_data.get('delivery_type')
delivery_date = form.cleaned_data.get('delivery_date')
time_from = form.cleaned_data.get('time_from')
time_to = form.cleaned_data.get('time_to')
delivery_cost = form.cleaned_data.get('delivery_cost', Decimal('0'))
pickup_warehouse = form.cleaned_data.get('pickup_warehouse')
# Проверяем наличие обязательных полей (время необязательно)
# Получаем данные из формы (уже провалидированы)
delivery_type = form.cleaned_data.get('delivery_type')
delivery_date = form.cleaned_data.get('delivery_date')
time_from = form.cleaned_data.get('time_from')
time_to = form.cleaned_data.get('time_to')
delivery_cost = form.cleaned_data.get('delivery_cost', Decimal('0'))
pickup_warehouse = form.cleaned_data.get('pickup_warehouse')
# Обрабатываем адрес для курьерской доставки (даже для черновиков, если указан)
address = None
if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
# Для курьерской доставки обрабатываем адрес, если он указан
address = AddressService.process_address_from_form(order, form.cleaned_data)
if address and not address.pk:
address.save()
# Создаем или обновляем Delivery
# Для черновиков создаем Delivery без обязательных проверок, чтобы сохранить адрес
if is_draft:
# Для черновиков создаем Delivery, если есть хотя бы адрес или данные доставки
if address or delivery_type or pickup_warehouse:
# Для черновиков используем значения по умолчанию, если не указаны
from django.utils import timezone
draft_delivery_type = delivery_type or Delivery.DELIVERY_TYPE_COURIER
draft_delivery_date = delivery_date or timezone.now().date()
Delivery.objects.update_or_create(
order=order,
defaults={
'delivery_type': draft_delivery_type,
'delivery_date': draft_delivery_date,
'time_from': time_from,
'time_to': time_to,
'address': address,
'pickup_warehouse': pickup_warehouse,
'cost': delivery_cost if delivery_cost else Decimal('0')
}
)
else:
# Для не-черновиков проверяем обязательные поля
if not delivery_type or not delivery_date:
raise ValidationError('Необходимо указать способ доставки и дату доставки')
# Обрабатываем адрес для курьерской доставки
address = None
if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
# Для курьерской доставки нужен адрес
address = AddressService.process_address_from_form(order, form.cleaned_data)
if not address:
raise ValidationError('Для курьерской доставки необходимо указать адрес')
if not address.pk:
address.save()
elif delivery_type == Delivery.DELIVERY_TYPE_PICKUP:
# Для самовывоза нужен склад
if not pickup_warehouse:
@@ -259,9 +282,8 @@ def order_update(request, order_number):
# Обрабатываем получателя
recipient = AddressService.process_recipient_from_form(order, form.cleaned_data)
if recipient:
# Если получатель не существует в БД, сохраняем его
if not recipient.pk:
recipient.save()
# Сохраняем получателя: если новый - создаем, если существующий - обновляем
recipient.save() # Django автоматически определит create или update
order.recipient = recipient
else:
# Если покупатель является получателем
@@ -274,30 +296,56 @@ def order_update(request, order_number):
# Проверяем, является ли заказ черновиком
is_draft = order.status and order.status.code == 'draft'
# Создаем или обновляем Delivery (обязательно, кроме черновиков)
if not is_draft:
# Получаем данные из формы (уже провалидированы)
delivery_type = form.cleaned_data.get('delivery_type')
delivery_date = form.cleaned_data.get('delivery_date')
time_from = form.cleaned_data.get('time_from')
time_to = form.cleaned_data.get('time_to')
delivery_cost = form.cleaned_data.get('delivery_cost', Decimal('0'))
pickup_warehouse = form.cleaned_data.get('pickup_warehouse')
# Проверяем наличие обязательных полей (время необязательно)
# Получаем данные из формы (уже провалидированы)
delivery_type = form.cleaned_data.get('delivery_type')
delivery_date = form.cleaned_data.get('delivery_date')
time_from = form.cleaned_data.get('time_from')
time_to = form.cleaned_data.get('time_to')
delivery_cost = form.cleaned_data.get('delivery_cost', Decimal('0'))
pickup_warehouse = form.cleaned_data.get('pickup_warehouse')
# Обрабатываем адрес для курьерской доставки (даже для черновиков, если указан)
address = None
if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
# Для курьерской доставки обрабатываем адрес, если он указан
address = AddressService.process_address_from_form(order, form.cleaned_data)
if address and not address.pk:
address.save()
# Создаем или обновляем Delivery
# Для черновиков создаем Delivery без обязательных проверок, чтобы сохранить адрес
if is_draft:
# Для черновиков создаем Delivery, если есть хотя бы адрес или данные доставки
if address or delivery_type or pickup_warehouse:
# Для черновиков используем значения по умолчанию, если не указаны
from django.utils import timezone
draft_delivery_type = delivery_type or Delivery.DELIVERY_TYPE_COURIER
draft_delivery_date = delivery_date or timezone.now().date()
Delivery.objects.update_or_create(
order=order,
defaults={
'delivery_type': draft_delivery_type,
'delivery_date': draft_delivery_date,
'time_from': time_from,
'time_to': time_to,
'address': address,
'pickup_warehouse': pickup_warehouse,
'cost': delivery_cost if delivery_cost else Decimal('0')
}
)
elif hasattr(order, 'delivery'):
# Если заказ стал черновиком и нет данных доставки, удаляем Delivery
order.delivery.delete()
else:
# Для не-черновиков проверяем обязательные поля
if not delivery_type or not delivery_date:
raise ValidationError('Необходимо указать способ доставки и дату доставки')
# Обрабатываем адрес для курьерской доставки
address = None
if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
# Для курьерской доставки нужен адрес
address = AddressService.process_address_from_form(order, form.cleaned_data)
if not address:
raise ValidationError('Для курьерской доставки необходимо указать адрес')
if not address.pk:
address.save()
elif delivery_type == Delivery.DELIVERY_TYPE_PICKUP:
# Для самовывоза нужен склад
if not pickup_warehouse:
@@ -316,9 +364,6 @@ def order_update(request, order_number):
'cost': delivery_cost if delivery_cost else Decimal('0')
}
)
elif hasattr(order, 'delivery'):
# Если заказ стал черновиком, удаляем Delivery
order.delivery.delete()
# Пересчитываем итоговую стоимость
order.calculate_total()