"""Read model for the task REST collection and detail endpoints.""" from django.contrib.contenttypes.models import ContentType from django.db.models import Count, IntegerField, OuterRef, Prefetch, Q, Subquery, Value from django.db.models.functions import Coalesce from communications.models import Message from tasks.access import task_board_access_q from tasks.models import ( Task, TaskAttachment, TaskBoard, TaskLinkedObjectKind, ) def task_api_queryset(*, user, params): task_content_type = ContentType.objects.get_for_model(Task) comments_subquery = ( Message.objects.filter( chat__type="comments", chat__context_content_type=task_content_type, chat__context_object_id=OuterRef("pk"), is_deleted=False, ) .values("chat") .annotate(count=Count("id")) .values("count") ) queryset = ( Task.objects.filter(board__is_archived=False) .filter(board__in=TaskBoard.objects.filter(task_board_access_q(user))) .select_related( "board", "column", "row", "created_by", "assignee", "cover", "cover__attachment", "cover__attachment__uploaded_by", "cover__comment", "cover__comment__author", "cover__external_link", "cover__external_link__created_by", "cover__linked_object", "cover__linked_object__content_type", ) .prefetch_related( "labels", "participants", "checklist_items", Prefetch( "cover__comment__task_attachments", queryset=TaskAttachment.objects.select_related("uploaded_by"), ), ) .annotate( linked_posts_count=Count( "linked_objects", filter=Q(linked_objects__kind=TaskLinkedObjectKind.POST), distinct=True, ), linked_messages_count=Count( "linked_objects", filter=Q(linked_objects__kind=TaskLinkedObjectKind.MESSAGE), distinct=True, ), linked_events_count=Count( "linked_objects", filter=Q(linked_objects__kind=TaskLinkedObjectKind.CALENDAR_EVENT), distinct=True, ), linked_documents_count=Count( "linked_objects", filter=Q( linked_objects__kind=TaskLinkedObjectKind.DOCUMENT, ), distinct=True, ), linked_requests_count=Count( "linked_objects", filter=Q( linked_objects__kind=TaskLinkedObjectKind.REQUEST, ), distinct=True, ), linked_procurement_requests_count=Count( "linked_objects", filter=Q( linked_objects__kind=(TaskLinkedObjectKind.PROCUREMENT_REQUEST), ), distinct=True, ), linked_employees_count=Count( "linked_objects", filter=Q( linked_objects__kind=TaskLinkedObjectKind.EMPLOYEE, ), distinct=True, ), linked_guests_count=Count( "linked_objects", filter=Q( linked_objects__kind=TaskLinkedObjectKind.GUEST, ), distinct=True, ), linked_guest_visits_count=Count( "linked_objects", filter=Q( linked_objects__kind=TaskLinkedObjectKind.GUEST_VISIT, ), distinct=True, ), linked_attendance_records_count=Count( "linked_objects", filter=Q( linked_objects__kind=(TaskLinkedObjectKind.ATTENDANCE_RECORD), ), distinct=True, ), linked_objects_count=( Count("linked_objects", distinct=True) + Count("external_links", distinct=True) ), comments_count=Coalesce( Subquery(comments_subquery, output_field=IntegerField()), Value(0), ), attachments_count=Count("attachments", distinct=True), checklist_total=Count("checklist_items", distinct=True), checklist_completed=Count( "checklist_items", filter=Q(checklist_items__is_completed=True), distinct=True, ), ) ) if board := params.get("board"): queryset = queryset.filter(board_id=board) if column := params.get("column"): queryset = queryset.filter(column_id=column) if row := params.get("row"): queryset = queryset.filter(row_id=row) if assignee := params.get("assignee"): queryset = queryset.filter(assignee_id=assignee) if priority := params.get("priority"): queryset = queryset.filter(priority=priority) if params.get("unassigned") == "true": queryset = queryset.filter(assignee__isnull=True) return queryset