Files
octopus/myproject/orders/services/address_service.py
Andrey Smakotin a3f5ac4c08 Fix: Enable autosave for delivery address fields with partial data
Исправлена проблема с автосохранением полей адреса доставки. Теперь адрес
сохраняется при заполнении любого поля, а не только при наличии улицы и
номера дома.

Изменения в 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>
2025-11-25 19:49:58 +03:00

147 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Сервис для работы с адресами заказов.
Содержит логику создания, обновления и управления адресами доставки.
"""
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