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

Merge branch '287-absence-creation-form-should-support-datetimes' into 'master'

Resolve "Absence creation form should support datetimes"

Closes #287

See merge request !392
parents 344a0374 dd632b2b
No related branches found
No related tags found
1 merge request!392Resolve "Absence creation form should support datetimes"
Pipeline #192402 failed
......@@ -93,6 +93,7 @@ import SecondaryActionButton from "aleksis.core/components/generic/buttons/Secon
import loadingMixin from "aleksis.core/mixins/loadingMixin.js";
import permissionsMixin from "aleksis.core/mixins/permissions.js";
import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
import { DateTime } from "luxon";
import { createAbsencesForPersons } from "./absenceCreation.graphql";
......@@ -122,6 +123,7 @@ export default {
},
mounted() {
this.addPermissions(["alsijil.view_register_absence_rule"]);
this.clearForm();
},
methods: {
cancel() {
......@@ -131,8 +133,12 @@ export default {
},
clearForm() {
this.persons = [];
this.startDate = "";
this.endDate = "";
this.startDate = DateTime.now()
.startOf("day")
.toISO({ suppressSeconds: true });
this.endDate = DateTime.now()
.endOf("day")
.toISO({ suppressSeconds: true });
this.comment = "";
this.absenceReason = "";
},
......@@ -142,8 +148,8 @@ export default {
createAbsencesForPersons,
{
persons: this.persons.map((p) => p.id),
start: this.startDate,
end: this.endDate,
start: this.$toUTCISO(this.$parseISODate(this.startDate)),
end: this.$toUTCISO(this.$parseISODate(this.endDate)),
comment: this.comment,
reason: this.absenceReason,
},
......
......@@ -26,9 +26,10 @@
<v-row>
<v-col cols="12" :sm="6" class="pl-0">
<div aria-required="true">
<date-field
<date-time-field
:label="$t('forms.labels.start')"
:max="endDate"
:max-date="endDate"
:max-time="maxStartTime"
:rules="$rules().required.build()"
:value="startDate"
@input="$emit('start-date', $event)"
......@@ -37,9 +38,10 @@
</v-col>
<v-col cols="12" :sm="6" class="pr-0">
<div aria-required="true">
<date-field
<date-time-field
:label="$t('forms.labels.end')"
:min="startDate"
:min-date="startDate"
:min-time="minEndTime"
:rules="$rules().required.build()"
:value="endDate"
@input="$emit('end-date', $event)"
......@@ -69,15 +71,16 @@
<script>
import AbsenceReasonGroupSelect from "aleksis.apps.kolego/components/AbsenceReasonGroupSelect.vue";
import DateField from "aleksis.core/components/generic/forms/DateField.vue";
import DateTimeField from "aleksis.core/components/generic/forms/DateTimeField.vue";
import { persons } from "./absenceCreation.graphql";
import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js";
import { DateTime } from "luxon";
export default {
name: "AbsenceCreationForm",
components: {
AbsenceReasonGroupSelect,
DateField,
DateTimeField,
},
mixins: [formRulesMixin],
emits: [
......@@ -113,5 +116,25 @@ export default {
required: true,
},
},
computed: {
maxStartTime() {
// Only if on the same day
const start = DateTime.fromISO(this.startDate);
const end = DateTime.fromISO(this.endDate);
if (start.day !== end.day) return;
return end.minus({ minutes: 5 }).toFormat("HH:mm");
},
minEndTime() {
// Only if on the same day
const start = DateTime.fromISO(this.startDate);
const end = DateTime.fromISO(this.endDate);
if (start.day !== end.day) return;
return start.plus({ minutes: 5 }).toFormat("HH:mm");
},
},
};
</script>
......@@ -6,7 +6,7 @@ query persons {
}
}
query lessonsForPersons($persons: [ID]!, $start: Date!, $end: Date!) {
query lessonsForPersons($persons: [ID]!, $start: DateTime!, $end: DateTime!) {
items: lessonsForPersons(persons: $persons, start: $start, end: $end) {
id
lessons {
......@@ -31,8 +31,8 @@ query lessonsForPersons($persons: [ID]!, $start: Date!, $end: Date!) {
# Use absencesInputType?
mutation createAbsencesForPersons(
$persons: [ID]!
$start: Date!
$end: Date!
$start: DateTime!
$end: DateTime!
$comment: String
$reason: ID!
) {
......
......@@ -11,7 +11,7 @@ from django.utils.translation import gettext as _
from calendarweek import CalendarWeek
from aleksis.apps.chronos.managers import DateRangeQuerySetMixin
from aleksis.core.managers import AlekSISBaseManagerWithoutMigrations, PolymorphicBaseManager
from aleksis.core.managers import AlekSISBaseManagerWithoutMigrations, RecurrencePolymorphicManager
if TYPE_CHECKING:
from aleksis.core.models import Group
......@@ -189,7 +189,7 @@ class GroupRoleAssignmentQuerySet(DateRangeQuerySetMixin, QuerySet):
return self.filter(Q(groups=group) | Q(groups__child_groups=group))
class DocumentationManager(PolymorphicBaseManager):
class DocumentationManager(RecurrencePolymorphicManager):
"""Manager adding specific methods to documentations."""
def get_queryset(self):
......@@ -205,9 +205,7 @@ class DocumentationManager(PolymorphicBaseManager):
)
class ParticipationStatusManager(PolymorphicBaseManager):
class ParticipationStatusManager(RecurrencePolymorphicManager):
"""Manager adding specific methods to participation statuses."""
def get_queryset(self):
"""Ensure often used related data are loaded as well."""
return super().get_queryset().select_related("person", "absence_reason", "base_absence")
pass
......@@ -63,8 +63,8 @@ class Query(graphene.ObjectType):
lessons_for_persons = graphene.List(
LessonsForPersonType,
persons=graphene.List(graphene.ID, required=True),
start=graphene.Date(required=True),
end=graphene.Date(required=True),
start=graphene.DateTime(required=True),
end=graphene.DateTime(required=True),
)
extra_marks = FilterOrderList(ExtraMarkType)
......@@ -213,8 +213,8 @@ class Query(graphene.ObjectType):
for person in persons:
docs, dummies = Documentation.get_documentations_for_person(
person,
datetime.combine(start, datetime.min.time()),
datetime.combine(end, datetime.max.time()),
start,
end,
)
lessons_for_person.append(LessonsForPersonType(id=person, lessons=docs + dummies))
......
from datetime import datetime
import datetime
from typing import List
from django.core.exceptions import PermissionDenied
from django.db.models import Q
import graphene
......@@ -14,8 +16,8 @@ from .participation_status import ParticipationStatusType
class AbsencesForPersonsCreateMutation(graphene.Mutation):
class Arguments:
persons = graphene.List(graphene.ID, required=True)
start = graphene.Date(required=True)
end = graphene.Date(required=True)
start = graphene.DateTime(required=True)
end = graphene.DateTime(required=True)
comment = graphene.String(required=False)
reason = graphene.ID(required=True)
......@@ -23,7 +25,16 @@ class AbsencesForPersonsCreateMutation(graphene.Mutation):
participation_statuses = graphene.List(ParticipationStatusType)
@classmethod
def mutate(cls, root, info, persons, start, end, comment, reason): # noqa
def mutate(
cls,
root,
info,
persons: List[str | int],
start: datetime.datetime,
end: datetime.datetime,
comment: str,
reason: str | int,
):
participation_statuses = []
persons = Person.objects.filter(pk__in=persons)
......@@ -31,17 +42,30 @@ class AbsencesForPersonsCreateMutation(graphene.Mutation):
for person in persons:
if not info.context.user.has_perm("alsijil.register_absence_rule", person):
raise PermissionDenied()
kolego_absence, __ = Absence.objects.get_or_create(
date_start=start,
date_end=end,
# Check if there is an existing absence with overlapping datetime
absences = Absence.objects.filter(
Q(datetime_start__lte=start) | Q(date_start__lte=start.date()),
Q(datetime_end__gte=end) | Q(date_end__gte=end.date()),
reason_id=reason,
person=person,
defaults={"comment": comment},
)
if len(absences) > 0:
kolego_absence = absences.first()
else:
# Check for same times and create otherwise
kolego_absence, __ = Absence.objects.get_or_create(
datetime_start=start,
datetime_end=end,
reason_id=reason,
person=person,
defaults={"comment": comment},
)
events = ParticipationStatus.get_single_events(
datetime.combine(start, datetime.min.time()),
datetime.combine(end, datetime.max.time()),
start,
end,
None,
{"person": person},
with_reference_object=True,
......
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