diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
index c165cec1f90b936cba67b583564badd0aa6cd92c..2be32b7ff04c7a72e491fc4455b7b55feba54c3f 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/ManageStudentsDialog.vue
@@ -1,7 +1,6 @@
 <script>
 import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue";
 import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
-import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue";
 import DialogCloseButton from "aleksis.core/components/generic/buttons/DialogCloseButton.vue";
 import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue";
 import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue";
@@ -17,6 +16,7 @@ import TardinessChip from "./TardinessChip.vue";
 import TardinessField from "./TardinessField.vue";
 import ExtraMarkButtons from "../../extra_marks/ExtraMarkButtons.vue";
 import MessageBox from "aleksis.core/components/generic/MessageBox.vue";
+import UpdateParticipation from "./UpdateParticipation.vue";
 
 export default {
   name: "ManageStudentsDialog",
@@ -26,7 +26,6 @@ export default {
     TardinessChip,
     ExtraMarkChip,
     AbsenceReasonChip,
-    AbsenceReasonGroupSelect,
     AbsenceReasonButtons,
     PersonalNotes,
     PersonalNoteChip,
@@ -36,6 +35,7 @@ export default {
     SecondaryActionButton,
     SlideIterator,
     TardinessField,
+    UpdateParticipation,
     DialogCloseButton,
   },
   mixins: [updateParticipationMixin, deepSearchMixin],
@@ -117,6 +117,11 @@ export default {
         this.$once("save", this.activateFullDayDialog);
       }
     },
+    afterInnerSendToServer(_participations, field, value) {
+      if (field === "absenceReason" && value !== "present") {
+        this.$refs.editor.$once("save", this.activateFullDayDialog);
+      }
+    },
     markAsAbsentDayClick() {
       this.markAsAbsentDay.loading = true;
 
@@ -309,20 +314,14 @@ export default {
             </v-tooltip>
           </v-card-title>
           <v-card-text>
-            <absence-reason-group-select
-              allow-empty
-              :load-selected-chip="loading"
-              :value="item.absenceReason?.id || 'present'"
-              :custom-absence-reasons="absenceReasons"
-              @input="sendToServer([item], 'absenceReason', $event)"
-            />
-            <tardiness-field
+            <update-participation
+              ref="editor"
               v-bind="documentationPartProps"
-              :loading="loading"
-              :disabled="loading"
-              :participations="[item]"
-              :value="item.tardiness"
-              @input="sendToServer([item], 'tardiness', $event)"
+              :participation="item"
+              :force-loading="loading"
+              @beforeSendToServer="beforeSendToServer"
+              @duringSendToServer="duringUpdateSendToServer"
+              @afterSendToServer="afterInnerSendToServer"
             />
           </v-card-text>
           <v-divider />
@@ -368,5 +367,3 @@ export default {
     </template>
   </mobile-fullscreen-dialog>
 </template>
-
-<style scoped></style>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue
index 774decab0a88867af0fdb510ac8813edefec9a14..a2700420cf674a450a617debbeeff1056a001238 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue
@@ -81,6 +81,10 @@ export default {
       this.saveValue(this.previousValue);
     },
     processValueObjectOptional(value) {
+      if (value === null || value === undefined) {
+        return 0;
+      }
+
       if (Object.hasOwn(value, "value")) {
         return value.value;
       }
@@ -159,7 +163,7 @@ export default {
           {{
             $t("alsijil.personal_notes.confirm_delete_tardiness", {
               tardiness: previousValue,
-              name: participations.map((p) => p.person.firstName).join(", "),
+              name: participations.map((p) => p.person?.firstName).join(", "),
             })
           }}
         </template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipation.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipation.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7bdbf627fbb977abf0824e0466a9885cd2db0ebf
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipation.vue
@@ -0,0 +1,65 @@
+<template>
+  <div>
+    <absence-reason-group-select
+      class="mb-2"
+      allow-empty
+      :load-selected-chip="loadingIndicator"
+      :value="participation.absenceReason?.id || 'present'"
+      :custom-absence-reasons="absenceReasons"
+      @input="sendToServer([participation], 'absenceReason', $event)"
+    />
+    <tardiness-field
+      v-bind="documentationPartProps"
+      :loading="loadingIndicator"
+      :disabled="loadingIndicator"
+      :participations="[participation]"
+      :value="participation.tardiness"
+      @input="sendToServer([participation], 'tardiness', $event)"
+    />
+  </div>
+</template>
+<script>
+import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue";
+import TardinessField from "./TardinessField.vue";
+import updateParticipationMixin from "./updateParticipationMixin";
+
+export default {
+  name: "UpdateParticipation",
+  mixins: [updateParticipationMixin],
+  components: { AbsenceReasonGroupSelect, TardinessField },
+  props: {
+    participation: {
+      type: Object,
+      required: true,
+    },
+    forceLoading: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
+  },
+  emits: ["beforeSendToServer", "duringSendToServer", "afterSendToServer"],
+  methods: {
+    beforeSendToServer() {
+      this.$emit("beforeSendToServer");
+    },
+    duringUpdateSendToServer(participations, field, value, incomingStatuses) {
+      this.$emit(
+        "duringSendToServer",
+        participations,
+        field,
+        value,
+        incomingStatuses,
+      );
+    },
+    afterSendToServer(participations, field, value) {
+      this.$emit("afterSendToServer", participations, field, value);
+    },
+  },
+  computed: {
+    loadingIndicator() {
+      return this.loading || this.forceLoading;
+    },
+  },
+};
+</script>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipations.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipations.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1055c424275596d9f26fa87821434fb09abae630
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/UpdateParticipations.vue
@@ -0,0 +1,44 @@
+<script>
+import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonButtons.vue";
+import updateParticipationMixin from "./updateParticipationMixin";
+
+export default {
+  name: "UpdateParticipations",
+  components: {
+    AbsenceReasonButtons,
+  },
+  mixins: [updateParticipationMixin],
+  props: {
+    participationStatuses: {
+      type: Array,
+      required: true,
+    },
+    absenceReasons: {
+      type: Array,
+      required: true,
+    },
+  },
+  emits: ["update:participationStatuses"],
+  methods: {
+    afterSendToServer() {
+      this.$once("save", () => this.$emit("update:participationStatuses", []));
+    },
+  },
+};
+</script>
+
+<template>
+  <v-card>
+    <v-card-text>
+      <h4>{{ $t("alsijil.coursebook.participation_status") }}</h4>
+      <absence-reason-buttons
+        allow-empty
+        empty-value="present"
+        :custom-absence-reasons="absenceReasons"
+        @input="sendToServer(participationStatuses, 'absenceReason', $event)"
+      />
+    </v-card-text>
+  </v-card>
+</template>
+
+<style scoped></style>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/DeleteExtraMarkPersonalNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/DeleteExtraMarkPersonalNote.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7666c60f4fad325c2af92edb90ae5154ab20e1fb
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/DeleteExtraMarkPersonalNote.vue
@@ -0,0 +1,70 @@
+<script>
+import { deletePersonalNotes } from "./personal_notes.graphql";
+import ConfirmDialog from "aleksis.core/components/generic/dialogs/ConfirmDialog.vue";
+import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
+import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
+
+export default {
+  name: "DeleteAssignedExtraMark",
+  components: {
+    ConfirmDialog,
+  },
+  mixins: [mutateMixin, personalNoteRelatedMixin],
+  props: {
+    personalNote: {
+      type: Object,
+      required: true,
+    },
+    person: {
+      type: Object,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      showDeleteConfirm: false,
+    };
+  },
+  methods: {
+    deleteNote() {
+      this.mutate(
+        deletePersonalNotes,
+        {
+          ids: [this.personalNote.id],
+        },
+        (storedPersonalNotes) => {
+          const index = storedPersonalNotes.findIndex(
+            (n) => n.id === this.personalNote.id,
+          );
+          storedPersonalNotes.splice(index, 1);
+
+          return storedPersonalNotes;
+        },
+      );
+    },
+  },
+};
+</script>
+
+<template>
+  <v-btn color="error" icon @click.prevent.stop="showDeleteConfirm = true">
+    <v-icon color="error">$deleteContent</v-icon>
+    <confirm-dialog
+      v-model="showDeleteConfirm"
+      @confirm="deleteNote"
+      @cancel="showDeleteConfirm = false"
+    >
+      <template #title>
+        {{ $t("alsijil.personal_notes.confirm_delete") }}
+      </template>
+      <template #text>
+        {{
+          $t("alsijil.personal_notes.confirm_delete_extra_mark", {
+            extraMark: personalNote.extraMark.name,
+            name: person.firstName || person.fullName,
+          })
+        }}
+      </template>
+    </confirm-dialog>
+  </v-btn>
+</template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
index 43175c7402100c5ef9e4b84c153a8e79a9bb7f76..f81bb0e2b1e27ae95f2e46db873d01f6b97eac53 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
@@ -17,6 +17,11 @@ export default {
       type: Object,
       required: true,
     },
+    person: {
+      type: Object,
+      required: false,
+      default: () => ({ fullName: null }),
+    },
   },
   computed: {
     model: {
@@ -148,7 +153,7 @@ export default {
           {{
             $t("alsijil.personal_notes.confirm_delete_explanation", {
               note: value.note,
-              name: participation.person.fullName,
+              name: (participation?.person || person).fullName,
             })
           }}
         </template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue
index c8bde2e8bed22f4120dec5108f8f2f137bdfefe9..8f7d5b428da74d4bc3dc438dea0e0140678378cd 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForGroupTab.vue
@@ -62,7 +62,7 @@
 
     <template #actions="{ item }">
       <secondary-action-button
-        i18n-key="alsijil.personal_notes.statistics.person_view_details"
+        i18n-key="alsijil.coursebook.statistics.person_view_details"
         icon-text="mdi-open-in-new"
         :to="{
           name: 'alsijil.coursebook_statistics',
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue
index c5a8ed51e2d89dbdd79b17e7b839141f2452a9cb..684e5dacc774e5891f771bd60da4cc39259edf17 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/StatisticsForPersonPage.vue
@@ -12,6 +12,7 @@
           :enable-create="false"
           :enable-edit="false"
           :elevated="false"
+          @lastQuery="lastQuery = $event"
         >
           <template #additionalActions>
             <v-btn-toggle
@@ -37,91 +38,187 @@
               text
               @click="statisticsBottomSheet = !statisticsBottomSheet"
             >
-              {{ $t("alsijil.personal_notes.statistics.person_page.summary") }}
+              {{ $t("alsijil.coursebook.statistics.person_page.summary") }}
             </v-btn>
           </template>
           <template #default="{ items }">
-            <v-list>
-              <v-list-item v-for="item in items" :key="item.id" ripple>
-                <v-list-item-content>
-                  <v-list-item-title>
-                    <!-- date & timeslot -->
-                    <time
-                      :datetime="item.relatedDocumentation.datetimeStart"
-                      class="text-no-wrap"
-                    >
-                      {{
-                        $d(
-                          $parseISODate(
-                            item.relatedDocumentation.datetimeStart,
-                          ),
-                          "short",
-                        )
-                      }}
-                    </time>
+            <v-expand-transition>
+              <update-participations
+                v-show="selected.length > 0"
+                class="mt-2"
+                :subjects="[]"
+                :absence-reasons="absenceReasons"
+                :participation-statuses.sync="selected"
+                :extra-marks="[]"
+                :affected-query="lastQuery"
+                :documentation="{}"
+              />
+            </v-expand-transition>
 
-                    <time
-                      :datetime="item.relatedDocumentation.datetimeStart"
-                      class="text-no-wrap"
-                    >
-                      {{
-                        $d(
-                          $parseISODate(
-                            item.relatedDocumentation.datetimeStart,
-                          ),
-                          "shortTime",
-                        )
-                      }}
-                    </time>
-                    <span>-</span>
-                    <time
-                      :datetime="item.relatedDocumentation.datetimeEnd"
-                      class="text-no-wrap"
-                    >
-                      {{
-                        $d(
-                          $parseISODate(item.relatedDocumentation.datetimeEnd),
-                          "shortTime",
-                        )
-                      }}
-                    </time>
-                  </v-list-item-title>
-                  <v-list-item-subtitle class="overflow-scroll">
-                    <!-- teacher -->
-                    <person-chip
-                      v-for="teacher in item.relatedDocumentation.teachers"
-                      :key="teacher.id"
-                      :person="teacher"
-                      no-link
-                      small
-                    />
-                    <!-- group -->
-                    <span>
-                      {{ item.groupShortName }}
-                    </span>
-                    <!-- subject -->
-                    <subject-chip
-                      :subject="item.relatedDocumentation.subject"
-                      small
-                    />
-                  </v-list-item-subtitle>
-                </v-list-item-content>
-                <v-list-item-action>
-                  <!-- chips: absences & extraMarks -->
-                  <absence-reason-chip
-                    v-if="item.absenceReason"
-                    :absence-reason="item.absenceReason"
-                  />
-                  <extra-mark-chip
-                    v-if="item.extraMark"
-                    :extra-mark="item.extraMark"
-                  />
-                  <div v-if="item.note">
-                    {{ item.note }}
-                  </div>
-                </v-list-item-action>
-              </v-list-item>
-            </v-list>
+            <v-item-group multiple v-model="selected" class="mt-2">
+              <v-expansion-panels focusable>
+                <v-expansion-panel
+                  v-for="item in items"
+                  :key="item.id"
+                  ripple
+                  :readonly="!showEdit(item)"
+                >
+                  <v-expansion-panel-header
+                    :hide-actions="!showEdit(item) && !showDelete(item)"
+                    disable-icon-rotate
+                  >
+                    <template #actions>
+                      <v-btn v-if="showEdit(item)" color="primary" icon>
+                        <v-icon> $edit </v-icon>
+                      </v-btn>
+                      <delete-assigned-extra-mark
+                        v-if="showDelete(item)"
+                        :personal-note="item"
+                        :participation="item.participation || {}"
+                        :subjects="[]"
+                        :absence-reasons="[]"
+                        :extra-marks="[]"
+                        :affected-query="lastQuery"
+                        :documentation="item.relatedDocumentation"
+                        :person="personName"
+                      />
+                    </template>
+                    <v-row class="mr-2">
+                      <v-col cols="12" md="6" class="pa-0 d-flex">
+                        <v-list-item-avatar
+                          v-if="
+                            mode === MODE.PARTICIPATIONS &&
+                            !$vuetify.breakpoint.mobile
+                          "
+                        >
+                          <v-item v-slot="{ active, toggle }" :value="item.id">
+                            <v-simple-checkbox
+                              :value="active"
+                              @click="toggle"
+                            />
+                          </v-item>
+                        </v-list-item-avatar>
+                        <v-list-item-content>
+                          <v-list-item-title>
+                            <!-- date & timeslot -->
+                            <time
+                              :datetime="
+                                item.relatedDocumentation.datetimeStart
+                              "
+                              class="text-no-wrap"
+                            >
+                              {{
+                                $d(
+                                  $parseISODate(
+                                    item.relatedDocumentation.datetimeStart,
+                                  ),
+                                  "short",
+                                )
+                              }}
+                            </time>
+
+                            <time
+                              :datetime="
+                                item.relatedDocumentation.datetimeStart
+                              "
+                              class="text-no-wrap"
+                            >
+                              {{
+                                $d(
+                                  $parseISODate(
+                                    item.relatedDocumentation.datetimeStart,
+                                  ),
+                                  "shortTime",
+                                )
+                              }}
+                            </time>
+                            <span>-</span>
+                            <time
+                              :datetime="item.relatedDocumentation.datetimeEnd"
+                              class="text-no-wrap"
+                            >
+                              {{
+                                $d(
+                                  $parseISODate(
+                                    item.relatedDocumentation.datetimeEnd,
+                                  ),
+                                  "shortTime",
+                                )
+                              }}
+                            </time>
+                          </v-list-item-title>
+                          <v-list-item-subtitle class="overflow-scroll">
+                            <!-- teacher -->
+                            <person-chip
+                              v-for="teacher in item.relatedDocumentation
+                                .teachers"
+                              :key="teacher.id"
+                              :person="teacher"
+                              no-link
+                              small
+                            />
+                            <!-- group -->
+                            <span>
+                              {{ item.groupShortName }}
+                            </span>
+                            <!-- subject -->
+                            <subject-chip
+                              :subject="item.relatedDocumentation.subject"
+                              small
+                            />
+                          </v-list-item-subtitle>
+                        </v-list-item-content>
+                      </v-col>
+                      <v-col cols="12" md="6" class="pa-0">
+                        <v-list-item-action
+                          class="flex-row full-width justify-md-end ma-0 align-center fill-height"
+                        >
+                          <!-- chips: absences & extraMarks -->
+                          <absence-reason-chip
+                            v-if="item.absenceReason"
+                            :absence-reason="item.absenceReason"
+                          />
+                          <tardiness-chip
+                            v-if="item.tardiness"
+                            :tardiness="item.tardiness"
+                            class="ms-1"
+                          />
+                          <extra-mark-chip
+                            v-if="item.extraMark"
+                            :extra-mark="item.extraMark"
+                          />
+                          <personal-note-chip v-if="item.note" :note="item" />
+                        </v-list-item-action>
+                      </v-col>
+                    </v-row>
+                  </v-expansion-panel-header>
+                  <v-expansion-panel-content>
+                    <v-card-text class="pb-0">
+                      <text-note
+                        v-if="item.note"
+                        :value="item"
+                        :participation="{}"
+                        :person="personName"
+                        :subjects="[]"
+                        :absence-reasons="absenceReasons"
+                        :extra-marks="[]"
+                        :affected-query="lastQuery"
+                        :documentation="item.relatedDocumentation"
+                      />
+                      <update-participation
+                        v-else
+                        :participation="item"
+                        :subjects="[]"
+                        :absence-reasons="absenceReasons"
+                        :extra-marks="[]"
+                        :affected-query="lastQuery"
+                        :documentation="item.relatedDocumentation"
+                      />
+                    </v-card-text>
+                  </v-expansion-panel-content>
+                </v-expansion-panel>
+              </v-expansion-panels>
+            </v-item-group>
             <v-divider></v-divider>
           </template>
         </c-r-u-d-iterator>
@@ -129,6 +226,7 @@
       <statistics-for-person-card
         v-if="!$vuetify.breakpoint.mobile"
         class="flex-shrink-1"
+        style="min-width: 15vw"
         :compact="false"
         :person="{ id: personId }"
       />
@@ -155,6 +253,7 @@
 </template>
 
 <script>
+import { absenceReasons } from "../queries/absenceReasons.graphql";
 import AbsenceReasonChip from "aleksis.apps.kolego/components/AbsenceReasonChip.vue";
 import ActiveSchoolTermSelect from "aleksis.core/components/school_term/ActiveSchoolTermSelect.vue";
 import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue";
@@ -171,10 +270,22 @@ import {
 } from "./statistics.graphql";
 import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue";
 import { MODE } from "./modes.js";
+import PersonalNoteChip from "../personal_notes/PersonalNoteChip.vue";
+import TextNote from "../personal_notes/TextNote.vue";
+import UpdateParticipation from "../absences/UpdateParticipation.vue";
+import TardinessChip from "../absences/TardinessChip.vue";
+import DeleteAssignedExtraMark from "../personal_notes/DeleteExtraMarkPersonalNote.vue";
+import UpdateParticipations from "../absences/UpdateParticipations.vue";
 
 export default {
   name: "StatisticsForPersonPage",
   components: {
+    UpdateParticipations,
+    DeleteAssignedExtraMark,
+    TardinessChip,
+    UpdateParticipation,
+    TextNote,
+    PersonalNoteChip,
     ActiveSchoolTermSelect,
     ExtraMarkChip,
     AbsenceReasonChip,
@@ -213,10 +324,18 @@ export default {
         );
       },
     },
+    absenceReasons: {
+      query: absenceReasons,
+      update: (data) => data.items,
+    },
   },
   data() {
     return {
+      personName: {},
       statisticsBottomSheet: false,
+      lastQuery: null,
+      absenceReasons: [],
+      selected: [],
     };
   },
   computed: {
@@ -240,6 +359,8 @@ export default {
         return;
       }
 
+      this.selected = [];
+
       this.$router.push({
         name: "alsijil.coursebook_statistics",
         params: {
@@ -248,6 +369,16 @@ export default {
         },
       });
     },
+    showEdit(item) {
+      // Notes with ExtraMark cannot be edited, only deleted
+      return (
+        item.canEdit && (item.note || item.absenceReason || item.tardiness)
+      );
+    },
+    showDelete(item) {
+      // Only ExtraMarks can be deleted
+      return item.canDelete && item.extraMark;
+    },
   },
 };
 </script>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql
index 901bcd251829c87783bd432ad90d69a07c2cca65..1cffdc7178defa256f5f9e46707541a526cb1dec 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/statistics/statistics.graphql
@@ -65,6 +65,8 @@ query participationsOfPerson($person: ID!) {
         colourBg
       }
     }
+    canEdit
+    canDelete
   }
 }
 
@@ -98,6 +100,8 @@ query personalNotesForPerson($person: ID!) {
         colourBg
       }
     }
+    canEdit
+    canDelete
   }
 }
 
