|
|
|
@ -136,6 +136,18 @@ class HadisCategoryTreeView(ListAPIView): |
|
|
|
for root in roots: |
|
|
|
sect_type = root.sect.sect_type |
|
|
|
|
|
|
|
# Build tree using mapping (returns None if the root branch is completely empty) |
|
|
|
category_data = self._build_tree_recursive( |
|
|
|
root, |
|
|
|
request, |
|
|
|
children_map, |
|
|
|
recursive_counts, |
|
|
|
hadis_ids_map, |
|
|
|
quran_data_map, |
|
|
|
) |
|
|
|
if category_data is None: |
|
|
|
continue |
|
|
|
|
|
|
|
if sect_type not in grouped_data: |
|
|
|
grouped_data[sect_type] = { |
|
|
|
'sects': {}, |
|
|
|
@ -158,15 +170,6 @@ class HadisCategoryTreeView(ListAPIView): |
|
|
|
'source_types': list(source_types) |
|
|
|
} |
|
|
|
|
|
|
|
# Build tree using mapping |
|
|
|
category_data = self._build_tree_recursive( |
|
|
|
root, |
|
|
|
request, |
|
|
|
children_map, |
|
|
|
recursive_counts, |
|
|
|
hadis_ids_map, |
|
|
|
quran_data_map, # 👇 پاس دادن مپِ قرآن به تابع بازگشتی |
|
|
|
) |
|
|
|
grouped_data[sect_type]['categories'].append(category_data) |
|
|
|
|
|
|
|
total_count = len(queryset) |
|
|
|
@ -180,10 +183,28 @@ class HadisCategoryTreeView(ListAPIView): |
|
|
|
|
|
|
|
def _build_tree_recursive(self, category, request, children_map, recursive_counts, hadis_ids_map, quran_data_map): |
|
|
|
""" |
|
|
|
Build tree from flat mapping |
|
|
|
Build tree from flat mapping, pruning any node that has no active children and no active hadiths. |
|
|
|
""" |
|
|
|
children = children_map.get(category.id, []) |
|
|
|
raw_children = children_map.get(category.id, []) |
|
|
|
built_children = [] |
|
|
|
for child in raw_children: |
|
|
|
child_node = self._build_tree_recursive( |
|
|
|
child, |
|
|
|
request, |
|
|
|
children_map, |
|
|
|
recursive_counts, |
|
|
|
hadis_ids_map, |
|
|
|
quran_data_map, |
|
|
|
) |
|
|
|
if child_node is not None: |
|
|
|
built_children.append(child_node) |
|
|
|
|
|
|
|
has_hadis = category.direct_hadis_count > 0 |
|
|
|
has_quran = bool(quran_data_map.get(category.id, None)) if category.source_type == HadisCategory.SourceType.QURAN else False |
|
|
|
|
|
|
|
# If this category has no children and no hadiths (and no quran verse), prune it |
|
|
|
if len(built_children) == 0 and not has_hadis and not has_quran: |
|
|
|
return None |
|
|
|
|
|
|
|
return { |
|
|
|
'id': category.id, |
|
|
|
@ -198,23 +219,12 @@ class HadisCategoryTreeView(ListAPIView): |
|
|
|
'has_hadis': has_hadis, |
|
|
|
'has_parent': category.parent_id is not None, |
|
|
|
'hadis_ids': hadis_ids_map.get(category.id, []) if has_hadis else [], |
|
|
|
# 👇 کلید جدید: تزریق دیتای قرآن دقیقاً داخل نودِ کتگوری |
|
|
|
'quran_data': quran_data_map.get(category.id, None) if category.source_type == HadisCategory.SourceType.QURAN else None, |
|
|
|
'order': category.order, |
|
|
|
'thumbnail': self._get_thumbnail_url(category, request), |
|
|
|
'xmind_file': self._get_xmind_url(category, request), |
|
|
|
'has_xmind_file': bool(getattr(category, 'xmind_file', None)), |
|
|
|
'children': [ |
|
|
|
self._build_tree_recursive( |
|
|
|
child, |
|
|
|
request, |
|
|
|
children_map, |
|
|
|
recursive_counts, |
|
|
|
hadis_ids_map, |
|
|
|
quran_data_map, # 👇 |
|
|
|
) |
|
|
|
for child in children |
|
|
|
] |
|
|
|
'children': built_children |
|
|
|
} |
|
|
|
|
|
|
|
def _get_thumbnail_url(self, category, request): |
|
|
|
@ -244,9 +254,15 @@ class HadisCategoryTreeNormalView(ListAPIView): |
|
|
|
return self.list(request, *args, **kwargs) |
|
|
|
|
|
|
|
def get_queryset(self): |
|
|
|
from django.db.models import Count, Q |
|
|
|
return HadisCategory.objects.filter( |
|
|
|
parent__isnull=True, |
|
|
|
sect__is_active=True |
|
|
|
).annotate( |
|
|
|
active_hadis_count=Count('hadis', filter=Q(hadis__status=True)), |
|
|
|
children_total_count=Count('children') |
|
|
|
).filter( |
|
|
|
Q(active_hadis_count__gt=0) | Q(children_total_count__gt=0) | Q(source_type=HadisCategory.SourceType.QURAN) |
|
|
|
).order_by('sect__order', 'order') |
|
|
|
|
|
|
|
|
|
|
|
@ -293,8 +309,6 @@ class HadisCategorySelectBySectView(ListAPIView): |
|
|
|
def get_queryset(self): |
|
|
|
sect_type = self.kwargs.get('sect_type') |
|
|
|
slug = self.kwargs.get('slug') |
|
|
|
print(slug) |
|
|
|
print(sect_type) |
|
|
|
|
|
|
|
# Find the parent category by slug and sect_type |
|
|
|
try: |
|
|
|
@ -304,14 +318,19 @@ class HadisCategorySelectBySectView(ListAPIView): |
|
|
|
sect__is_active=True |
|
|
|
) |
|
|
|
except HadisCategory.DoesNotExist: |
|
|
|
print('not ok') |
|
|
|
return HadisCategory.objects.none() |
|
|
|
|
|
|
|
# Return children of this category, filtered as before |
|
|
|
from django.db.models import Count, Q |
|
|
|
# Return children of this category that have either active hadiths, children, or are quran |
|
|
|
return HadisCategory.objects.filter( |
|
|
|
parent=parent_category, |
|
|
|
sect__sect_type=sect_type, |
|
|
|
sect__is_active=True |
|
|
|
).annotate( |
|
|
|
active_hadis_count=Count('hadis', filter=Q(hadis__status=True)), |
|
|
|
children_total_count=Count('children') |
|
|
|
).filter( |
|
|
|
Q(active_hadis_count__gt=0) | Q(children_total_count__gt=0) | Q(source_type=HadisCategory.SourceType.QURAN) |
|
|
|
).order_by('order') |
|
|
|
|
|
|
|
|
|
|
|
@ -369,39 +388,61 @@ class HadisCategorySelectBySectSourceView(ListAPIView): |
|
|
|
except HadisCategory.DoesNotExist: |
|
|
|
return HadisCategory.objects.none() |
|
|
|
|
|
|
|
# Return children of this category, filtered by source_type |
|
|
|
from django.db.models import Count, Q |
|
|
|
# Return children of this category, filtered by source_type and excluding empty leaves |
|
|
|
return HadisCategory.objects.filter( |
|
|
|
parent=parent_category, |
|
|
|
sect__sect_type=sect_type, |
|
|
|
sect__is_active=True, |
|
|
|
source_type=source_type |
|
|
|
).annotate( |
|
|
|
active_hadis_count=Count('hadis', filter=Q(hadis__status=True)), |
|
|
|
children_total_count=Count('children') |
|
|
|
).filter( |
|
|
|
Q(active_hadis_count__gt=0) | Q(children_total_count__gt=0) | Q(source_type=HadisCategory.SourceType.QURAN) |
|
|
|
).order_by('order') |
|
|
|
|
|
|
|
class CategoriesView(ListAPIView): |
|
|
|
""" |
|
|
|
API view to list all HadisCategories |
|
|
|
API view to list all HadisCategories (excluding empty leaf categories) |
|
|
|
""" |
|
|
|
queryset = HadisCategory.objects.all() |
|
|
|
serializer_class = CategorySerializer |
|
|
|
pagination_class = StandardResultsSetPagination |
|
|
|
@categories_list_swagger |
|
|
|
def get(self, request, *args, **kwargs): |
|
|
|
return self.list(request, *args, **kwargs) |
|
|
|
|
|
|
|
def get_queryset(self): |
|
|
|
from django.db.models import Count, Q |
|
|
|
return HadisCategory.objects.filter( |
|
|
|
sect__is_active=True |
|
|
|
).annotate( |
|
|
|
active_hadis_count=Count('hadis', filter=Q(hadis__status=True)), |
|
|
|
children_total_count=Count('children') |
|
|
|
).filter( |
|
|
|
Q(active_hadis_count__gt=0) | Q(children_total_count__gt=0) | Q(source_type=HadisCategory.SourceType.QURAN) |
|
|
|
).order_by('order', 'id') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CategoriesBySectView(ListAPIView): |
|
|
|
""" |
|
|
|
API view to list HadisCategories filtered by sect_type |
|
|
|
API view to list HadisCategories filtered by sect_type (excluding empty leaf categories) |
|
|
|
""" |
|
|
|
serializer_class = CategorySerializer |
|
|
|
pagination_class = StandardResultsSetPagination |
|
|
|
|
|
|
|
def get_queryset(self): |
|
|
|
sect_type = self.kwargs.get('sect_type') |
|
|
|
from django.db.models import Count, Q |
|
|
|
queryset = HadisCategory.objects.filter( |
|
|
|
sect__sect_type=sect_type, |
|
|
|
sect__is_active=True |
|
|
|
).annotate( |
|
|
|
active_hadis_count=Count('hadis', filter=Q(hadis__status=True)), |
|
|
|
children_total_count=Count('children') |
|
|
|
).filter( |
|
|
|
Q(active_hadis_count__gt=0) | Q(children_total_count__gt=0) | Q(source_type=HadisCategory.SourceType.QURAN) |
|
|
|
) |
|
|
|
is_root = self.request.query_params.get('is_root', 'true').lower() |
|
|
|
if is_root in ['true', '1']: |
|
|
|
|