import uuid from django.db import models from .persian_text import normalize_persian_text class PersianTextNormalizationMixin: """Normalize only explicitly listed human-authored model fields on save.""" persian_text_fields = {} def save(self, *args, **kwargs): update_fields = kwargs.get("update_fields") for field_name, multiline in self.persian_text_fields.items(): if update_fields is None or field_name in update_fields: value = getattr(self, field_name, None) if value is not None: setattr( self, field_name, normalize_persian_text(value, multiline=multiline), ) return super().save(*args, **kwargs) class TimeStampedModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: abstract = True class PublicIdModel(models.Model): public_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) class Meta: abstract = True class SiteBranding(models.Model): """Database-backed copy shared by customer, authentication and staff pages.""" site_title = models.CharField(max_length=160, default="گفت‌وگو با واحد فروش") header_title = models.CharField(max_length=160, default="گفت‌وگو با واحد فروش") header_subtitle = models.CharField(max_length=200, default="درخواست روشن، پیگیری مطمئن") staff_brand_title = models.CharField(max_length=160, default="گفت‌وگو با واحد فروش") staff_brand_subtitle = models.CharField(max_length=200, default="مرکز ارتباط با مشتری") staff_panel_label = models.CharField(max_length=120, default="پنل کارشناسان") pwa_title = models.CharField(max_length=80, default="واحد فروش") company_logo = models.ImageField(upload_to="branding/logo/", blank=True, verbose_name="لوگوی اصلی") favicon = models.ImageField(upload_to="branding/favicon/", blank=True, verbose_name="Favicon") pwa_icon = models.ImageField(upload_to="branding/pwa/", blank=True, verbose_name="آیکون PWA") pwa_name = models.CharField(max_length=160, default="گفت‌وگو با واحد فروش", verbose_name="نام کامل PWA") pwa_description = models.CharField(max_length=300, default="ثبت و پیگیری درخواست‌های فروش لوله گستر گلپایگان", verbose_name="توضیح PWA") pwa_install_label = models.CharField(max_length=160, default="نصب گفت‌وگو با واحد فروش", verbose_name="عنوان پیشنهاد نصب PWA") pwa_install_help = models.CharField(max_length=300, default="برای دسترسی سریع، برنامه را به صفحه اصلی گوشی اضافه کنید.", verbose_name="راهنمای نصب PWA") login_intro_enabled = models.BooleanField(default=True, verbose_name="نمایش بخش معرفی ورود") login_intro_icon = models.CharField(max_length=32, default="✦", blank=True, verbose_name="آیکون معرفی ورود") login_intro_eyebrow = models.CharField(max_length=200, default="ارتباط مستقیم با تیم فروش", verbose_name="بالانویس معرفی ورود") login_intro_heading = models.TextField(default="پاسخ روشن،\nپیگیری ساده.", verbose_name="عنوان معرفی ورود") login_intro_body = models.TextField( default="درخواست خود را ثبت کنید، فایل و پیام صوتی بفرستید و پاسخ کارشناس را در یک فضای امن دنبال کنید.", verbose_name="متن معرفی ورود", ) staff_login_intro_enabled = models.BooleanField(default=True, verbose_name="نمایش معرفی ورود کارشناسان") staff_login_intro_icon = models.CharField(max_length=32, default="◈", blank=True, verbose_name="آیکون معرفی ورود کارشناسان") staff_login_intro_eyebrow = models.CharField(max_length=200, default="پنل کارشناسان فروش", verbose_name="بالانویس ورود کارشناسان") staff_login_intro_heading = models.TextField(default="پاسخ‌های بهتر،\nفروش هوشمندتر.", verbose_name="عنوان ورود کارشناسان") staff_login_intro_body = models.TextField(default="صف درخواست‌ها، SLA، اولویت‌ها و سوابق مشتری را از یک میز کار متمرکز مدیریت کنید.", verbose_name="متن ورود کارشناسان") customer_tickets_hero_enabled = models.BooleanField(default=True, verbose_name="نمایش معرفی صفحه تیکت‌های مشتری") customer_tickets_hero_eyebrow = models.CharField(max_length=200, default="مرکز ارتباط با فروش", verbose_name="بالانویس صفحه تیکت‌های مشتری") customer_tickets_hero_heading = models.TextField(default="هر درخواست، یک مسیر روشن\nتا رسیدن به پاسخ.", verbose_name="عنوان صفحه تیکت‌های مشتری") customer_tickets_hero_body = models.TextField(default="موضوع جدیدی دارید؟ آن را جدا ثبت کنید تا تیم فروش دقیق‌تر و سریع‌تر پیگیری کند.", verbose_name="متن صفحه تیکت‌های مشتری") developer_credit_text = models.CharField( max_length=500, default="برنامه نویسی و توسعه: محمد جواد فصاحت | 09202202129", verbose_name="متن امضای توسعه‌دهنده", ) developer_credit_html = models.TextField( blank=True, verbose_name="HTML سفارشی امضای توسعه‌دهنده", help_text="فقط برای HTML مورد اعتماد؛ لینک، آیکون و style خطی مجاز است.", ) use_developer_credit_html = models.BooleanField( default=False, verbose_name="استفاده از HTML سفارشی", help_text="با فعال‌سازی، HTML بدون escape نمایش داده می‌شود؛ فقط مدیر ارشد باید آن را ویرایش کند.", ) staff_sidebar_credit_text = models.CharField( max_length=500, default="برنامه نویسی و توسعه: محمد جواد فصاحت", verbose_name="متن امضای پایین sidebar کارکنان", ) staff_sidebar_credit_html = models.TextField( blank=True, verbose_name="HTML سفارشی امضای sidebar کارکنان", help_text="مستقل از امضای عمومی؛ فقط برای HTML مورد اعتماد.", ) use_staff_sidebar_credit_html = models.BooleanField( default=False, verbose_name="استفاده از HTML سفارشی در sidebar", ) updated_at = models.DateTimeField(auto_now=True) class Meta: verbose_name = "تنظیمات عنوان و برند" verbose_name_plural = "تنظیمات عنوان و برند" def save(self, *args, **kwargs): self.pk = 1 return super().save(*args, **kwargs) @classmethod def load(cls): return cls.objects.filter(pk=1).first() or cls() def __str__(self): return self.site_title class PageTitle(models.Model): """Editable browser title for a named Django route.""" route_name = models.CharField(max_length=160, unique=True, help_text="مانند accounts:login") title = models.CharField(max_length=240) is_active = models.BooleanField(default=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ("route_name",) verbose_name = "عنوان صفحه" verbose_name_plural = "عنوان صفحات" def __str__(self): return f"{self.route_name}: {self.title}"