""" Сервис для работы с адресами и получателями заказов. Содержит логику создания, обновления и управления адресами доставки и получателями. """ 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 # Если у заказа уже есть получатель - обновляем его вместо создания нового # Загружаем заказ из БД, чтобы получить актуального получателя if order.pk: try: # Order уже импортирован в начале файла db_order = Order.objects.select_related('recipient').get(pk=order.pk) if db_order.recipient: # Обновляем существующего получателя db_order.recipient.name = name db_order.recipient.phone = phone # Сохранять будем в views.py, здесь просто возвращаем объект return db_order.recipient except Order.DoesNotExist: pass # Проверяем, есть ли уже такой получатель в БД (по имени и телефону) 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