From eae1c27b764a0d85a24b0f6c65fabc77605733fa Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 24 Jan 2025 18:24:16 +0100 Subject: [PATCH 1/4] Calculate statistics about participations with lesson events --- aleksis/apps/alsijil/model_extensions.py | 12 +++--------- aleksis/apps/alsijil/tasks.py | 8 ++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/aleksis/apps/alsijil/model_extensions.py b/aleksis/apps/alsijil/model_extensions.py index a3d9c14fa..e1a2bd0ef 100644 --- a/aleksis/apps/alsijil/model_extensions.py +++ b/aleksis/apps/alsijil/model_extensions.py @@ -2,6 +2,7 @@ from django.db.models import FilteredRelation, Q, QuerySet, Value from django.db.models.aggregates import Count, Sum from django.utils.translation import gettext as _ +from aleksis.apps.chronos.models import LessonEvent from aleksis.apps.kolego.models import AbsenceReason from aleksis.core.models import Group, Person, SchoolTerm @@ -137,13 +138,6 @@ def annotate_person_statistics_for_school_term( datetime_end__date__lte=school_term.date_end, ) if group: - documentations = documentations.filter( - pk__in=Documentation.objects.filter(course__groups=group) - .values_list("pk", flat=True) - .union( - Documentation.objects.filter(course__groups__parent_groups=group).values_list( - "pk", flat=True - ) - ) - ) + lesson_events = LessonEvent.objects.filter(LessonEvent.objects.for_group_q(group)) + documentations = documentations.filter(amends__in=lesson_events) return annotate_person_statistics_from_documentations(persons, documentations) diff --git a/aleksis/apps/alsijil/tasks.py b/aleksis/apps/alsijil/tasks.py index 5c0377d74..71de0d315 100644 --- a/aleksis/apps/alsijil/tasks.py +++ b/aleksis/apps/alsijil/tasks.py @@ -7,6 +7,7 @@ from django.utils.translation import gettext as _ from celery.result import allow_join_result from celery.states import SUCCESS +from aleksis.apps.chronos.models import LessonEvent from aleksis.apps.cursus.models import Course from aleksis.apps.kolego.models.absence import AbsenceReason from aleksis.core.models import Group, PDFFile @@ -118,6 +119,13 @@ def generate_full_register_printout( course__groups__parent_groups=group ).values_list("pk", flat=True) ) + .union( + Documentation.objects.filter( + amends__in=LessonEvent.objects.filter( + LessonEvent.objects.for_group_q(group) + ) + ).values_list("pk", flat=True) + ) ) ) -- GitLab From 40967ac94f86967b7c86afc7e911313b026b41e2 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 24 Jan 2025 18:25:23 +0100 Subject: [PATCH 2/4] Add indicator for not counted absences --- .../coursebook/statistics/StatisticsForPersonPage.vue | 8 ++++++++ .../components/coursebook/statistics/statistics.graphql | 1 + aleksis/apps/alsijil/frontend/messages/de.json | 3 ++- aleksis/apps/alsijil/frontend/messages/en.json | 3 ++- aleksis/apps/alsijil/schema/documentation.py | 6 ++++++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue index dc8ae7867..c9c8bcd3c 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue @@ -179,6 +179,14 @@ <v-list-item-action class="flex-row full-width justify-md-end ma-0 align-center fill-height" > + <v-chip + color="warning" + class="mx-1" + v-if="!item.relatedDocumentation.amended" + >{{ + $t("alsijil.coursebook.statistics.not_counted") + }}</v-chip + > <!-- chips: absences & extraMarks --> <absence-reason-chip v-if="item.absenceReason" diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql index 1cffdc717..a83e3fa59 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql +++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql @@ -64,6 +64,7 @@ query participationsOfPerson($person: ID!) { colourFg colourBg } + amended } canEdit canDelete diff --git a/aleksis/apps/alsijil/frontend/messages/de.json b/aleksis/apps/alsijil/frontend/messages/de.json index 4d134acfe..b1650ed2b 100644 --- a/aleksis/apps/alsijil/frontend/messages/de.json +++ b/aleksis/apps/alsijil/frontend/messages/de.json @@ -82,7 +82,8 @@ "title": "Kursbuch · Statistiken · {fullName}" }, "person_view_details": "Details", - "title_plural": "Statistiken" + "title_plural": "Statistiken", + "not_counted": "nicht gezählt" }, "status": { "available": "Kursbucheintrag vorhanden", diff --git a/aleksis/apps/alsijil/frontend/messages/en.json b/aleksis/apps/alsijil/frontend/messages/en.json index a40f8d547..99ce86919 100644 --- a/aleksis/apps/alsijil/frontend/messages/en.json +++ b/aleksis/apps/alsijil/frontend/messages/en.json @@ -85,7 +85,8 @@ "summary": "Summary" }, "person_view_details": "Details", - "title_plural": "Statistics" + "title_plural": "Statistics", + "not_counted": "not counted" }, "notes": { "show_list": "List of participants", diff --git a/aleksis/apps/alsijil/schema/documentation.py b/aleksis/apps/alsijil/schema/documentation.py index ad88b2de3..9548581a6 100644 --- a/aleksis/apps/alsijil/schema/documentation.py +++ b/aleksis/apps/alsijil/schema/documentation.py @@ -48,6 +48,7 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp course = graphene.Field(CourseType, required=False) amends = graphene.Field(lambda: LessonEventType, required=False) + amended = graphene.Boolean(required=False) subject = graphene.Field(SubjectType, required=False) participations = graphene.List(ParticipationStatusType, required=False) @@ -66,6 +67,11 @@ class DocumentationType(PermissionsTypeMixin, DjangoFilterMixin, DjangoObjectTyp return root._amends_prefetched return root.amends + @staticmethod + @bypass_get_queryset + def resolve_amended(root: Documentation, info, **kwargs): + return root.amends_id is not None + @staticmethod @bypass_get_queryset def resolve_teachers(root: Documentation, info, **kwargs): -- GitLab From d43b44bd75d97a293bbc4b876fc92c0804475744 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 24 Jan 2025 18:25:45 +0100 Subject: [PATCH 3/4] Fix query --- .../frontend/components/extra_marks/ExtraMarkButtons.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue index 01deef401..8a8485bcc 100644 --- a/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue +++ b/aleksis/apps/alsijil/frontend/components/extra_marks/ExtraMarkButtons.vue @@ -1,5 +1,5 @@ <script> -import { extraMarks } from "./extra_marks.graphql"; +import { extraMarksList } from "./extra_marks.graphql"; export default { name: "ExtraMarkButtons", @@ -10,7 +10,7 @@ export default { }, apollo: { extraMarks: { - query: extraMarks, + query: extraMarksList, update: (data) => data.items, skip() { return this.customExtraMarks.length > 0; -- GitLab From 7faa1dfbe012c141e6506ddf7ba6a36abe6db412 Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Fri, 24 Jan 2025 18:25:53 +0100 Subject: [PATCH 4/4] Add print button to coursebook group tab --- .../coursebook/CoursebookPrintDialog.vue | 17 +++++++++++++++-- .../statistics/StatisticsForGroupTab.vue | 9 +++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookPrintDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookPrintDialog.vue index 976dccbeb..8a9058d6d 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookPrintDialog.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookPrintDialog.vue @@ -20,9 +20,10 @@ import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.v {{ $t("alsijil.coursebook.print.title") }} </template> <template #content> - {{ $t("alsijil.coursebook.print.groups") }} <v-autocomplete + v-if="!group" :items="availableGroups" + :label="$t('alsijil.coursebook.print.groups')" item-text="name" item-value="id" :value="value" @@ -87,7 +88,16 @@ export default { */ availableGroups: { type: Array, - required: true, + required: false, + default: () => [], + }, + /** + * Set a group to use this dialog exclusively for + */ + group: { + type: Object, + required: false, + default: null, }, /** * Initially selected groups @@ -121,6 +131,9 @@ export default { }, computed: { selectedGroups() { + if (this.group) { + return [this.group.id]; + } if (this.currentGroupSelection.length == 0) { return this.value.map((group) => group.id); } else { diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue index 95d377ac6..1575348b9 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue @@ -10,6 +10,9 @@ :show-select="false" @items="items = $event" > + <template #additionalActions> + <coursebook-print-dialog :group="group" /> + </template> <template v-for="(extraMark, index) in extraMarks" #[`extraMarks.${index}.count`]="{ item }" @@ -67,7 +70,7 @@ :to="{ name: 'core.personById', params: { - personId: item.person.id, + id: item.person.id, }, hash: '#' + MODE.PARTICIPATIONS, }" @@ -81,13 +84,14 @@ import groupOverviewTabMixin from "aleksis.core/mixins/groupOverviewTabMixin.js" import CRUDList from "aleksis.core/components/generic/CRUDList.vue"; import PersonChip from "aleksis.core/components/person/PersonChip.vue"; import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue"; +import CoursebookPrintDialog from "../CoursebookPrintDialog.vue"; import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue"; import ExtraMarkChip from "aleksis.apps.alsijil/components/extra_marks/ExtraMarkChip.vue"; import { statisticsByGroup } from "./statistics.graphql"; import { absenceReasons } from "../queries/absenceReasons.graphql"; -import { extraMarks } from "../../extra_marks/extra_marks.graphql"; +import { extraMarks } from "../queries/extraMarks.graphql"; import { MODE } from "./modes"; export default { @@ -99,6 +103,7 @@ export default { ExtraMarkChip, PersonChip, SecondaryActionButton, + CoursebookPrintDialog, }, data() { return { -- GitLab