Исправлена персистентность типа доставки при автосохранении
Проблема: После переключения между "С доставкой" и "Самовывоз" и автосохранения, при перезагрузке страницы всегда отображался "Самовывоз", независимо от фактически сохраненного значения.
Изменения:
1. **orders/templates/orders/order_form.html**:
- Переписана инициализация управления типом доставки
- Код вынесен из jQuery document.ready в отдельный DOMContentLoaded обработчик
- Разделена логика синхронизации:
* syncDeliveryTypeFromRadio() - для обработки кликов пользователя
* syncUIFromCheckbox() - для инициализации UI из значения чекбокса
- Исправлен рендеринг скрытого чекбокса is_delivery с явным атрибутом checked
- Удалена лишняя закрывающая скобка, вызывавшая JS ошибку
- Удален дублирующийся обработчик select2:opening для выбора клиента
2. **orders/services/draft_service.py**:
- Добавлена явная конвертация boolean полей (is_delivery, customer_is_recipient, is_anonymous)
- Обработка различных типов данных (bool, string, None) в единый boolean
- Добавлено логирование для отладки is_delivery (временно)
Результат: Тип доставки теперь корректно сохраняется через автосохранение и восстанавливается при перезагрузке страницы.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
"allow": [
|
"allow": [
|
||||||
"Bash(dir /b /s settings.py)",
|
"Bash(dir /b /s settings.py)",
|
||||||
"Bash(git add:*)",
|
"Bash(git add:*)",
|
||||||
"Bash(..venvScriptspython.exe manage.py check)"
|
"Bash(..venvScriptspython.exe manage.py check)",
|
||||||
|
"Bash(python:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -143,8 +143,27 @@ class DraftOrderService:
|
|||||||
if field in data:
|
if field in data:
|
||||||
value = data[field]
|
value = data[field]
|
||||||
|
|
||||||
|
# Конвертируем boolean поля
|
||||||
|
if field in ['is_delivery', 'customer_is_recipient', 'is_anonymous']:
|
||||||
|
# Явно конвертируем в bool, обрабатывая различные типы данных
|
||||||
|
original_value = value
|
||||||
|
if isinstance(value, bool):
|
||||||
|
value = value
|
||||||
|
elif isinstance(value, str):
|
||||||
|
value = value.lower() in ('true', '1', 'yes', 'on')
|
||||||
|
elif value is None:
|
||||||
|
value = False
|
||||||
|
else:
|
||||||
|
value = bool(value)
|
||||||
|
|
||||||
|
# Логируем для отладки
|
||||||
|
if field == 'is_delivery':
|
||||||
|
import logging
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.info(f"[AUTOSAVE] is_delivery: original={original_value} (type={type(original_value)}), converted={value}")
|
||||||
|
|
||||||
# Конвертируем числовые поля в Decimal
|
# Конвертируем числовые поля в Decimal
|
||||||
if field in ['delivery_cost', 'discount_amount']:
|
elif field in ['delivery_cost', 'discount_amount']:
|
||||||
if value == '' or value is None:
|
if value == '' or value is None:
|
||||||
value = None
|
value = None
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -188,18 +188,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<!-- Скрытое поле для передачи значения is_delivery -->
|
<!-- Скрытое поле для передачи значения is_delivery -->
|
||||||
<input type="hidden" id="{{ form.is_delivery.id_for_label }}" name="{{ form.is_delivery.name }}" value="on">
|
<div style="display: none;">
|
||||||
|
<input type="checkbox"
|
||||||
|
id="{{ form.is_delivery.id_for_label }}"
|
||||||
|
name="{{ form.is_delivery.name }}"
|
||||||
|
value="on"
|
||||||
|
{% if form.instance.is_delivery %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Кнопки выбора типа доставки -->
|
<!-- Кнопки выбора типа доставки -->
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label d-block mb-2">Тип доставки</label>
|
<label class="form-label d-block mb-2">Тип доставки</label>
|
||||||
<div class="btn-group w-100" role="group">
|
<div class="btn-group w-100" role="group">
|
||||||
<input type="radio" class="btn-check" name="delivery-type" id="delivery-type-delivery" value="delivery" checked>
|
<input type="radio" class="btn-check" name="delivery-type" id="delivery-type-delivery" value="delivery" {% if form.instance.is_delivery %}checked{% endif %}>
|
||||||
<label class="btn btn-outline-primary" for="delivery-type-delivery">
|
<label class="btn btn-outline-primary" for="delivery-type-delivery">
|
||||||
<i class="bi bi-truck"></i> С ДОСТАВКОЙ
|
<i class="bi bi-truck"></i> С ДОСТАВКОЙ
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input type="radio" class="btn-check" name="delivery-type" id="delivery-type-pickup" value="pickup">
|
<input type="radio" class="btn-check" name="delivery-type" id="delivery-type-pickup" value="pickup" {% if not form.instance.is_delivery %}checked{% endif %}>
|
||||||
<label class="btn btn-outline-primary" for="delivery-type-pickup">
|
<label class="btn btn-outline-primary" for="delivery-type-pickup">
|
||||||
<i class="bi bi-shop"></i> САМОВЫВОЗ
|
<i class="bi bi-shop"></i> САМОВЫВОЗ
|
||||||
</label>
|
</label>
|
||||||
@@ -842,19 +848,29 @@ initCustomerSelect2();
|
|||||||
// Инициализация Select2 для остальных полей (после jQuery загружен)
|
// Инициализация Select2 для остальных полей (после jQuery загружен)
|
||||||
if (typeof $ !== 'undefined') {
|
if (typeof $ !== 'undefined') {
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
console.log('[INIT] jQuery document ready triggered');
|
||||||
|
|
||||||
$('.select2:not(.select2-order-item)').select2({
|
$('.select2:not(.select2-order-item)').select2({
|
||||||
theme: 'bootstrap-5',
|
theme: 'bootstrap-5',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
language: 'ru'
|
language: 'ru'
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// === УПРАВЛЕНИЕ ТИПОМ ДОСТАВКИ (КНОПКИ) ===
|
// === УПРАВЛЕНИЕ ТИПОМ ДОСТАВКИ (КНОПКИ) ===
|
||||||
|
// ВАЖНО: Этот код должен быть ВНЕ jQuery document.ready,
|
||||||
|
// чтобы выполниться после полной загрузки DOM
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
console.log('[DELIVERY TYPE] DOM loaded, initializing...');
|
||||||
|
|
||||||
const deliveryTypeRadios = document.querySelectorAll('input[name="delivery-type"]');
|
const deliveryTypeRadios = document.querySelectorAll('input[name="delivery-type"]');
|
||||||
const isDeliveryCheckbox = document.getElementById('{{ form.is_delivery.id_for_label }}');
|
const isDeliveryCheckbox = document.getElementById('{{ form.is_delivery.id_for_label }}');
|
||||||
const deliveryModeFields = document.getElementById('delivery-mode-fields');
|
const deliveryModeFields = document.getElementById('delivery-mode-fields');
|
||||||
const pickupFields = document.getElementById('pickup-fields');
|
const pickupFields = document.getElementById('pickup-fields');
|
||||||
|
|
||||||
function syncDeliveryType() {
|
function syncDeliveryTypeFromRadio() {
|
||||||
|
// Синхронизирует чекбокс И UI с выбранной радиокнопкой
|
||||||
const selectedType = document.querySelector('input[name="delivery-type"]:checked').value;
|
const selectedType = document.querySelector('input[name="delivery-type"]:checked').value;
|
||||||
|
|
||||||
if (selectedType === 'delivery') {
|
if (selectedType === 'delivery') {
|
||||||
@@ -872,14 +888,33 @@ if (typeof $ !== 'undefined') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработчики для кнопок
|
function syncUIFromCheckbox() {
|
||||||
|
// Синхронизирует ТОЛЬКО UI (не трогает чекбокс) с текущим значением чекбокса
|
||||||
|
if (isDeliveryCheckbox.checked) {
|
||||||
|
// Синхронизируем радиокнопки
|
||||||
|
document.getElementById('delivery-type-delivery').checked = true;
|
||||||
|
// Синхронизируем видимость секций
|
||||||
|
deliveryModeFields.style.display = 'block';
|
||||||
|
pickupFields.style.display = 'none';
|
||||||
|
console.log('[DELIVERY TYPE] UI synced: showing delivery fields');
|
||||||
|
} else {
|
||||||
|
// Синхронизируем радиокнопки
|
||||||
|
document.getElementById('delivery-type-pickup').checked = true;
|
||||||
|
// Синхронизируем видимость секций
|
||||||
|
deliveryModeFields.style.display = 'none';
|
||||||
|
pickupFields.style.display = 'block';
|
||||||
|
console.log('[DELIVERY TYPE] UI synced: showing pickup fields');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработчики для кнопок - при клике синхронизируем чекбокс с радиокнопками
|
||||||
deliveryTypeRadios.forEach(radio => {
|
deliveryTypeRadios.forEach(radio => {
|
||||||
radio.addEventListener('change', syncDeliveryType);
|
radio.addEventListener('change', syncDeliveryTypeFromRadio);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Инициализация при загрузке
|
// Инициализация при загрузке - синхронизируем UI с текущим значением чекбокса (из формы)
|
||||||
console.log('[DELIVERY TYPE] Initializing delivery type buttons');
|
console.log('[DELIVERY TYPE] Initializing delivery type, checkbox value:', isDeliveryCheckbox.checked);
|
||||||
syncDeliveryType();
|
syncUIFromCheckbox();
|
||||||
|
|
||||||
// Показ/скрытие полей получателя
|
// Показ/скрытие полей получателя
|
||||||
const customerIsRecipientCheckbox = document.getElementById('{{ form.customer_is_recipient.id_for_label }}');
|
const customerIsRecipientCheckbox = document.getElementById('{{ form.customer_is_recipient.id_for_label }}');
|
||||||
@@ -1353,8 +1388,9 @@ if (typeof $ !== 'undefined') {
|
|||||||
alert('Произошла ошибка при создании комплекта: ' + error.message);
|
alert('Произошла ошибка при создании комплекта: ' + error.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Закрытие обработчика DOMContentLoaded для управления типом доставки и остальных функций
|
||||||
});
|
});
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Модальное окно для создания нового клиента -->
|
<!-- Модальное окно для создания нового клиента -->
|
||||||
|
|||||||
Reference in New Issue
Block a user