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:
@@ -4,6 +4,7 @@
|
||||
Структура:
|
||||
- OrderStatus: Статусы заказов
|
||||
- Address: Адреса доставки
|
||||
- Recipient: Получатели заказов
|
||||
- Order: Главная модель заказа
|
||||
- OrderItem: Позиции в заказе
|
||||
- PaymentMethod: Способы оплаты (справочник)
|
||||
@@ -17,6 +18,7 @@ from .payment_method import PaymentMethod
|
||||
|
||||
# 2. Модели с зависимостями от справочников
|
||||
from .address import Address
|
||||
from .recipient import Recipient
|
||||
|
||||
# 3. Главная модель Order (зависит от Status, Address)
|
||||
from .order import Order
|
||||
@@ -29,6 +31,7 @@ from .transaction import Transaction
|
||||
__all__ = [
|
||||
'OrderStatus',
|
||||
'Address',
|
||||
'Recipient',
|
||||
'Order',
|
||||
'OrderItem',
|
||||
'PaymentMethod',
|
||||
|
||||
@@ -3,26 +3,9 @@ from django.db import models
|
||||
|
||||
class Address(models.Model):
|
||||
"""
|
||||
Модель адреса доставки для заказа цветочного магазина в Минске.
|
||||
Адрес принадлежит конкретному заказу доставки.
|
||||
Модель адреса доставки.
|
||||
Адрес может использоваться в разных заказах и для разных получателей.
|
||||
"""
|
||||
# Информация о получателе
|
||||
recipient_name = models.CharField(
|
||||
max_length=200,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Имя получателя",
|
||||
help_text="Имя человека, которому будет доставлен заказ"
|
||||
)
|
||||
|
||||
recipient_phone = models.CharField(
|
||||
max_length=20,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Телефон получателя",
|
||||
help_text="Контактный телефон получателя для уточнения адреса"
|
||||
)
|
||||
|
||||
street = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
@@ -103,12 +86,7 @@ class Address(models.Model):
|
||||
if self.apartment_number:
|
||||
address_parts.append(f"кв/офис {self.apartment_number}")
|
||||
|
||||
address_line = ", ".join(address_parts) if address_parts else "Адрес не указан"
|
||||
|
||||
# Формируем строку с именем получателя
|
||||
if self.recipient_name:
|
||||
return f"{self.recipient_name} - {address_line}"
|
||||
return address_line
|
||||
return ", ".join(address_parts) if address_parts else "Адрес не указан"
|
||||
|
||||
@property
|
||||
def full_address(self):
|
||||
|
||||
@@ -6,6 +6,7 @@ from inventory.models import Warehouse
|
||||
from simple_history.models import HistoricalRecords
|
||||
from .status import OrderStatus
|
||||
from .address import Address
|
||||
from .recipient import Recipient
|
||||
|
||||
|
||||
class Order(models.Model):
|
||||
@@ -38,12 +39,12 @@ class Order(models.Model):
|
||||
)
|
||||
|
||||
# Адрес доставки (для курьерской доставки)
|
||||
delivery_address = models.OneToOneField(
|
||||
delivery_address = models.ForeignKey(
|
||||
Address,
|
||||
on_delete=models.CASCADE,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='order',
|
||||
related_name='orders',
|
||||
verbose_name="Адрес доставки",
|
||||
help_text="Обязательно для курьерской доставки"
|
||||
)
|
||||
@@ -160,30 +161,24 @@ class Order(models.Model):
|
||||
help_text="Обновляется автоматически при добавлении платежей"
|
||||
)
|
||||
|
||||
# Дополнительная информация
|
||||
# Информация о получателе
|
||||
customer_is_recipient = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name="Покупатель является получателем",
|
||||
help_text="Если отмечено, данные получателя не требуются отдельно"
|
||||
)
|
||||
|
||||
# Данные получателя (если покупатель != получатель)
|
||||
recipient_name = models.CharField(
|
||||
max_length=200,
|
||||
blank=True,
|
||||
# Получатель (если покупатель != получатель)
|
||||
recipient = models.ForeignKey(
|
||||
Recipient,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
verbose_name="Имя получателя",
|
||||
blank=True,
|
||||
related_name='orders',
|
||||
verbose_name="Получатель",
|
||||
help_text="Заполняется, если покупатель не является получателем"
|
||||
)
|
||||
|
||||
recipient_phone = models.CharField(
|
||||
max_length=20,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Телефон получателя",
|
||||
help_text="Контактный телефон получателя"
|
||||
)
|
||||
|
||||
is_anonymous = models.BooleanField(
|
||||
default=False,
|
||||
verbose_name="Анонимная доставка",
|
||||
|
||||
41
myproject/orders/models/recipient.py
Normal file
41
myproject/orders/models/recipient.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Recipient(models.Model):
|
||||
"""
|
||||
Модель получателя заказа.
|
||||
Один получатель может получать доставки по разным адресам.
|
||||
"""
|
||||
name = models.CharField(
|
||||
max_length=200,
|
||||
verbose_name="Имя получателя",
|
||||
help_text="ФИО или название организации получателя"
|
||||
)
|
||||
|
||||
phone = models.CharField(
|
||||
max_length=20,
|
||||
verbose_name="Телефон получателя",
|
||||
help_text="Контактный телефон для связи с получателем"
|
||||
)
|
||||
|
||||
# Временные метки
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Получатель"
|
||||
verbose_name_plural = "Получатели"
|
||||
indexes = [
|
||||
models.Index(fields=['phone']),
|
||||
models.Index(fields=['name']),
|
||||
models.Index(fields=['created_at']),
|
||||
]
|
||||
ordering = ['-created_at']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.phone})"
|
||||
|
||||
@property
|
||||
def display_name(self):
|
||||
"""Форматированное имя для отображения"""
|
||||
return f"{self.name} - {self.phone}"
|
||||
Reference in New Issue
Block a user