feat(orders): add recipient management and enhance order forms

- Introduced Recipient model to manage order recipients separately from customers.
- Updated Order model to link to Recipient, replacing recipient_name and recipient_phone fields.
- Enhanced OrderForm to include recipient selection modes: customer, history, and new.
- Added AJAX endpoint to fetch recipient history for customers.
- Updated admin interface to manage recipients and display recipient information in order details.
- Refactored address handling to accommodate new recipient logic.
- Improved demo order creation to include random recipients.
This commit is contained in:
2025-12-23 00:08:41 +03:00
parent 483f150e7a
commit 6669d47cdf
15 changed files with 559 additions and 110 deletions

View File

@@ -1,12 +1,12 @@
"""
Сервис для работы с адресами заказов.
Содержит логику создания, обновления и управления адресами доставки.
Сервис для работы с адресами и получателями заказов.
Содержит логику создания, обновления и управления адресами доставки и получателями.
"""
from ..models import Order, Address
from ..models import Order, Address, Recipient
class AddressService:
"""Сервис для управления адресами доставки в заказах"""
"""Сервис для управления адресами доставки и получателями в заказах"""
@staticmethod
def create_address_from_form_data(form_data):
@@ -27,8 +27,6 @@ class AddressService:
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', ''),
@@ -40,6 +38,76 @@ class AddressService:
)
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
"""
recipient_mode = form_data.get('recipient_mode')
# Если режим "покупатель = получатель" - возвращаем None
if recipient_mode == 'customer':
return None
# Если режим "выбрать из истории" - возвращаем выбранного получателя
if recipient_mode == '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_mode == '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):
"""
@@ -90,7 +158,17 @@ class AddressService:
# Если все поля адреса пустые, возвращаем 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
@@ -113,7 +191,7 @@ class AddressService:
).order_by('-created_at')
addresses = Address.objects.filter(
order__in=customer_orders
orders__in=customer_orders
).distinct().order_by('-created_at')
return addresses