diff --git a/taiga/projects/epics/serializers.py b/taiga/projects/epics/serializers.py index 4118553e..081245d9 100644 --- a/taiga/projects/epics/serializers.py +++ b/taiga/projects/epics/serializers.py @@ -49,10 +49,15 @@ class EpicListSerializer(VoteResourceSerializerMixin, WatchedResourceSerializer, blocked_note = Field() tags = Field() is_closed = MethodField() + user_stories_counts = MethodField() def get_is_closed(self, obj): return obj.status is not None and obj.status.is_closed + def get_user_stories_counts(self, obj): + assert hasattr(obj, "user_stories_counts"), "instance must have a user_stories_counts attribute" + return obj.user_stories_counts + class EpicSerializer(EpicListSerializer): comment = MethodField() diff --git a/taiga/projects/epics/utils.py b/taiga/projects/epics/utils.py index d10dddab..20f45046 100644 --- a/taiga/projects/epics/utils.py +++ b/taiga/projects/epics/utils.py @@ -26,14 +26,29 @@ from taiga.projects.votes.utils import attach_is_voter_to_queryset def attach_extra_info(queryset, user=None, include_attachments=False): - if include_attachments: queryset = attach_basic_attachments(queryset) queryset = queryset.extra(select={"include_attachments": "True"}) + queryset = attach_user_stories_counts_to_queryset(queryset) queryset = attach_total_voters_to_queryset(queryset) queryset = attach_watchers_to_queryset(queryset) queryset = attach_total_watchers_to_queryset(queryset) queryset = attach_is_voter_to_queryset(queryset, user) queryset = attach_is_watcher_to_queryset(queryset, user) return queryset + + +def attach_user_stories_counts_to_queryset(queryset, as_field="user_stories_counts"): + model = queryset.model + sql = """SELECT json_build_object( + 'opened', COALESCE(SUM(CASE WHEN is_closed IS FALSE THEN 1 ELSE 0 END), 0), + 'closed', COALESCE(SUM(CASE WHEN is_closed IS TRUE THEN 1 ELSE 0 END), 0) + ) + FROM epics_relateduserstory + INNER JOIN userstories_userstory ON epics_relateduserstory.user_story_id = userstories_userstory.id + WHERE epics_relateduserstory.epic_id = {tbl}.id""" + + sql = sql.format(tbl=model._meta.db_table) + queryset = queryset.extra(select={as_field: sql}) + return queryset diff --git a/taiga/projects/management/commands/sample_data.py b/taiga/projects/management/commands/sample_data.py index 00103c6e..54b4e027 100644 --- a/taiga/projects/management/commands/sample_data.py +++ b/taiga/projects/management/commands/sample_data.py @@ -111,7 +111,7 @@ NUM_EMPTY_PROJECTS = getattr(settings, "SAMPLE_DATA_NUM_EMPTY_PROJECTS", 2) NUM_BLOCKED_PROJECTS = getattr(settings, "SAMPLE_DATA_NUM_BLOCKED_PROJECTS", 1) NUM_MILESTONES = getattr(settings, "SAMPLE_DATA_NUM_MILESTONES", (1, 5)) NUM_EPICS = getattr(settings, "SAMPLE_DATA_NUM_EPICS", (4, 8)) -NUM_USS_EPICS = getattr(settings, "SAMPLE_DATA_NUM_USS_EPICS", (2, 6)) +NUM_USS_EPICS = getattr(settings, "SAMPLE_DATA_NUM_USS_EPICS", (2, 12)) NUM_USS = getattr(settings, "SAMPLE_DATA_NUM_USS", (3, 7)) NUM_TASKS_FINISHED = getattr(settings, "SAMPLE_DATA_NUM_TASKS_FINISHED", (1, 5)) NUM_TASKS = getattr(settings, "SAMPLE_DATA_NUM_TASKS", (0, 4)) @@ -553,7 +553,7 @@ class Command(BaseCommand): if self.sd.choice([True, True, False, True, True]): filters = {"project": epic.project} n = self.sd.choice(list(range(self.sd.int(*NUM_USS_EPICS)))) - + print (n) user_stories = UserStory.objects.filter(**filters).order_by("?")[:n] for idx, us in enumerate(list(user_stories)): RelatedUserStory.objects.create(epic=epic,