Исправлена проблема с автосохранением полей адреса доставки. Теперь адрес сохраняется при заполнении любого поля, а не только при наличии улицы и номера дома. Изменения в Backend (address_service.py): - Изменена логика валидации в process_address_from_form() - Теперь адрес сохраняется если заполнено хотя бы одно поле - Удалено жёсткое требование заполнения street и building_number - Проверяем наличие данных во всех полях адреса Изменения в Frontend (autosave.js): - Переработана логика сбора данных адреса - address_mode='new' устанавливается при заполнении любого поля адреса - Все непустые поля адреса отправляются на сервер - Используется более элегантный подход с Object.values() и .some() Теперь автосохранение работает корректно: - Заполнение поля "Улица" → автосохранение срабатывает - Заполнение "Номер дома" → автосохранение срабатывает - Заполнение любого другого поля адреса → автосохранение срабатывает - После перезагрузки страницы все данные восстанавливаются 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
147 lines
5.9 KiB
Python
147 lines
5.9 KiB
Python
"""
|
||
Сервис для работы с адресами заказов.
|
||
Содержит логику создания, обновления и управления адресами доставки.
|
||
"""
|
||
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()
|
||
|
||
# Для автосохранения разрешаем сохранять адрес даже если не все поля заполнены
|
||
# Проверяем только что хотя бы одно поле адреса заполнено
|
||
has_any_address_data = any([
|
||
street,
|
||
building_number,
|
||
form_data.get('address_apartment_number', '').strip(),
|
||
form_data.get('address_entrance', '').strip(),
|
||
form_data.get('address_floor', '').strip(),
|
||
form_data.get('address_intercom_code', '').strip(),
|
||
form_data.get('address_delivery_instructions', '').strip(),
|
||
])
|
||
|
||
if not has_any_address_data:
|
||
# Если все поля адреса пустые, возвращаем 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
|