from django.db import models from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError from mptt.models import MPTTModel, TreeForeignKey from django.utils.text import slugify from django.conf import settings from utils.mixins import LowercaseSlugMixin class HadisSect(models.Model): class SectType(models.TextChoices): SHIA = 'shia', _('Shia') SUNNI = 'sunni', _('Sunni') sect_type = models.CharField(max_length=10, choices=SectType.choices, unique=True, verbose_name=_('Sect Name')) title = models.JSONField(default = list , verbose_name=_('Title')) description = models.JSONField(default = list , verbose_name=_('Description')) is_active = models.BooleanField(default=True, verbose_name=_('Is Active')) order = models.IntegerField(default=0, verbose_name=_('order')) def __str__(self): title = self.title[0]['text'] if self.title else "Untitled Sect" return f"{self.sect_type}: {title}" def get_title(self,lang): """ Get title for a specific language """ if not self.title or not isinstance(self.title, list): return None for tr in self.title: if isinstance(tr, dict) and tr.get('language_code') == lang: return tr.get('text', '') for tr in self.title: if isinstance(tr, dict) and tr.get('language_code') == 'en': return tr.get('text', '') return None def get_description(self,lang): """ Get title for a specific language """ if not self.description or not isinstance(self.description, list): return None for tr in self.description: if isinstance(tr, dict) and tr.get('language_code') == lang: return tr.get('text', '') for tr in self.description: if isinstance(tr, dict) and tr.get('language_code') == 'en': return tr.get('text', '') return None class Meta: verbose_name = _('Hadis Sect') verbose_name_plural = _('Hadis Sects') ordering = ('order',) class HadisCategory(LowercaseSlugMixin, MPTTModel): class SourceType(models.TextChoices): QURAN = 'quran', _('Quran') HADITH = 'hadith', _('Hadith') HISTORY = 'history', _('History') FATWA = 'fatwa', _('Fatwa') QUOTE = 'quote', _('Quote') parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') sect = models.ForeignKey(HadisSect, on_delete=models.PROTECT, verbose_name=_('Sect'), null=False, blank=False) source_type = models.CharField(max_length=10, choices=SourceType.choices, verbose_name=_('Source Type')) title = models.JSONField(default = list , verbose_name=_('Title')) description = models.JSONField(default = list , verbose_name=_('Description')) order = models.IntegerField(default=0, verbose_name=_('order')) xmind_file = models.FileField(upload_to='hadis/xmind_files/', verbose_name=_('xmind file'), null=True, blank=True) slug = models.SlugField(max_length=255, null=True, blank=True,allow_unicode=True) content_type = None language = None language_id = None def clean(self): super().clean() if self.parent and self.sect_id != self.parent.sect_id: raise ValidationError( _('Child category must have the same sect_type as its parent. ' f'Parent sect: {self.parent.sect.sect_type}, ' f'Your sect: {self.sect.sect_type}') ) slug_source_field = 'title' def save(self, *args, **kwargs): self.full_clean() super().save(*args, **kwargs) @property def share_link(self): if self.slug: return f"{settings.DOVODI_DOMAIN}/arguments/category/{self.slug}" return None @property def xmind_share_link(self): if self.slug: return f"{settings.DOVODI_DOMAIN}/xmind/{self.slug}" return None class Meta: indexes = [ models.Index(fields=['parent', 'sect']), models.Index(fields=['sect', 'order']) ] verbose_name = _('Hadis Category') verbose_name_plural = _('Hadis Categories') ordering = ('order',) def __str__(self): title = self.title[0]['text'] if self.title else "Untitled Category" return f"{self.sect.sect_type}: {self.source_type} - {title}" def get_title(self,lang): """ Get title for a specific language """ if not self.title or not isinstance(self.title, list): return None for tr in self.title: if isinstance(tr, dict) and tr.get('language_code') == lang: return tr.get('text', '') for tr in self.title: if isinstance(tr, dict) and tr.get('language_code') == 'en': return tr.get('text', '') return None def get_description(self,lang): """ Get title for a specific language """ if not self.description or not isinstance(self.description, list): return None for tr in self.description: if isinstance(tr, dict) and tr.get('language_code') == lang: return tr.get('text', '') for tr in self.description: if isinstance(tr, dict) and tr.get('language_code') == 'en': return tr.get('text', '') return None class CategoryQuranVerse(models.Model): """ Model to store Quranic verse details for a HadisCategory when its source_type is 'quran'. """ category = models.OneToOneField( HadisCategory, on_delete=models.CASCADE, related_name='quran_verse', verbose_name=_('Category') ) surah_name = models.JSONField(default=list, verbose_name=_('Surah Name')) # برای پشتیبانی از رِنج آیات (مثل 12-15) از CharField استفاده می‌کنیم ayah_number = models.CharField(max_length=50, verbose_name=_('Ayah Number')) arabic_text = models.TextField(verbose_name=_('Arabic Text')) translation = models.JSONField(default=list, verbose_name=_('Primary Translation')) translator = models.JSONField(default=list, verbose_name=_('Primary Translator')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('Created At')) updated_at = models.DateTimeField(auto_now=True, verbose_name=_('Updated At')) class Meta: verbose_name = _('Category Quran Verse') verbose_name_plural = _('Category Quran Verses') def __str__(self): # تلاش برای استخراج اسم سوره جهت نمایش در ادمین پنل try: surah = self.surah_name[0]['text'] if self.surah_name else "Unknown Surah" except (IndexError, KeyError, TypeError): surah = "Unknown Surah" return f"{self.category} -> {surah} : {self.ayah_number}" class QuranSecondaryTranslation(models.Model): """ Model to store multiple secondary translations for a Quran verse. """ quran_verse = models.ForeignKey( CategoryQuranVerse, on_delete=models.CASCADE, related_name='secondary_translations', verbose_name=_('Quran Verse') ) translation_text = models.JSONField(default=list, verbose_name=_('Translation Text')) translator = models.JSONField(default=list, verbose_name=_('Translator Name')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('Created At')) updated_at = models.DateTimeField(auto_now=True, verbose_name=_('Updated At')) class Meta: verbose_name = _('Quran Secondary Translation') verbose_name_plural = _('Quran Secondary Translations') ordering = ['id'] def __str__(self): try: translator_name = self.translator[0]['text'] if self.translator else "Unknown Translator" except (IndexError, KeyError, TypeError): translator_name = "Unknown Translator" return f"Translation by {translator_name}"