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

Add migration for existing overlapping absences

parent 812c00fe
No related branches found
No related tags found
1 merge request!52Resolve "Only allow one absence at any point of time"
Pipeline #194084 passed
# Generated by Django 4.2.13 on 2024-07-16 11:01
from datetime import datetime, time
from django.db import migrations, models
from django.db.models import Q
def _run_forward(apps, schema_editor):
Absence = apps.get_model("kolego", "Absence")
for absence in Absence.objects.order_by("-datetime_start", "-date_start"):
# Convert dates of new event to datetimes in case dates are used
new_datetime_start = (
absence.datetime_start
if absence.datetime_start
else datetime.combine(absence.date_start, time.min)
).astimezone(absence.timezone)
new_datetime_end = (
absence.datetime_end
if absence.datetime_end
else datetime.combine(absence.date_end, time.max)
).astimezone(absence.timezone)
events_within = Absence.objects.filter(
person=absence.person,
).filter(
Q(datetime_start__lte=new_datetime_end, datetime_end__gte=new_datetime_start)
| Q(date_start__lte=new_datetime_end.date(), date_end__gte=new_datetime_start.date())
)
for event_within in events_within:
event_within_datetime_start = (
event_within.datetime_start
if event_within.datetime_start
else datetime.combine(event_within.date_start, time.min)
)
event_within_datetime_end = (
event_within.datetime_end
if event_within.datetime_end
else datetime.combine(event_within.date_end, time.max)
)
# If overlapping absence has the same reason, just extend it
if event_within.reason == absence.reason:
event_within.datetime_start = min(new_datetime_start, event_within_datetime_start)
event_within.datetime_end = max(new_datetime_end, event_within_datetime_end)
event_within.save()
else:
if (
new_datetime_start > event_within_datetime_start
and new_datetime_end < event_within_datetime_end
):
# Cut existing event in two parts
# First, cut end date of existing one
event_within.datetime_end = new_datetime_start
event_within.save()
# Then, create new event based on existing one filling up the remaining time
end_filler_event = event_within
end_filler_event.pk = None
end_filler_event.id = None
end_filler_event.calendarevent_ptr_id = None
end_filler_event.freebusy_ptr_id = None
end_filler_event._state.adding = True
end_filler_event.datetime_start = new_datetime_end
end_filler_event.datetime_end = event_within_datetime_end
end_filler_event.save()
elif (
new_datetime_start <= event_within_datetime_start
and new_datetime_end >= event_within_datetime_end
):
# Delete existing event
event_within.delete()
elif (
new_datetime_start > event_within_datetime_start
and new_datetime_start < event_within_datetime_end
and new_datetime_end >= event_within_datetime_end
):
# Cut end of existing event
event_within.datetime_end = new_datetime_start
event_within.save()
elif (
new_datetime_start <= event_within_datetime_start
and new_datetime_end < event_within_datetime_end
and new_datetime_end > event_within_datetime_start
):
# Cut start of existing event
event_within.datetime_start = new_datetime_end
event_within.save()
class Migration(migrations.Migration):
dependencies = [
("kolego", "0004_absencereasontag_absencereason_tags"),
]
operations = [migrations.RunPython(_run_forward)]
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