Files
octopus/myproject/orders/models/kit_snapshot.py

164 lines
5.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Снапшоты комплектов для сохранения истории заказов.
При добавлении комплекта (ProductKit) в заказ создается снимок его состояния,
чтобы изменения в комплекте не влияли на историю заказов.
"""
from django.db import models
from decimal import Decimal
class KitSnapshot(models.Model):
"""
Снимок комплекта на момент заказа.
Сохраняет название, цены и состав комплекта.
"""
# Связь с оригинальным комплектом (для аналитики)
original_kit = models.ForeignKey(
'products.ProductKit',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='snapshots',
verbose_name="Оригинальный комплект",
help_text="Ссылка на комплект, с которого создан снимок"
)
# Копия основных данных комплекта
name = models.CharField(max_length=200, verbose_name="Название")
sku = models.CharField(max_length=100, blank=True, verbose_name="Артикул")
description = models.TextField(blank=True, verbose_name="Описание")
# Цены на момент заказа
base_price = models.DecimalField(
max_digits=10,
decimal_places=2,
default=Decimal('0'),
verbose_name="Базовая цена"
)
price = models.DecimalField(
max_digits=10,
decimal_places=2,
default=Decimal('0'),
verbose_name="Итоговая цена"
)
sale_price = models.DecimalField(
max_digits=10,
decimal_places=2,
null=True,
blank=True,
verbose_name="Цена со скидкой"
)
# Корректировки цены
price_adjustment_type = models.CharField(
max_length=20,
default='none',
verbose_name="Тип корректировки"
)
price_adjustment_value = models.DecimalField(
max_digits=10,
decimal_places=2,
default=Decimal('0'),
verbose_name="Значение корректировки"
)
is_temporary = models.BooleanField(default=False, verbose_name="Временный комплект")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
class Meta:
verbose_name = "Снимок комплекта"
verbose_name_plural = "Снимки комплектов"
ordering = ['-created_at']
indexes = [
models.Index(fields=['original_kit']),
models.Index(fields=['created_at']),
]
def __str__(self):
date_str = self.created_at.strftime('%d.%m.%Y %H:%M') if self.created_at else ''
return f"Снимок: {self.name} ({date_str})"
@property
def actual_price(self):
"""Финальная цена (sale_price или price)"""
if self.sale_price:
return self.sale_price
return self.price
def get_total_components_count(self):
"""Количество компонентов в комплекте"""
return self.items.count()
class KitItemSnapshot(models.Model):
"""
Снимок компонента комплекта.
Сохраняет информацию о товаре и его количестве в комплекте.
"""
kit_snapshot = models.ForeignKey(
KitSnapshot,
on_delete=models.CASCADE,
related_name='items',
verbose_name="Снимок комплекта"
)
# Ссылка на оригинальный товар (для резервирования)
original_product = models.ForeignKey(
'products.Product',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='kit_item_snapshots',
verbose_name="Оригинальный товар",
help_text="Ссылка на товар для резервирования на складе"
)
# Данные о товаре
product_name = models.CharField(
max_length=200,
blank=True,
verbose_name="Название товара"
)
product_sku = models.CharField(
max_length=100,
blank=True,
verbose_name="Артикул товара"
)
product_price = models.DecimalField(
max_digits=10,
decimal_places=2,
default=Decimal('0'),
verbose_name="Цена товара"
)
# Если был выбран из группы вариантов
variant_group_name = models.CharField(
max_length=200,
blank=True,
verbose_name="Группа вариантов"
)
quantity = models.DecimalField(
max_digits=10,
decimal_places=3,
verbose_name="Количество"
)
class Meta:
verbose_name = "Снимок компонента"
verbose_name_plural = "Снимки компонентов"
indexes = [
models.Index(fields=['kit_snapshot']),
]
def __str__(self):
name = self.product_name or self.variant_group_name or "Неизвестный товар"
return f"{name} x{self.quantity}"
@property
def total_price(self):
"""Стоимость компонента (цена * количество)"""
return self.product_price * self.quantity