""" Модели для работы с группами вариантов товаров. Позволяет группировать взаимозаменяемые товары (например, розы разной длины). """ from django.db import models class ProductVariantGroup(models.Model): """ Группа вариантов товара (взаимозаменяемые товары). Например: "Роза красная Freedom" включает розы 50см, 60см, 70см. """ name = models.CharField(max_length=200, verbose_name="Название") description = models.TextField(blank=True, verbose_name="Описание") 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 = "Группы вариантов" ordering = ['name'] def __str__(self): return self.name def get_products_count(self): """Возвращает количество товаров в группе""" return self.items.count() @property def in_stock(self): """ Вариант в наличии, если хотя бы один из его товаров в наличии. Товар в наличии, если Product.in_stock = True. """ return self.items.filter(product__in_stock=True).exists() @property def price(self): """ Цена варианта определяется по приоритету товаров: 1. Берётся цена товара с приоритетом 1, если он в наличии 2. Если нет - цена товара с приоритетом 2 3. И так далее по приоритетам 4. Если ни один товар не в наличии - берётся самый дорогой товар из группы Возвращает Decimal (цену) или None если группа пуста. """ items = self.items.all().order_by('priority', 'id') if not items.exists(): return None # Ищем первый товар в наличии for item in items: if item.product.in_stock: return item.product.sale_price # Если ни один товар не в наличии - берем самый дорогой max_price = None for item in items: if max_price is None or item.product.sale_price > max_price: max_price = item.product.sale_price return max_price class ProductVariantGroupItem(models.Model): """ Товар в группе вариантов с приоритетом для этой конкретной группы. Приоритет определяет порядок выбора товара при использовании группы в комплектах. Например: в группе "Роза красная Freedom" - роза 50см имеет приоритет 1, 60см = 2, 70см = 3. """ variant_group = models.ForeignKey( ProductVariantGroup, on_delete=models.CASCADE, related_name='items', verbose_name="Группа вариантов" ) product = models.ForeignKey( 'Product', on_delete=models.CASCADE, related_name='variant_group_items', verbose_name="Товар" ) priority = models.PositiveIntegerField( default=0, help_text="Меньше = выше приоритет (1 - наивысший приоритет в этой группе)" ) class Meta: verbose_name = "Товар в группе вариантов" verbose_name_plural = "Товары в группах вариантов" ordering = ['priority', 'id'] unique_together = [['variant_group', 'product']] indexes = [ models.Index(fields=['variant_group', 'priority']), models.Index(fields=['product']), ] def __str__(self): return f"{self.variant_group.name} - {self.product.name} (приоритет {self.priority})"