Исправлена отображение полей адреса и стили формы заказа

## Основные изменения:

### 1. Исправлена логика выбора режима адреса
- Переместил функцию initAddressModeToggle() из jQuery блока в отдельную функцию
- Теперь инициализация адреса работает независимо от jQuery
- Добавлены подробные логи в консоль для отладки ([ADDRESS MODE] префикс)

### 2. Добавлены CSS классы для управления видимостью
- address-history-mode: display: none !important (по умолчанию скрыт)
- address-new-mode: display: none !important (по умолчанию скрыт)
- .visible класс переводит элементы на display: block !important
- Использование classList.add/remove вместо inline styles

### 3. Исправлены стили полей формы (OrderForm)
- Добавлена явная обработка для Select полей - получают form-select
- Поле "Статус" и другие Select теперь имеют правильные стили Bootstrap
- Разделена логика для RadioSelect, Select и остальных полей

### 4. Улучшена отладка
- Добавлены console.log сообщения на каждом этапе инициализации
- Префикс [ADDRESS MODE] помогает отличить логи системы адреса от других

## Технические детали:

- Address сервис использует метод format_address_for_display() для красивого вывода
- AJAX endpoint get_customer_address_history() загружает адреса клиента
- Три режима адреса: history (из истории), new (новый адрес), empty (без адреса)
- Режим empty выбирается по умолчанию

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-11 02:49:25 +03:00
parent 7d82d67b5f
commit ddbb4f963b
16 changed files with 956 additions and 188 deletions

View File

@@ -0,0 +1,134 @@
"""
Сервис для работы с адресами заказов.
Содержит логику создания, обновления и управления адресами доставки.
"""
from ..models import Order, Address
class AddressService:
"""Сервис для управления адресами доставки в заказах"""
@staticmethod
def create_address_from_form_data(form_data):
"""
Создает объект Address из данных формы.
Args:
form_data (dict): Словарь с данными из формы
- address_street
- address_building_number
- address_apartment_number (опционально)
- address_entrance (опционально)
- address_floor (опционально)
- address_intercom_code (опционально)
- address_delivery_instructions (опционально)
Returns:
Address: Новый объект адреса (не сохраненный в БД)
"""
address = Address(
recipient_name=form_data.get('recipient_name', ''),
recipient_phone=form_data.get('recipient_phone', ''),
street=form_data.get('address_street', ''),
building_number=form_data.get('address_building_number', ''),
apartment_number=form_data.get('address_apartment_number', ''),
entrance=form_data.get('address_entrance', ''),
floor=form_data.get('address_floor', ''),
intercom_code=form_data.get('address_intercom_code', ''),
delivery_instructions=form_data.get('address_delivery_instructions', ''),
confirm_address_with_recipient=form_data.get('address_confirm_with_recipient', False),
)
return address
@staticmethod
def process_address_from_form(order, form_data):
"""
Обрабатывает адрес из данных формы заказа.
Создает новый Address или использует существующий в зависимости от режима.
Args:
order (Order): Объект заказа
form_data (dict): Все данные из формы
Returns:
Address or None: Адрес для привязки к заказу или None
"""
address_mode = form_data.get('address_mode')
# Если режим "без адреса" - возвращаем None
if address_mode == 'empty':
return None
# Если режим "выбрать из истории" - возвращаем выбранный адрес
if address_mode == 'history':
address_id = form_data.get('address_from_history')
if address_id:
try:
return Address.objects.get(pk=address_id)
except Address.DoesNotExist:
return None
# Если режим "ввести новый адрес"
if address_mode == 'new':
# Проверяем обязательные поля
street = form_data.get('address_street', '').strip()
building_number = form_data.get('address_building_number', '').strip()
if not street or not building_number:
# Если обязательные поля не заполнены, возвращаем None
return None
# Создаем новый адрес
address = AddressService.create_address_from_form_data(form_data)
return address
return None
@staticmethod
def get_customer_address_history(customer):
"""
Получает список адресов из истории заказов клиента.
Args:
customer (Customer): Клиент
Returns:
QuerySet: Адреса, отсортированные по дате создания (новые первыми)
"""
customer_orders = Order.objects.filter(
customer=customer,
delivery_address__isnull=False
).order_by('-created_at')
addresses = Address.objects.filter(
order__in=customer_orders
).distinct().order_by('-created_at')
return addresses
@staticmethod
def format_address_for_display(address):
"""
Форматирует адрес для отображения в списке.
Args:
address (Address): Объект адреса
Returns:
str: Форматированная строка адреса
"""
address_line = f"{address.street}, {address.building_number}"
if address.apartment_number:
address_line += f", кв. {address.apartment_number}"
details = []
if address.entrance:
details.append(f"подъезд {address.entrance}")
if address.floor:
details.append(f"этаж {address.floor}")
if details:
address_line += f" ({', '.join(details)})"
return address_line

View File

@@ -9,8 +9,9 @@ from decimal import Decimal
import decimal
from datetime import datetime, date, time
from ..models import Order, OrderItem
from ..models import Order, OrderItem, Address
from products.models import Product, ProductKit
from .address_service import AddressService
class DraftOrderService:
@@ -87,7 +88,6 @@ class DraftOrderService:
# ForeignKey поля требуют специальной обработки
fk_fields = {
'customer': 'customers.Customer',
'delivery_address': 'customers.Address',
'pickup_shop': 'shops.Shop',
}
@@ -113,6 +113,31 @@ class DraftOrderService:
except Model.DoesNotExist:
pass # Игнорируем несуществующие объекты
# === Обработка адреса доставки ===
# Новая логика с выбором режима адреса
if 'address_mode' in data:
address = AddressService.process_address_from_form(order, data)
if address:
# Если адрес не существует в БД, сохраняем его
if not address.pk:
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()
elif 'delivery_address' in data and data['delivery_address']:
# Старая логика для совместимости (если передается delivery_address напрямую)
try:
address = Address.objects.get(pk=data['delivery_address'])
order.delivery_address = address
except Address.DoesNotExist:
pass
# Обрабатываем простые поля
for field in simple_fields:
if field in data: