Fix: Order creation error - avoid calling reset_delivery_cost before items are saved

The error occurred because:
1. OrderForm.save(commit=False) was calling reset_delivery_cost()
2. reset_delivery_cost() uses DeliveryCostCalculator which accesses order.items
3. But items don't exist yet when order is not saved to DB

Solution:
- OrderForm.save() now only calls reset_delivery_cost() when commit=True
- order_create() explicitly calls reset_delivery_cost() AFTER saving items
- This ensures items exist in DB before delivery cost calculation

Error was: 'Order' instance needs to have a primary key value before this relationship can be used.
This commit is contained in:
2025-11-28 23:34:53 +03:00
parent 9a44c98e6e
commit 39ab474a3c
2 changed files with 16 additions and 2 deletions

View File

@@ -200,6 +200,9 @@ class OrderForm(forms.ModelForm):
Логика: Логика:
- Если delivery_cost заполнено → используется ручное значение (is_custom_delivery_cost = True) - Если delivery_cost заполнено → используется ручное значение (is_custom_delivery_cost = True)
- Если delivery_cost пустое → автоматический расчет (is_custom_delivery_cost = False) - Если delivery_cost пустое → автоматический расчет (is_custom_delivery_cost = False)
ВАЖНО: reset_delivery_cost() вызывается только при commit=True,
т.к. требует наличия сохраненных items в БД.
""" """
instance = super().save(commit=False) instance = super().save(commit=False)
@@ -210,7 +213,11 @@ class OrderForm(forms.ModelForm):
# Ручное значение указано # Ручное значение указано
instance.set_delivery_cost(delivery_cost, is_custom=True) instance.set_delivery_cost(delivery_cost, is_custom=True)
else: else:
# Пустое поле или 0 → автоматический расчет # Пустое поле или 0 → помечаем что нужен автоматический расчет
# НО не вызываем reset_delivery_cost() если commit=False!
instance.is_custom_delivery_cost = False
if commit:
# Автоматический расчет только при commit=True
instance.reset_delivery_cost() instance.reset_delivery_cost()
if commit: if commit:

View File

@@ -68,6 +68,7 @@ def order_create(request):
payment_formset = PaymentFormSet(request.POST) payment_formset = PaymentFormSet(request.POST)
if form.is_valid() and formset.is_valid() and payment_formset.is_valid(): if form.is_valid() and formset.is_valid() and payment_formset.is_valid():
# Сохраняем форму БЕЗ commit, чтобы не вызывать reset_delivery_cost() до сохранения items
order = form.save(commit=False) order = form.save(commit=False)
# Обрабатываем адрес доставки # Обрабатываем адрес доставки
@@ -89,6 +90,7 @@ def order_create(request):
# Кнопка "Создать заказ" - статус из формы или NULL # Кнопка "Создать заказ" - статус из формы или NULL
order.modified_by = request.user order.modified_by = request.user
# Сохраняем заказ в БД (теперь у него есть pk)
order.save() order.save()
# Сохраняем позиции заказа # Сохраняем позиции заказа
@@ -99,6 +101,11 @@ def order_create(request):
payment_formset.instance = order payment_formset.instance = order
payment_formset.save() payment_formset.save()
# Пересчитываем стоимость доставки если она не установлена вручную
delivery_cost = form.cleaned_data.get('delivery_cost')
if not delivery_cost or delivery_cost <= 0:
order.reset_delivery_cost()
# Пересчитываем итоговую сумму # Пересчитываем итоговую сумму
order.calculate_total() order.calculate_total()
order.save() order.save()