from django.db import models from django.urls import reverse from django.utils.html import strip_tags from django.conf import settings import re class ProductCategory(models.Model): """Категория продуктов""" name = models.CharField(max_length=100, unique=True, verbose_name="Название") slug = models.SlugField(max_length=120, unique=True, verbose_name="URL") description = models.TextField(blank=True, verbose_name="Описание") class Meta: verbose_name = "Категория продуктов" verbose_name_plural = "Категории продуктов" def __str__(self): return self.name class Configuration(models.Model): """Конфигурация 1С, к которой относится продукт""" name = models.CharField(max_length=200, unique=True, verbose_name="Название") slug = models.SlugField(max_length=220, unique=True, verbose_name="URL") description = models.TextField(blank=True, verbose_name="Описание") class Meta: verbose_name = "Конфигурация 1С" verbose_name_plural = "Конфигурации 1С" def __str__(self): return self.name class Product(models.Model): """Программный продукт / модуль 1С""" title = models.CharField(max_length=200, verbose_name="Название") slug = models.SlugField(max_length=220, unique=True, verbose_name="URL") category = models.ForeignKey( ProductCategory, on_delete=models.PROTECT, related_name="products", verbose_name="Категория" ) short_description = models.TextField( verbose_name="Краткое описание", help_text="Отображается в списке продуктов" ) content = models.TextField(verbose_name="Полное описание") price = models.DecimalField( max_digits=10, decimal_places=2, verbose_name="Цена", help_text="Будет видна только зарегистрированным пользователям" ) image = models.ImageField( upload_to="products/%Y/%m/%d/", blank=True, verbose_name="Изображение" ) configurations = models.ManyToManyField( Configuration, blank=True, related_name="products", verbose_name="Совместимые конфигурации" ) is_published = models.BooleanField(default=True, verbose_name="Опубликовано") time_create = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") time_update = models.DateTimeField(auto_now=True, verbose_name="Дата изменения") meta_description = models.CharField( max_length=160, blank=True, verbose_name="Meta-описание", help_text="Краткое описание для поисковых систем (до 160 символов)" ) class Meta: verbose_name = "Продукт" verbose_name_plural = "Продукты" ordering = ["-time_create"] indexes = [ models.Index(fields=["-time_create", "is_published"]), ] def __str__(self): return self.title def get_absolute_url(self): return reverse("products:product_detail", kwargs={"slug": self.slug}) def get_seo_title(self): return f"{self.title} | Продукты С.Н.А. Технологии" def get_seo_description(self): if self.meta_description: return self.meta_description clean = re.sub(r'\s+', ' ', strip_tags(self.short_description)).strip() return clean[:157] + '…' if len(clean) > 160 else clean class Order(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='Продукт') configuration = models.ForeignKey( Configuration, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='Конфигурация 1С' ) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='Пользователь' ) name = models.CharField(max_length=100, verbose_name='Имя') phone = models.CharField(max_length=20, verbose_name='Телефон') email = models.EmailField(verbose_name='Email') address = models.TextField(blank=True, verbose_name='Адрес доставки') comment = models.TextField(blank=True, verbose_name='Комментарий') created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата заказа') is_processed = models.BooleanField(default=False, verbose_name='Обработан') notification_sent = models.BooleanField(default=False, verbose_name='Уведомление отправлено') class Meta: verbose_name = 'Заказ' verbose_name_plural = 'Заказы' ordering = ['-created_at'] def __str__(self): return f'Заказ #{self.id} – {self.product.title} от {self.name}'