from django.db import models from .base import BaseDiscount class Discount(BaseDiscount): """ Основная модель скидки. Наследует все поля из BaseDiscount и добавляет специфические параметры. """ # Для scope='order' - минимальная сумма заказа min_order_amount = models.DecimalField( max_digits=10, decimal_places=2, null=True, blank=True, verbose_name="Мин. сумма заказа", help_text="Скидка применяется только если сумма заказа >= этого значения" ) # Для scope='product' и scope='category' - товары и категории products = models.ManyToManyField( 'products.Product', blank=True, related_name='discounts', verbose_name="Товары" ) categories = models.ManyToManyField( 'products.ProductCategory', blank=True, related_name='discounts', verbose_name="Категории" ) # Исключения (товары, к которым скидка НЕ применяется) excluded_products = models.ManyToManyField( 'products.Product', blank=True, related_name='excluded_from_discounts', verbose_name="Исключенные товары" ) # Автоматическая скидка (не требует промокода) is_auto = models.BooleanField( default=False, verbose_name="Автоматическая", help_text="Применяется автоматически при выполнении условий" ) class Meta: verbose_name = "Скидка" verbose_name_plural = "Скидки" indexes = [ models.Index(fields=['is_active']), models.Index(fields=['scope']), models.Index(fields=['discount_type']), models.Index(fields=['is_auto']), ] def applies_to_product(self, product): """ Проверить, применяется ли скидка к товару. Args: product: Объект Product Returns: bool: True если скидка применяется к товару """ # Проверяем исключения if self.excluded_products.filter(id=product.id).exists(): return False # Если scope='product', проверяем прямое соответствие if self.scope == 'product': return self.products.filter(id=product.id).exists() # Если scope='category', проверяем категории товара if self.scope == 'category': if not self.categories.exists(): return False product_categories = product.categories.all() return self.categories.filter(id__in=product_categories).exists() return False def get_applicable_products(self): """ Получить queryset товаров, к которым применяется эта скидка. Returns: QuerySet: Товары, к которым применяется скидка """ from products.models import Product if self.scope == 'product': qs = self.products.all() # Исключаем исключенные товары if self.excluded_products.exists(): qs = qs.exclude(id__in=self.excluded_products.values_list('id', flat=True)) return qs if self.scope == 'category': # Товары из указанных категорий product_ids = Product.objects.filter( categories__in=self.categories.all() ).values_list('id', flat=True).distinct() # Исключаем исключенные товары if self.excluded_products.exists(): excluded_ids = self.excluded_products.values_list('id', flat=True) product_ids = set(product_ids) - set(excluded_ids) return Product.objects.filter(id__in=product_ids) return Product.objects.none()