Fix: Auto-fill product prices when empty or zero in autosave
Исправлена проблема с пропаданием цен товаров при автосохранении и
перезагрузке страницы.
ПРОБЛЕМА:
- При автосохранении пустые поля цен отправлялись как '0'
- Backend сохранял 0 в базу данных
- При перезагрузке страницы поля цен оставались пустыми
- Итоговая сумма товаров показывала 0.00 руб.
РЕШЕНИЕ 1 - Backend (draft_service.py):
- Изменена логика обработки цен в update_draft()
- Если цена пустая или равна 0, используется actual_price из каталога
- Добавлена корректная обработка price_raw перед конвертацией в Decimal
- Улучшена логика определения is_custom_price
Логика обработки цены:
1. Получаем price_raw из items_data
2. Если price_raw пустой или 0 → используем original_price из каталога
3. Если price_raw заполнен → используем его и сравниваем с original_price
4. is_custom_price = True только если разница больше 0.01
РЕШЕНИЕ 2 - Frontend (order_form.html):
- Добавлена fallback логика в шаблоне для отображения цены
- Если item_form.instance.price пустой/None/0 → показываем actual_price
- Используется inline условие {% if %} для проверки наличия цены
- Отдельная логика для product и product_kit
Теперь работает корректно:
✅ При выборе товара цена автоматически заполняется из каталога
✅ Автосохранение сохраняет правильную цену (из каталога или изменённую)
✅ При перезагрузке страницы цены отображаются корректно
✅ Итоговая сумма товаров рассчитывается правильно
✅ Бейдж "Изменена" показывается только для реально изменённых цен
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -231,12 +231,11 @@ class DraftOrderService:
|
|||||||
product_id = item_data.get('product_id')
|
product_id = item_data.get('product_id')
|
||||||
product_kit_id = item_data.get('product_kit_id')
|
product_kit_id = item_data.get('product_kit_id')
|
||||||
quantity = item_data.get('quantity', 1)
|
quantity = item_data.get('quantity', 1)
|
||||||
price = item_data.get('price', 0)
|
price_raw = item_data.get('price', '')
|
||||||
|
|
||||||
# Конвертируем в Decimal
|
# Конвертируем количество в Decimal
|
||||||
try:
|
try:
|
||||||
quantity = Decimal(str(quantity))
|
quantity = Decimal(str(quantity))
|
||||||
price = Decimal(str(price))
|
|
||||||
except (ValueError, TypeError, decimal.InvalidOperation):
|
except (ValueError, TypeError, decimal.InvalidOperation):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -257,9 +256,23 @@ class DraftOrderService:
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Определяем, изменилась ли цена
|
# Определяем оригинальную цену из каталога
|
||||||
original_price = product.actual_price if product else product_kit.actual_price
|
original_price = product.actual_price if product else product_kit.actual_price
|
||||||
|
|
||||||
|
# Конвертируем цену в Decimal, если пустая - используем оригинальную
|
||||||
|
try:
|
||||||
|
price = Decimal(str(price_raw)) if price_raw else Decimal('0')
|
||||||
|
# Если цена 0 или пустая, используем оригинальную цену
|
||||||
|
if price == Decimal('0'):
|
||||||
|
price = original_price
|
||||||
|
is_custom_price = False
|
||||||
|
else:
|
||||||
|
# Определяем, изменилась ли цена
|
||||||
is_custom_price = abs(price - original_price) > Decimal('0.01')
|
is_custom_price = abs(price - original_price) > Decimal('0.01')
|
||||||
|
except (ValueError, TypeError, decimal.InvalidOperation):
|
||||||
|
# В случае ошибки используем оригинальную цену
|
||||||
|
price = original_price
|
||||||
|
is_custom_price = False
|
||||||
|
|
||||||
# Обновляем существующую позицию или создаём новую
|
# Обновляем существующую позицию или создаём новую
|
||||||
if index < len(existing_items):
|
if index < len(existing_items):
|
||||||
|
|||||||
@@ -227,9 +227,9 @@
|
|||||||
<label class="form-label">Цена</label>
|
<label class="form-label">Цена</label>
|
||||||
<div class="position-relative">
|
<div class="position-relative">
|
||||||
{% if item_form.instance.product %}
|
{% if item_form.instance.product %}
|
||||||
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{{ item_form.instance.price }}" data-original-price="{{ item_form.instance.product.actual_price }}">
|
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product.actual_price }}">
|
||||||
{% elif item_form.instance.product_kit %}
|
{% elif item_form.instance.product_kit %}
|
||||||
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{{ item_form.instance.price }}" data-original-price="{{ item_form.instance.product_kit.actual_price }}">
|
<input type="number" name="{{ item_form.price.name }}" step="0.01" min="0" class="form-control" id="{{ item_form.price.id_for_label }}" value="{% if item_form.instance.price %}{{ item_form.instance.price }}{% else %}{{ item_form.instance.product_kit.actual_price }}{% endif %}" data-original-price="{{ item_form.instance.product_kit.actual_price }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ item_form.price }}
|
{{ item_form.price }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Reference in New Issue
Block a user