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,7 +1,7 @@
# -*- coding: utf-8 -*-
from django import forms
from django.forms import inlineformset_factory
from .models import Order, OrderItem, Transaction, Address, OrderStatus
from .models import Order, OrderItem, Transaction, Address, OrderStatus, Recipient
from customers.models import Customer
from inventory.models import Warehouse
from products.models import Product, ProductKit
@@ -11,7 +11,43 @@ from decimal import Decimal
class OrderForm(forms.ModelForm):
"""Форма для создания и редактирования заказа"""
# Поля для ввода адреса
# Поля для работы с получателем
recipient_mode = forms.ChoiceField(
choices=[
('customer', 'Покупатель является получателем'),
('history', 'Выбрать из истории'),
('new', 'Другой получатель'),
],
initial='customer',
widget=forms.RadioSelect(attrs={'class': 'form-check-input'}),
required=False,
label='Получатель'
)
# Выбор получателя из истории
recipient_from_history = forms.ModelChoiceField(
queryset=Recipient.objects.none(),
required=False,
widget=forms.Select(attrs={'class': 'form-select'}),
label='Получатель из истории'
)
# Поля для нового получателя
recipient_name = forms.CharField(
max_length=200,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Имя получателя'}),
label='Имя получателя'
)
recipient_phone = forms.CharField(
max_length=20,
required=False,
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Телефон получателя'}),
label='Телефон получателя'
)
# Поля для работы с адресом
address_mode = forms.ChoiceField(
choices=[
('history', 'Выбрать из истории'),
@@ -99,8 +135,7 @@ class OrderForm(forms.ModelForm):
'delivery_time_end',
'delivery_cost',
'customer_is_recipient',
'recipient_name',
'recipient_phone',
'recipient',
'status',
'is_anonymous',
'special_instructions',
@@ -186,15 +221,25 @@ class OrderForm(forms.ModelForm):
self.fields['is_delivery'].label = 'С доставкой'
self.fields['customer_is_recipient'].label = 'Покупатель = получатель'
# Поля получателя опциональны
self.fields['recipient_name'].required = False
self.fields['recipient_phone'].required = False
# Поле получателя опционально
self.fields['recipient'].required = False
# Поле ручной стоимости доставки опционально
self.fields['delivery_cost'].required = False
self.fields['delivery_cost'].label = 'Ручная стоимость доставки'
self.fields['delivery_cost'].help_text = 'Оставьте пустым для автоматического расчета'
# Инициализируем queryset для recipient_from_history
if self.instance.pk and self.instance.customer:
# При редактировании заказа загружаем историю получателей этого клиента
customer_orders = Order.objects.filter(
customer=self.instance.customer,
recipient__isnull=False
).order_by('-created_at')
self.fields['recipient_from_history'].queryset = Recipient.objects.filter(
orders__in=customer_orders
).distinct().order_by('-created_at')
# Инициализируем queryset для address_from_history
# Это будет переопределено в представлении после выбора клиента
if self.instance.pk and self.instance.customer:
@@ -204,9 +249,15 @@ class OrderForm(forms.ModelForm):
delivery_address__isnull=False
).order_by('-created_at')
self.fields['address_from_history'].queryset = Address.objects.filter(
order__in=customer_orders
orders__in=customer_orders
).distinct().order_by('-created_at')
# Инициализируем поля получателя из существующего recipient
if self.instance.pk and self.instance.recipient:
recipient = self.instance.recipient
self.fields['recipient_name'].initial = recipient.name or ''
self.fields['recipient_phone'].initial = recipient.phone or ''
# Инициализируем поля адреса из существующего delivery_address
if self.instance.pk and self.instance.delivery_address:
address = self.instance.delivery_address