"""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 employees.services.skill_progress import skill_queryset_with_rarity 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", Prefetch("skills", queryset=skill_queryset_with_rarity()), "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