diff --git a/apps/hadis/views/hadis.py b/apps/hadis/views/hadis.py index fbb8a5f..290e52d 100644 --- a/apps/hadis/views/hadis.py +++ b/apps/hadis/views/hadis.py @@ -690,11 +690,13 @@ class CategoryHadisCorrectionsView(ListAPIView): @swagger_auto_schema( operation_summary="Get Category Hadis Corrections", - operation_description="Returns all text corrections across all hadiths belonging to a specific category, including hadis_info for each correction.", + operation_description="Returns all text corrections across all hadiths belonging to a specific category, including hadis_info for each correction. Supports filtering by multiple hadiths and/or categories.", tags=['Dobodbi - Hadis (V2)'], manual_parameters=[ openapi.Parameter('search', openapi.IN_QUERY, description="Search in text or narrator", type=openapi.TYPE_STRING), - openapi.Parameter('hadis_slug', openapi.IN_QUERY, description="Filter corrections by specific hadith slug", type=openapi.TYPE_STRING), + openapi.Parameter('hadis_slug', openapi.IN_QUERY, description="Filter corrections by specific hadith slug (comma-separated for multiple)", type=openapi.TYPE_STRING), + openapi.Parameter('hadis_slugs', openapi.IN_QUERY, description="Filter corrections by multiple hadith slugs (comma-separated)", type=openapi.TYPE_STRING), + openapi.Parameter('category_slugs', openapi.IN_QUERY, description="Filter corrections by multiple category slugs (comma-separated)", type=openapi.TYPE_STRING), openapi.Parameter('is_bookmark', openapi.IN_QUERY, description="Filter only bookmarked corrections (requires auth)", type=openapi.TYPE_BOOLEAN), ] ) @@ -704,12 +706,52 @@ class CategoryHadisCorrectionsView(ListAPIView): def get_queryset(self): category_slug = self.kwargs.get('category_slug') try: - category = HadisCategory.objects.get(slug=category_slug) - category_ids = category.get_descendants(include_self=True).values_list('id', flat=True) - hadis_ids = Hadis.objects.filter( - category_id__in=category_ids, - status=True - ).values_list('id', flat=True) + category_ids = [] + if category_slug: + category = HadisCategory.objects.get(slug=category_slug) + category_ids = list(category.get_descendants(include_self=True).values_list('id', flat=True)) + + # Optional filter by multiple categories (selected subcategories or category slugs/IDs) + cat_param_keys = ['category_slugs', 'categories', 'category_slug'] + cat_slug_list = [] + for key in cat_param_keys: + vals = self.request.query_params.getlist(key) if hasattr(self.request.query_params, 'getlist') else [] + if not vals and key in self.request.query_params: + val = self.request.query_params.get(key) + if val: + vals = [val] if isinstance(val, str) else list(val) + for v in vals: + if isinstance(v, str): + cat_slug_list.extend([s.strip() for s in v.split(',') if s.strip()]) + elif isinstance(v, (list, tuple)): + cat_slug_list.extend(v) + elif v is not None: + cat_slug_list.append(str(v)) + + if cat_slug_list: + cat_filter = Q(slug__in=cat_slug_list) + id_list = [int(s) for s in cat_slug_list if str(s).isdigit()] + if id_list: + cat_filter |= Q(id__in=id_list) + + selected_categories = HadisCategory.objects.filter(cat_filter) + selected_cat_ids = set() + for sc in selected_categories: + selected_cat_ids.update(sc.get_descendants(include_self=True).values_list('id', flat=True)) + + if selected_cat_ids: + if category_ids: + category_ids = list(set(category_ids).intersection(selected_cat_ids)) + else: + category_ids = list(selected_cat_ids) + else: + return HadisCorrection.objects.none() + + hadis_filter_kwargs = {'status': True} + if category_ids: + hadis_filter_kwargs['category_id__in'] = category_ids + + hadis_ids = Hadis.objects.filter(**hadis_filter_kwargs).values_list('id', flat=True) queryset = HadisCorrection.objects.filter( hadis_id__in=hadis_ids @@ -731,10 +773,30 @@ class CategoryHadisCorrectionsView(ListAPIView): ) queryset = queryset.filter(search_conditions) - # Optional filter by specific hadith slug within this category - hadis_slug = self.request.query_params.get('hadis_slug', None) - if hadis_slug: - queryset = queryset.filter(hadis__slug=hadis_slug) + # Optional filter by specific hadith slug(s) or ID(s) + hadis_param_keys = ['hadis_slug', 'hadis_slugs', 'hadiths'] + hadis_slug_list = [] + for key in hadis_param_keys: + vals = self.request.query_params.getlist(key) if hasattr(self.request.query_params, 'getlist') else [] + if not vals and key in self.request.query_params: + val = self.request.query_params.get(key) + if val: + vals = [val] if isinstance(val, str) else list(val) + for v in vals: + if isinstance(v, str): + hadis_slug_list.extend([s.strip() for s in v.split(',') if s.strip()]) + elif isinstance(v, (list, tuple)): + hadis_slug_list.extend(v) + elif v is not None: + hadis_slug_list.append(str(v)) + + if hadis_slug_list: + hadis_query = Q(hadis__slug__in=hadis_slug_list) + id_list = [int(s) for s in hadis_slug_list if str(s).isdigit()] + if id_list: + hadis_query |= Q(hadis__id__in=id_list) + + queryset = queryset.filter(hadis_query) # Filter by bookmarks if provided is_bookmark = self.request.query_params.get('is_bookmark', '').lower() @@ -754,15 +816,44 @@ class CategoryHadisCorrectionsView(ListAPIView): def list(self, request, *args, **kwargs): response = super().list(request, *args, **kwargs) category_slug = self.kwargs.get('category_slug') - category_obj = HadisCategory.objects.filter(slug=category_slug).first() + category_obj = HadisCategory.objects.filter(slug=category_slug).first() if category_slug else None category_data = SimpleCategory(category_obj, context={'request': request}).data if category_obj else None + available_hadiths = [] + available_categories = [] + if category_obj: + cat_ids = category_obj.get_descendants(include_self=True).values_list('id', flat=True) + hadiths_in_cat = Hadis.objects.filter( + category_id__in=cat_ids, + status=True + ).order_by('number', 'id') + + for h in hadiths_in_cat: + h_title = get_localized_text(h.title, request) if hasattr(h, 'title') and h.title else f"Hadith {h.number}" + available_hadiths.append({ + "id": h.id, + "number": h.number, + "slug": h.slug, + "title": h_title, + }) + + subcats = category_obj.get_children() if hasattr(category_obj, 'get_children') else category_obj.children.all() + for sc in subcats: + sc_title = get_localized_text(sc.title, request) if hasattr(sc, 'title') and sc.title else sc.slug + available_categories.append({ + "id": sc.id, + "slug": sc.slug, + "title": sc_title, + }) + if isinstance(response.data, dict): ordered_data = { 'count': response.data.get('count', 0), 'next': response.data.get('next'), 'previous': response.data.get('previous'), 'current_category': category_data, + 'available_hadiths': available_hadiths, + 'available_categories': available_categories, 'results': response.data.get('results', []), } response.data = ordered_data