Files
octopus/myproject/orders/services/address_service.py
Andrey Smakotin d62caa924b Упрощение системы получателей доставки
- Удалено избыточное поле customer_is_recipient из модели Order
- Добавлено свойство @property is_customer_recipient для обратной совместимости
- Заменены радиокнопки recipient_mode на чекбокс 'Другой получатель' в форме
- Добавлено поле recipient_source для выбора между историей и новым получателем
- Обновлен AddressService.process_recipient_from_form() для работы с чекбоксом
- Обновлены шаблоны: order_form.html (чекбокс вместо радиокнопок) и order_detail.html
- Удалено customer_is_recipient из admin и demo команды
- Создана миграция для удаления поля customer_is_recipient

Логика упрощена: recipient is None = получатель = покупатель, иначе - отдельный получатель
2025-12-24 17:54:57 +03:00

227 lines
9.1 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, Recipient
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(
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 create_recipient_from_form_data(form_data):
"""
Создает объект Recipient из данных формы.
Args:
form_data (dict): Словарь с данными из формы
- recipient_name
- recipient_phone
Returns:
Recipient: Новый объект получателя (не сохраненный в БД)
"""
recipient = Recipient(
name=form_data.get('recipient_name', ''),
phone=form_data.get('recipient_phone', ''),
)
return recipient
@staticmethod
def process_recipient_from_form(order, form_data):
"""
Обрабатывает получателя из данных формы заказа.
Создает нового Recipient или использует существующего в зависимости от режима.
Args:
order (Order): Объект заказа
form_data (dict): Все данные из формы
Returns:
Recipient or None: Получатель для привязки к заказу или None
"""
# Если чекбокс "Другой получатель" не включен - возвращаем None (получатель = покупатель)
other_recipient = form_data.get('other_recipient', False)
if not other_recipient:
return None
# Определяем источник получателя
recipient_source = form_data.get('recipient_source', 'new')
# Если режим "выбрать из истории" - возвращаем выбранного получателя
if recipient_source == 'history':
recipient_id = form_data.get('recipient_from_history')
if recipient_id:
try:
return Recipient.objects.get(pk=recipient_id)
except Recipient.DoesNotExist:
return None
# Если режим "новый получатель"
if recipient_source == 'new':
name = form_data.get('recipient_name', '').strip()
phone = form_data.get('recipient_phone', '').strip()
if not name or not phone:
return None
# Проверяем, есть ли уже такой получатель в БД
existing_recipient = Recipient.objects.filter(
name=name,
phone=phone
).first()
if existing_recipient:
return existing_recipient
# Создаем нового получателя
recipient = AddressService.create_recipient_from_form_data(form_data)
return recipient
return None
@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
# Проверяем, есть ли уже такой адрес в БД (по основным полям)
existing_address = Address.objects.filter(
street=street,
building_number=building_number,
apartment_number=form_data.get('address_apartment_number', '').strip()
).first()
if existing_address:
return existing_address
# Создаем новый адрес
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(
orders__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