Skip to content
Snippets Groups Projects
Commit 9f2e8cd3 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge branch...

Merge branch '288-suggest-creating-kolego-absence-for-the-rest-of-the-day-when-entering-absences' into 'master'

Resolve "Suggest creating Kolego absence for the rest of the day when entering absences"

Closes #288

See merge request !373
parents 69e52c72 e11fdcc9
No related branches found
No related tags found
1 merge request!373Resolve "Suggest creating Kolego absence for the rest of the day when entering absences"
Pipeline #192445 failed
......@@ -3,16 +3,22 @@ import AbsenceReasonButtons from "aleksis.apps.kolego/components/AbsenceReasonBu
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";
import updateParticipationMixin from "./updateParticipationMixin.js";
import deepSearchMixin from "aleksis.core/mixins/deepSearchMixin.js";
import LessonInformation from "../documentation/LessonInformation.vue";
import {
extendParticipationStatuses,
updateParticipationStatuses,
} from "./participationStatus.graphql";
import SlideIterator from "aleksis.core/components/generic/SlideIterator.vue";
import PersonalNotes from "../personal_notes/PersonalNotes.vue";
import ExtraMarkChip from "../../extra_marks/ExtraMarkChip.vue";
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";
export default {
name: "ManageStudentsDialog",
......@@ -26,7 +32,9 @@ export default {
AbsenceReasonButtons,
PersonalNotes,
LessonInformation,
MessageBox,
MobileFullscreenDialog,
SecondaryActionButton,
SlideIterator,
TardinessField,
DialogCloseButton,
......@@ -39,6 +47,14 @@ export default {
loadSelected: false,
selected: [],
isExpanded: false,
markAsAbsentDay: {
showAlert: false,
num: 0,
reason: "no reason",
name: "nobody",
participationIDs: [],
loading: false,
},
};
},
props: {
......@@ -69,6 +85,71 @@ export default {
this.$set(this.selected, []);
this.$refs.iterator.selected = [];
},
activateFullDayDialog(items) {
const itemIds = items.map((item) => item.id);
const participations = this.documentation.participations.filter((part) =>
itemIds.includes(part.id),
);
if (this.markAsAbsentDay.num === 1) {
this.markAsAbsentDay.name = participations[0].person.firstName;
}
this.$set(this.markAsAbsentDay, "participationIDs", itemIds);
this.markAsAbsentDay.loading = false;
this.markAsAbsentDay.showAlert = true;
},
beforeSendToServer() {
this.markAsAbsentDay.showAlert = false;
this.markAsAbsentDay.participationIDs = [];
},
duringUpdateSendToServer(
_participations,
_field,
_value,
incomingStatuses,
) {
this.markAsAbsentDay.reason = incomingStatuses[0].absenceReason?.name;
this.markAsAbsentDay.num = incomingStatuses.length;
},
afterSendToServer(_participations, field, value) {
if (field === "absenceReason" && value !== "present") {
this.$once("save", this.activateFullDayDialog);
}
},
markAsAbsentDayClick() {
this.markAsAbsentDay.loading = true;
this.mutate(
extendParticipationStatuses,
{
input: this.markAsAbsentDay.participationIDs,
},
(storedDocumentations, incomingStatuses) => {
const documentation = storedDocumentations.find(
(doc) => doc.id === this.documentation.id,
);
incomingStatuses.forEach((newStatus) => {
const participationStatus = documentation.participations.find(
(part) => part.id === newStatus.id,
);
participationStatus.baseAbsence = newStatus.baseAbsence;
participationStatus.isOptimistic = newStatus.isOptimistic;
});
this.markAsAbsentDay.reason = "no reason";
this.markAsAbsentDay.num = 0;
this.markAsAbsentDay.participationIDs = [];
this.markAsAbsentDay.loading = false;
this.markAsAbsentDay.showAlert = false;
return storedDocumentations;
},
);
},
},
};
</script>
......@@ -106,6 +187,40 @@ export default {
class="pt-4 full-width"
/>
</v-scroll-x-transition>
<message-box
v-model="markAsAbsentDay.showAlert"
color="success"
icon="$success"
transition="slide-y-transition"
dismissible
class="mt-4 mb-0 full-width"
>
<div class="text-subtitle-2">
{{
$tc(
"alsijil.coursebook.mark_as_absent_day.title",
markAsAbsentDay.num,
markAsAbsentDay,
)
}}
</div>
<p class="text-body-2 pa-0 ma-0" style="word-break: break-word">
{{
$t(
"alsijil.coursebook.mark_as_absent_day.description",
markAsAbsentDay,
)
}}
</p>
<secondary-action-button
color="success"
i18n-key="alsijil.coursebook.mark_as_absent_day.action_button"
class="mt-2"
:loading="markAsAbsentDay.loading"
@click="markAsAbsentDayClick"
/>
</message-box>
</template>
<template #content>
<slide-iterator
......
......@@ -64,3 +64,14 @@ mutation touchDocumentation($documentationId: ID!) {
}
}
}
mutation extendParticipationStatuses($input: [ID]!) {
extendParticipationStatuses(input: $input) {
items: participations {
id
}
absences {
id
}
}
}
......@@ -28,6 +28,8 @@ export default {
return;
}
this.beforeSendToServer(participations, field, value);
this.mutate(
updateParticipationStatuses,
{
......@@ -51,9 +53,18 @@ export default {
participationStatus.isOptimistic = newStatus.isOptimistic;
});
this.duringUpdateSendToServer(
participations,
field,
value,
incomingStatuses,
);
return storedDocumentations;
},
);
this.afterSendToServer(participations, field, value);
},
addExtraMarks(participations, extraMarkId) {
// Get all participation statuses without this extra mark and get the respective person ids
......@@ -91,5 +102,14 @@ export default {
},
);
},
beforeSendToServer(_participations, _field, _value) {
// Noop hook
},
duringUpdateSendToServer(_participations, _field, _value, _incoming) {
// Noop hook
},
afterSendToServer(_participations, _field, _value) {
// Noop hook
},
},
};
......@@ -111,6 +111,11 @@
"lessons": "No lessons | 1 lesson | {count} lessons",
"success": "The absences were registered successfully.",
"warning": "The following lessons are in the selected time period. Please check that you want to register the absences for these lessons before confirming."
},
"mark_as_absent_day": {
"title": "Error: no person | Successfully marked {name} as {reason} | Successfully marked {n} people as {reason}",
"description": "Do you want to mark them as {reason} for the rest of their day?",
"action_button": "Extend absence"
}
},
"personal_notes": {
......
......@@ -32,7 +32,10 @@ from .extra_marks import (
ExtraMarkBatchPatchMutation,
ExtraMarkType,
)
from .participation_status import ParticipationStatusBatchPatchMutation
from .participation_status import (
ExtendParticipationStatusToAbsenceBatchMutation,
ParticipationStatusBatchPatchMutation,
)
from .personal_note import (
PersonalNoteBatchCreateMutation,
PersonalNoteBatchDeleteMutation,
......@@ -233,6 +236,7 @@ class Mutation(graphene.ObjectType):
touch_documentation = TouchDocumentationMutation.Field()
update_participation_statuses = ParticipationStatusBatchPatchMutation.Field()
create_absences_for_persons = AbsencesForPersonsCreateMutation.Field()
extend_participation_statuses = ExtendParticipationStatusToAbsenceBatchMutation.Field()
create_extra_marks = ExtraMarkBatchCreateMutation.Field()
update_extra_marks = ExtraMarkBatchPatchMutation.Field()
......
import datetime
from django.core.exceptions import PermissionDenied
from django.utils.translation import gettext_lazy as _
import graphene
from graphene_django import DjangoObjectType
from reversion import create_revision, set_comment, set_user
from aleksis.apps.alsijil.models import NewPersonalNote, ParticipationStatus
from aleksis.apps.alsijil.schema.personal_note import PersonalNoteType
from aleksis.apps.kolego.models import Absence
from aleksis.apps.kolego.schema.absence import AbsenceType
from aleksis.core.schema.base import (
BaseBatchPatchMutation,
DjangoFilterMixin,
......@@ -70,3 +76,77 @@ class ParticipationStatusBatchPatchMutation(BaseBatchPatchMutation):
"alsijil.edit_participation_status_for_documentation_rule", obj.related_documentation
):
raise PermissionDenied()
class ExtendParticipationStatusToAbsenceBatchMutation(graphene.Mutation):
class Arguments:
input = graphene.List(graphene.ID, description=_("List of ParticipationStatus IDs"))
participations = graphene.List(ParticipationStatusType)
absences = graphene.List(AbsenceType)
@classmethod
def create_absence(cls, info, participation_id):
participation = ParticipationStatus.objects.get(pk=participation_id)
if participation.date_end:
end_date = participation.date_end
else:
end_date = ParticipationStatus.value_end_datetime(participation).date()
end_datetime = datetime.datetime.combine(
end_date, datetime.time.max, participation.timezone
)
if participation.base_absence:
# Update the base absence to increase length if needed
absence = participation.base_absence
if absence.date_end:
if absence.date_end < end_date:
absence.date_end = end_date
absence.save()
return participation, absence
# Absence uses a datetime
if absence.datetime_end.astimezone(absence.timezone) < end_datetime:
# The end date ends after the previous absence end
absence.datetime_end = end_datetime
absence.save()
return participation, absence
else:
# No base absence, simply create one
data = dict(
reason_id=participation.absence_reason.id,
person=participation.person,
)
if participation.date_start:
data["date_start"] = participation.date_start
data["date_end"] = end_date
else:
data["datetime_start"] = ParticipationStatus.value_start_datetime(participation)
data["datetime_end"] = end_datetime
absence, __ = Absence.objects.get_or_create(**data)
participation.base_absence = absence
participation.save()
return participation, absence
@classmethod
def mutate(cls, root, info, input): # noqa
with create_revision():
set_user(info.context.user)
set_comment(_("Extended absence reason from coursebook."))
participations, absences = zip(
*[cls.create_absence(info, participation_id) for participation_id in input]
)
return ExtendParticipationStatusToAbsenceBatchMutation(
participations=participations, absences=absences
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment