feat(orders): добавлены поля скидок в Order и OrderItem

Интеграция системы скидок с моделями заказов:

Order:
- applied_discount: ForeignKey на Discount
- discount_amount: сумма скидки на заказ
- applied_promo_code: использованный промокод
- calculate_total(): обновлён с учётом скидки

OrderItem:
- applied_discount: ForeignKey на Discount
- discount_amount: сумма скидки на позицию
- get_total_price(): обновлён с учётом скидки

Миграция:
- 0003_order_applied_discount... добавляет новые поля

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-11 00:30:34 +03:00
parent 241625eba7
commit 9960590dcc
4 changed files with 94 additions and 7 deletions

View File

@@ -91,6 +91,7 @@ TENANT_APPS = [
'orders', # Заказы
'inventory', # Складской учет
'pos', # POS Terminal
'discounts', # Скидки и промокоды
'system_settings', # Системные настройки компании (только для владельца)
# TODO: 'simple_history' - вернуть позже для истории изменений
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 5.0.10 on 2026-01-10 21:12
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('discounts', '0001_initial'),
('orders', '0002_initial'),
]
operations = [
migrations.AddField(
model_name='order',
name='applied_discount',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='orders', to='discounts.discount', verbose_name='Примененная скидка'),
),
migrations.AddField(
model_name='order',
name='applied_promo_code',
field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Использованный промокод'),
),
migrations.AddField(
model_name='order',
name='discount_amount',
field=models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Сумма скидки'),
),
migrations.AddField(
model_name='orderitem',
name='applied_discount',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='order_items', to='discounts.discount', verbose_name='Скидка на позицию'),
),
migrations.AddField(
model_name='orderitem',
name='discount_amount',
field=models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Сумма скидки'),
),
]

View File

@@ -69,6 +69,30 @@ class Order(models.Model):
help_text="Общая сумма заказа"
)
# Скидки
applied_discount = models.ForeignKey(
'discounts.Discount',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='orders',
verbose_name="Примененная скидка"
)
discount_amount = models.DecimalField(
max_digits=10,
decimal_places=2,
default=0,
verbose_name="Сумма скидки"
)
applied_promo_code = models.CharField(
max_length=50,
blank=True,
null=True,
verbose_name="Использованный промокод"
)
# Частичная оплата
amount_paid = models.DecimalField(
max_digits=10,
@@ -382,18 +406,21 @@ class Order(models.Model):
def calculate_total(self):
"""
Пересчитывает итоговую сумму заказа.
total_amount = subtotal + delivery_cost
total_amount = subtotal + delivery_cost - discount_amount
"""
from decimal import Decimal
subtotal = self.subtotal
delivery_cost = Decimal('0')
# Получаем стоимость доставки из связанной модели Delivery
if hasattr(self, 'delivery'):
delivery_cost = self.delivery.cost
self.total_amount = subtotal + delivery_cost
# Вычитаем скидку на весь заказ (если есть)
order_discount = Decimal(str(self.discount_amount)) if self.discount_amount else Decimal('0')
self.total_amount = subtotal + delivery_cost - order_discount
self.save(update_fields=['total_amount'])
def reset_delivery_cost(self):

View File

@@ -82,6 +82,23 @@ class OrderItem(models.Model):
help_text="True если цена была изменена вручную при создании заказа"
)
# Скидки
applied_discount = models.ForeignKey(
'discounts.Discount',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='order_items',
verbose_name="Скидка на позицию"
)
discount_amount = models.DecimalField(
max_digits=10,
decimal_places=2,
default=0,
verbose_name="Сумма скидки"
)
# Витринные продажи
is_from_showcase = models.BooleanField(
default=False,
@@ -214,8 +231,10 @@ class OrderItem(models.Model):
super().save(*args, **kwargs)
def get_total_price(self):
"""Возвращает общую стоимость позиции"""
return self.price * self.quantity
"""Возвращает общую стоимость позиции с учетом скидки"""
subtotal = self.price * self.quantity
discount = Decimal(str(self.discount_amount)) if self.discount_amount else Decimal('0')
return subtotal - discount
@property
def item_name(self):