You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
6.4 KiB

2 days ago
from django.db import models
# Справочник товаров
class Product(models.Model):
name = models.CharField(max_length=255, verbose_name="Наименование товара")
manufacturer_name = models.CharField(max_length=255, verbose_name="Производитель")
manufacturer_country = models.CharField(max_length=255, verbose_name="Страна производителя")
manufacturer_code = models.CharField(max_length=50, verbose_name="Код производителя", blank=True, null=True)
dimensions = models.CharField(max_length=255, verbose_name="Размеры", blank=True, null=True)
unit_of_measure = models.CharField(max_length=50, verbose_name="Единица измерения")
shelf_life_days = models.IntegerField(verbose_name="Срок годности (дни)")
barcode = models.CharField(max_length=50, unique=True, verbose_name="Штрихкод")
def __str__(self):
return self.name
# Типы цен (например, регулярная, скидочная, акционная)
class PriceType(models.Model):
name = models.CharField(max_length=50, verbose_name="Тип цены", choices=[
('regular', 'Регулярная'),
('discount', 'Скидочная'),
('promotional', 'Акционная'),
])
def __str__(self):
return self.name
# Прайс-листы (со всеми ценами)
class PriceList(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
price_type = models.ForeignKey(PriceType, on_delete=models.CASCADE, verbose_name="Тип цены")
entry_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Входная цена")
final_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена")
date_effective = models.DateField(verbose_name="Дата вступления в силу")
constraint_percent_limit = models.DecimalField(max_digits=5, decimal_places=2, default=1000, verbose_name="Лимит на наценку (%)")
constraint_price_change = models.DecimalField(max_digits=5, decimal_places=2, default=90, verbose_name="Лимит на изменение цены (%)")
def save(self, *args, **kwargs):
# Логика проверки на изменение цены
if self.pk:
old_price = PriceList.objects.get(pk=self.pk).final_price
price_change_percent = abs((self.final_price - old_price) / old_price) * 100
if price_change_percent > self.constraint_price_change:
raise ValueError(f"Цена не может измениться более чем на {self.constraint_price_change}%")
super().save(*args, **kwargs)
def __str__(self):
return f"{self.product.name} - {self.price_type.name} - {self.final_price} руб."
# Скидки и акции (могут применяться к товарам)
class Discount(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
discount_percentage = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Процент скидки")
start_date = models.DateField(verbose_name="Дата начала")
end_date = models.DateField(verbose_name="Дата окончания")
description = models.TextField(verbose_name="Описание акции", blank=True, null=True)
def __str__(self):
return f"Скидка {self.discount_percentage}% на {self.product.name} с {self.start_date} по {self.end_date}"
# История изменений цен
class PriceChangeHistory(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
old_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Старая цена")
new_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Новая цена")
change_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата изменения цены")
reason = models.TextField(verbose_name="Причина изменения цены", blank=True, null=True)
def __str__(self):
return f"{self.product.name} - изменение цены с {self.old_price} на {self.new_price} - {self.change_date}"
# Пример использования ценников для печати
class PriceTag(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="Товар")
price_list = models.ForeignKey(PriceList, on_delete=models.CASCADE, verbose_name="Прайс-лист")
tag_image = models.ImageField(upload_to='price_tags/', verbose_name="Изображение ценника", blank=True, null=True)
price_effective_date = models.DateField(verbose_name="Дата вступления в силу ценника")
def __str__(self):
return f"Ценник для {self.product.name} - {self.price_effective_date}"
# Связь с историей акций
class DiscountHistory(models.Model):
discount = models.ForeignKey(Discount, on_delete=models.CASCADE, verbose_name="Акция/Скидка")
old_discount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Старая скидка")
new_discount = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="Новая скидка")
change_date = models.DateTimeField(auto_now_add=True, verbose_name="Дата изменения скидки")
reason = models.TextField(verbose_name="Причина изменения скидки", blank=True, null=True)
def __str__(self):
return f"Изменение скидки с {self.old_discount}% на {self.new_discount}% для {self.discount.product.name}"
# Пример применения скидки к прайс-листу
class PriceListWithDiscount(models.Model):
price_list = models.ForeignKey(PriceList, on_delete=models.CASCADE, verbose_name="Прайс-лист")
discount = models.ForeignKey(Discount, on_delete=models.CASCADE, verbose_name="Скидка")
final_price_after_discount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена после скидки")
def __str__(self):
return f"{self.price_list.product.name} - {self.final_price_after_discount} руб. (с учетом скидки)"