From d62caa924b232bc0259013044c87c85bafc2afa9 Mon Sep 17 00:00:00 2001 From: Andrey Smakotin Date: Wed, 24 Dec 2025 17:54:57 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BF=D1=80=D0=BE=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D1=8B=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B0=D1=82=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9=20=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Удалено избыточное поле 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 = получатель = покупатель, иначе - отдельный получатель --- myproject/orders/admin.py | 4 +- myproject/orders/forms.py | 58 +++++--- .../management/commands/create_demo_orders.py | 1 - .../0003_remove_customer_is_recipient.py | 21 +++ myproject/orders/models/order.py | 13 +- myproject/orders/models/recipient.py | 2 +- myproject/orders/services/address_service.py | 14 +- .../orders/templates/orders/order_detail.html | 2 +- .../orders/templates/orders/order_form.html | 135 +++++++++++------- 9 files changed, 168 insertions(+), 82 deletions(-) create mode 100644 myproject/orders/migrations/0003_remove_customer_is_recipient.py diff --git a/myproject/orders/admin.py b/myproject/orders/admin.py index 3e8dba2..dbdb034 100644 --- a/myproject/orders/admin.py +++ b/myproject/orders/admin.py @@ -86,9 +86,9 @@ class OrderAdmin(admin.ModelAdmin): }), ('Получатель', { 'fields': ( - 'customer_is_recipient', 'recipient', - ) + ), + 'description': 'Если получатель не указан, получателем является покупатель' }), ('Оплата', { 'fields': ( diff --git a/myproject/orders/forms.py b/myproject/orders/forms.py index 69e520b..890a706 100644 --- a/myproject/orders/forms.py +++ b/myproject/orders/forms.py @@ -11,16 +11,24 @@ class OrderForm(forms.ModelForm): """Форма для создания и редактирования заказа""" # Поля для работы с получателем - recipient_mode = forms.ChoiceField( + other_recipient = forms.BooleanField( + required=False, + initial=False, + widget=forms.CheckboxInput(attrs={'class': 'form-check-input'}), + label='Другой получатель', + help_text='Если отмечено, получатель отличается от покупателя' + ) + + # Режим выбора другого получателя (история или новый) + recipient_source = forms.ChoiceField( choices=[ - ('customer', 'Покупатель является получателем'), ('history', 'Выбрать из истории'), - ('new', 'Другой получатель'), + ('new', 'Новый получатель'), ], - initial='customer', + initial='new', widget=forms.RadioSelect(attrs={'class': 'form-check-input'}), required=False, - label='Получатель' + label='Способ указания получателя' ) # Выбор получателя из истории @@ -170,7 +178,6 @@ class OrderForm(forms.ModelForm): model = Order fields = [ 'customer', - 'customer_is_recipient', 'recipient', 'status', 'is_anonymous', @@ -232,28 +239,47 @@ class OrderForm(forms.ModelForm): 'data-placeholder': 'Начните вводить имя, телефон или email' }) - # Подсказки - self.fields['customer_is_recipient'].label = 'Покупатель = получатель' - # Поле получателя опционально self.fields['recipient'].required = False + # Инициализируем чекбокс other_recipient на основе наличия recipient + if self.instance.pk: + # При редактировании заказа: если есть recipient, чекбокс включен + if self.instance.recipient: + self.fields['other_recipient'].initial = True + # Определяем источник получателя + # Проверяем, есть ли этот recipient в истории клиента + if self.instance.customer: + customer_orders = Order.objects.filter( + customer=self.instance.customer, + recipient__isnull=False + ).exclude(pk=self.instance.pk).order_by('-created_at') + history_recipients = Recipient.objects.filter( + orders__in=customer_orders + ).distinct() + if self.instance.recipient in history_recipients: + self.fields['recipient_source'].initial = 'history' + self.fields['recipient_from_history'].initial = self.instance.recipient.pk + else: + self.fields['recipient_source'].initial = 'new' + self.fields['recipient_name'].initial = self.instance.recipient.name or '' + self.fields['recipient_phone'].initial = self.instance.recipient.phone or '' + else: + self.fields['other_recipient'].initial = False + # Инициализируем 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') + ).exclude(pk=self.instance.pk).order_by('-created_at') self.fields['recipient_from_history'].queryset = Recipient.objects.filter( 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 '' + elif not self.instance.pk: + # При создании нового заказа queryset пустой (будет заполнен через JS при выборе клиента) + self.fields['recipient_from_history'].queryset = Recipient.objects.none() # Инициализируем queryset для pickup_warehouse from inventory.models import Warehouse diff --git a/myproject/orders/management/commands/create_demo_orders.py b/myproject/orders/management/commands/create_demo_orders.py index 3924ff6..9af66e0 100644 --- a/myproject/orders/management/commands/create_demo_orders.py +++ b/myproject/orders/management/commands/create_demo_orders.py @@ -132,7 +132,6 @@ class Command(BaseCommand): # Дополнительная информация if random.random() > 0.7: # 30% - подарок другому человеку - order.customer_is_recipient = False # Создаем получателя recipient_name = f"Получатель {i+1}" recipient_phone = f"+7{random.randint(9000000000, 9999999999)}" diff --git a/myproject/orders/migrations/0003_remove_customer_is_recipient.py b/myproject/orders/migrations/0003_remove_customer_is_recipient.py new file mode 100644 index 0000000..538fb85 --- /dev/null +++ b/myproject/orders/migrations/0003_remove_customer_is_recipient.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.10 on 2025-12-24 10:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('orders', '0002_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='historicalorder', + name='customer_is_recipient', + ), + migrations.RemoveField( + model_name='order', + name='customer_is_recipient', + ), + ] diff --git a/myproject/orders/models/order.py b/myproject/orders/models/order.py index 477c90c..dbda011 100644 --- a/myproject/orders/models/order.py +++ b/myproject/orders/models/order.py @@ -94,13 +94,7 @@ class Order(models.Model): ) # Информация о получателе - customer_is_recipient = models.BooleanField( - default=True, - verbose_name="Покупатель является получателем", - help_text="Если отмечено, данные получателя не требуются отдельно" - ) - - # Получатель (если покупатель != получатель) + # Получатель (если None - получатель = покупатель, иначе - отдельный получатель) recipient = models.ForeignKey( Recipient, on_delete=models.SET_NULL, @@ -324,3 +318,8 @@ class Order(models.Model): if hasattr(self, 'delivery') and self.delivery: return self.delivery.pickup_warehouse return None + + @property + def is_customer_recipient(self): + """Является ли покупатель получателем (обратная совместимость)""" + return self.recipient is None diff --git a/myproject/orders/models/recipient.py b/myproject/orders/models/recipient.py index df03746..30fb394 100644 --- a/myproject/orders/models/recipient.py +++ b/myproject/orders/models/recipient.py @@ -38,4 +38,4 @@ class Recipient(models.Model): @property def display_name(self): """Форматированное имя для отображения""" - return f"{self.name} - {self.phone}" + return f"Получатель{self.name} - {self.phone}" diff --git a/myproject/orders/services/address_service.py b/myproject/orders/services/address_service.py index 71c45e2..f737de7 100644 --- a/myproject/orders/services/address_service.py +++ b/myproject/orders/services/address_service.py @@ -70,14 +70,16 @@ class AddressService: Returns: Recipient or None: Получатель для привязки к заказу или None """ - recipient_mode = form_data.get('recipient_mode') - - # Если режим "покупатель = получатель" - возвращаем None - if recipient_mode == 'customer': + # Если чекбокс "Другой получатель" не включен - возвращаем 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_mode == 'history': + if recipient_source == 'history': recipient_id = form_data.get('recipient_from_history') if recipient_id: try: @@ -86,7 +88,7 @@ class AddressService: return None # Если режим "новый получатель" - if recipient_mode == 'new': + if recipient_source == 'new': name = form_data.get('recipient_name', '').strip() phone = form_data.get('recipient_phone', '').strip() diff --git a/myproject/orders/templates/orders/order_detail.html b/myproject/orders/templates/orders/order_detail.html index dcb04d3..0ac4c74 100644 --- a/myproject/orders/templates/orders/order_detail.html +++ b/myproject/orders/templates/orders/order_detail.html @@ -131,7 +131,7 @@ - {% if not order.customer_is_recipient and order.recipient %} + {% if order.recipient %}
Получатель
diff --git a/myproject/orders/templates/orders/order_form.html b/myproject/orders/templates/orders/order_form.html index 0d71cff..9f93ec0 100644 --- a/myproject/orders/templates/orders/order_form.html +++ b/myproject/orders/templates/orders/order_form.html @@ -532,54 +532,74 @@
Получатель
- +
- {% for choice in form.recipient_mode %}
- {{ choice.tag }} -
- {% endfor %} - {% if form.recipient_mode.errors %} -
{{ form.recipient_mode.errors }}
+ {% if form.other_recipient.errors %} +
{{ form.other_recipient.errors }}
{% endif %}
- - - - -