from django.db import models from django.db.models import F, ForeignKey from django.utils.translation import gettext_lazy as _ from django.conf import settings from django.utils.text import slugify from filer.fields.image import FilerImageField from .reference import BookReference class HadisCollection(models.Model): title = models.CharField(max_length=255, verbose_name=_('title')) slug = models.SlugField(max_length=255, unique=True, verbose_name=_('slug'), blank=True) summary = models.TextField(verbose_name=_('summary'), null=True, blank=True) status = models.BooleanField(default=True, verbose_name=_('status')) order = models.IntegerField(default=0, verbose_name=_('order')) thumbnail = FilerImageField( related_name="+", on_delete=models.CASCADE, help_text=_('thumbnail image'), null=True, blank=True, verbose_name=_('thumbnail') ) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) updated_at = models.DateTimeField(auto_now=True, verbose_name=_('updated at')) def save(self, *args, **kwargs): if not self.slug: base_slug = slugify(self.title, allow_unicode=True) slug = base_slug counter = 1 while HadisCollection.objects.filter(slug=slug).exclude(pk=self.pk).exists(): slug = f"{base_slug}-{counter}" counter += 1 self.slug = slug super().save(*args, **kwargs) def __str__(self): return self.title class Meta: verbose_name = _('hadis collection') verbose_name_plural = _('hadis collections') ordering = ('order',) class HadisInCollection(models.Model): hadis = models.ForeignKey('Hadis', on_delete=models.CASCADE, verbose_name=_('hadis'), related_name='collection_items') collection = models.ForeignKey(HadisCollection, on_delete=models.CASCADE, verbose_name=_('collection'), related_name='hadis_items') order = models.IntegerField(default=0, verbose_name=_('order')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) class Meta: verbose_name = _('hadis in collection') verbose_name_plural = _('hadis in collections') ordering = ('order',) unique_together = ('hadis', 'collection') def __str__(self): return f"{self.collection.title} - {self.hadis.number}" class HadisTag(models.Model): title = models.CharField(max_length=355, verbose_name=_('title')) status = models.BooleanField(default=True, verbose_name=_('status')) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) updated_at = models.DateTimeField(auto_now=True, verbose_name=_('updated at')) def __str__(self): return f"{self.title}" class HadisStatus(models.Model): class ColorChoices(models.TextChoices): RED = 'red', _('Red') GREEN = 'green', _('Green') BLUE = 'blue', _('Blue') YELLOW = 'yellow', _('Yellow') ORANGE = 'orange', _('Orange') PURPLE = 'purple', _('Purple') GRAY = 'gray', _('Gray') title = models.CharField(max_length=119, verbose_name=_('title')) color = models.CharField(max_length=20, choices=ColorChoices.choices, verbose_name=_('color')) order = models.IntegerField(default=0, verbose_name=_('order')) def __str__(self): return self.title class Meta: verbose_name = _('hadis status') verbose_name_plural = _('hadis statuses') ordering = ('order',) class Hadis(models.Model): category = models.ForeignKey("hadis.HadisCategory", on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('category')) number = models.PositiveIntegerField(verbose_name=_('number'), default=1) title_narrator = models.CharField(max_length=255, verbose_name=_('title narrator'), null=True, blank=True) title = models.CharField(max_length=255, verbose_name=_('title'), null=True, blank=True) description = models.TextField(verbose_name=_('description'), blank=True, null=True) text = models.TextField(verbose_name=_('text')) translation = models.JSONField(verbose_name=_('translation'), default=list) status = models.BooleanField(default=True, verbose_name=_('visibility')) hadis_status = models.ForeignKey(HadisStatus, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('hadis status')) hadis_status_text = models.CharField(max_length=255, verbose_name=_('hadis status text'), null=True, blank=True) address = models.TextField(verbose_name=_('address'), null=True, blank=True) links = models.JSONField(verbose_name=_('links'), null=True, blank=True, default=dict) tags = models.ManyToManyField("HadisTag", related_name="hadis_overview", verbose_name=_('tags'), blank=True) share_link = models.CharField(max_length=255, verbose_name=_('share link'), null=True, blank=True) explanation = models.TextField(verbose_name=_('explanation'), null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) updated_at = models.DateTimeField(auto_now=True, verbose_name=_('updated at')) def __str__(self): return f"{self.number} - {self.title}" if self.title else f"Hadis {self.number}" def get_translation(self, lang): """ Get translation for a specific language """ if not self.translation or not isinstance(self.translation, list): return None for tr in self.translation: if isinstance(tr, dict) and tr.get('language_code') == lang: return tr.get('title', '') for tr in self.translation: if isinstance(tr, dict) and tr.get('language_code') == 'en': return tr.get('title', '') return None def save(self, *args, **kwargs): # ساخت share_link قبل از ذخیره if not self.share_link: self.share_link = f"{settings.SITE_DOMAIN}/hadis/{self.id}" super().save(*args, **kwargs) class Meta: verbose_name = _('hadis') verbose_name_plural = _('hadises') ordering = ('category', 'number') class HadisReference(models.Model): hadis = models.ForeignKey( Hadis, on_delete=models.CASCADE, verbose_name=_('hadis'), related_name='references' ) book_reference = models.ForeignKey( BookReference, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('book reference'), related_name='hadis_references' ) created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('created at')) description = models.TextField(verbose_name=_('description'), null=True, blank=True) class Meta: verbose_name = _('Hadis Reference') verbose_name_plural = _('Hadis References') # unique_together = ('hadis', 'book_reference') def __str__(self): return f'{self.hadis.number}-{self.book_reference.title if self.book_reference else "No Book Reference"}' class ReferenceImage(models.Model): reference = models.ForeignKey(HadisReference, verbose_name="Hadis Reference", on_delete=models.CASCADE) thumbnail = models.ImageField(upload_to='hadis/reference_images/', null=True, blank=True, verbose_name=_('thumbnail')) priority = models.IntegerField( default=0, verbose_name=_("Priority"), help_text=_("Priority of the image, lower values mean higher priority.") ) class Meta: verbose_name = _('Reference Image') verbose_name_plural = _('Reference Images') def __str__(self): return f'{self.reference.title}-{self.id}' def save(self, *args, **kwargs): if ReferenceImage.objects.filter(reference=self.reference, priority=self.priority).exists(): ReferenceImage.objects.filter( reference=self.reference, priority__gte=self.priority ).update(priority=F('priority') + 1) super().save(*args, **kwargs) class HadisCorrection(models.Model): hadis = models.ForeignKey(Hadis, verbose_name=_("hadis correction"), on_delete=models.CASCADE) title = models.CharField(max_length=255, verbose_name=_("title")) description = models.TextField(verbose_name=_("description"), blank=True, null=True) translation = models.JSONField(verbose_name=_("translation"), default=list) 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 = _("Hadis Correction") verbose_name_plural = _("Hadis Corrections") ordering = ("-created_at",) def __str__(self): return f"{self.hadis.number} - {self.title}"