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} руб. (с учетом скидки)"