Исправлена отображение полей адреса и стили формы заказа
## Основные изменения: ### 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:
134
myproject/orders/services/address_service.py
Normal file
134
myproject/orders/services/address_service.py
Normal 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
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user