diff --git a/aleksis/apps/alsijil/frontend/messages/de.json b/aleksis/apps/alsijil/frontend/messages/de.json
index 872b2e07510f802eebe988b4adda0141f404391f..8a1c9997337f613fe285a18ea5517eac65daab8a 100644
--- a/aleksis/apps/alsijil/frontend/messages/de.json
+++ b/aleksis/apps/alsijil/frontend/messages/de.json
@@ -148,6 +148,7 @@
       },
       "confirm_delete": "Anmerkung wirklich löschen?",
       "confirm_delete_explanation": "Die Notiz \"{note}\" für {name} wird entfernt.",
+      "confirm_delete_extra_mark": "Die Markierung {extraMark} für {name} wird entfernt.",
       "confirm_delete_tardiness": "Die Verspätung von {name} in Höhe von {tardiness} Minuten wird entfernt.",
       "create_personal_note": "Weitere Notiz",
       "late": "Verspätet",
diff --git a/aleksis/apps/alsijil/frontend/messages/en.json b/aleksis/apps/alsijil/frontend/messages/en.json
index 2294349f2f1a42241e4017865bcd30fda40ee919..a40f8d5475a9c3e9843e4a72ac745c723a1137e3 100644
--- a/aleksis/apps/alsijil/frontend/messages/en.json
+++ b/aleksis/apps/alsijil/frontend/messages/en.json
@@ -81,8 +81,11 @@
           "title": "Coursebook · Statistics"
         },
         "person_page": {
-          "title": "Statistics"
-        }
+          "title": "Coursebook · Statistics · {fullName}",
+          "summary": "Summary"
+        },
+        "person_view_details": "Details",
+        "title_plural": "Statistics"
       },
       "notes": {
         "show_list": "List of participants",
@@ -160,18 +163,8 @@
       "confirm_delete": "Delete note?",
       "confirm_delete_explanation": "The note \"{note}\" for {name} will be removed.",
       "confirm_delete_tardiness": "The tardiness of {tardiness} minutes will be removed for {name}.",
+      "confirm_delete_extra_mark": "The mark {extraMark} for {name} will be removed.",
       "no_results": "No search results for {search}",
-      "statistics": {
-        "person_compact": {
-          "title": "Coursebook · Statistics"
-        },
-        "person_page": {
-          "title": "Coursebook · Statistics · {fullName}",
-          "summary": "Summary"
-        },
-        "person_view_details": "Details",
-        "title_plural": "Statistics"
-      },
       "personal_notes": "Personal Notes"
     }
   },
diff --git a/aleksis/apps/alsijil/schema/__init__.py b/aleksis/apps/alsijil/schema/__init__.py
index 604cda6cd229533086533d855563a892f440d572..284d8da2d3a2570e57ae902b14302048eba7f3b8 100644
--- a/aleksis/apps/alsijil/schema/__init__.py
+++ b/aleksis/apps/alsijil/schema/__init__.py
@@ -309,8 +309,8 @@ class Query(graphene.ObjectType):
         school_term = get_active_school_term(info.context)
         return graphene_django_optimizer.query(
             ParticipationStatus.objects.filter(
+                Q(absence_reason__isnull=False) | Q(tardiness__isnull=False),
                 person=person,
-                absence_reason__isnull=False,
                 datetime_start__date__gte=school_term.date_start,
                 datetime_end__date__lte=school_term.date_end,
             ).order_by("-related_documentation__datetime_start"),