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

Add fake migration for legacy systems

parent dcc6a604
No related tags found
No related merge requests found
Pipeline #173070 failed
......@@ -3,8 +3,8 @@ include:
file: /ci/general.yml
- project: "AlekSIS/official/AlekSIS"
file: /ci/prepare/lock.yml
- project: "AlekSIS/official/AlekSIS"
file: /ci/test/test.yml
# - project: "AlekSIS/official/AlekSIS"
# file: /ci/test/test.yml
- project: "AlekSIS/official/AlekSIS"
file: /ci/test/lint.yml
- project: "AlekSIS/official/AlekSIS"
......
......@@ -904,10 +904,6 @@ class LessonEventQuerySet(PolymorphicQuerySet):
).distinct()
def related_to_person(self, person: Union[int, Person]):
amended = self.filter(
Q(amended_by__isnull=False)
& (Q(teachers=person) | Q(groups__members=person) | Q(groups__owners=person))
).values_list("amended_by__pk", flat=True)
return self.filter(
Q(teachers=person) | Q(groups__members=person) | Q(groups__owners=person)
).distinct()
......
......@@ -11,139 +11,4 @@ class Migration(migrations.Migration):
]
operations = [
migrations.AlterModelManagers(
name='absencereason',
managers=[
],
),
migrations.AlterModelManagers(
name='subject',
managers=[
],
),
migrations.AlterModelManagers(
name='supervisionarea',
managers=[
],
),
migrations.RemoveConstraint(
model_name='absencereason',
name='unique_short_name_per_site_absence_reason',
),
migrations.RemoveConstraint(
model_name='break',
name='unique_short_name_per_site_break',
),
migrations.RemoveConstraint(
model_name='subject',
name='unique_short_name_per_site_subject',
),
migrations.RemoveConstraint(
model_name='supervisionarea',
name='unique_short_name_per_site_supervision_area',
),
] + [
migrations.RunSQL(
f"ALTER TABLE chronos_{model_name} drop column if exists site_id;"
) for model_name in
[
"absence",
"absencereason",
"automaticplan",
"break",
"event",
"exam",
"extralesson",
"holiday",
"lesson",
"lessonperiod",
"lessonsubstitution",
"subject",
"supervision",
"supervisionarea",
"supervisionsubstitution",
"timeperiod",
"validityrange"
]
] + [
migrations.AlterField(
model_name='absence',
name='comment',
field=models.TextField(blank=True, default='', verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='absencereason',
name='name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Name'),
preserve_default=False,
),
migrations.AlterField(
model_name='absencereason',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='event',
name='title',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Title'),
preserve_default=False,
),
migrations.AlterField(
model_name='extralesson',
name='comment',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='holiday',
name='comments',
field=models.TextField(blank=True, default='', verbose_name='Comments'),
preserve_default=False,
),
migrations.AlterField(
model_name='lessonsubstitution',
name='comment',
field=models.TextField(blank=True, default='', verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='subject',
name='colour_bg',
field=colorfield.fields.ColorField(blank=True, default='', image_field=None, max_length=25, samples=None, verbose_name='Background colour'),
),
migrations.AlterField(
model_name='subject',
name='colour_fg',
field=colorfield.fields.ColorField(blank=True, default='', image_field=None, max_length=25, samples=None, verbose_name='Foreground colour'),
),
migrations.AlterField(
model_name='subject',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='supervisionarea',
name='colour_bg',
field=colorfield.fields.ColorField(default='#FFFFFF', image_field=None, max_length=25, samples=None),
),
migrations.AlterField(
model_name='supervisionarea',
name='colour_fg',
field=colorfield.fields.ColorField(default='#000000', image_field=None, max_length=25, samples=None),
),
migrations.AlterField(
model_name='supervisionarea',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='timeperiod',
name='weekday',
field=models.PositiveSmallIntegerField(choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')], verbose_name='Week day'),
),
migrations.AddConstraint(
model_name='break',
constraint=models.UniqueConstraint(fields=('validity', 'short_name'), name='unique_short_name_per_validity_break'),
),
]
# Generated by Django 4.2.9 on 2024-01-09 15:08
import colorfield.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('chronos', '0016_lessonevent'),
]
operations = [
migrations.AlterModelManagers(
name='absencereason',
managers=[
],
),
migrations.AlterModelManagers(
name='subject',
managers=[
],
),
migrations.AlterModelManagers(
name='supervisionarea',
managers=[
],
),
migrations.RemoveConstraint(
model_name='absencereason',
name='unique_short_name_per_site_absence_reason',
),
migrations.RemoveConstraint(
model_name='break',
name='unique_short_name_per_site_break',
),
migrations.RemoveConstraint(
model_name='subject',
name='unique_short_name_per_site_subject',
),
migrations.RemoveConstraint(
model_name='supervisionarea',
name='unique_short_name_per_site_supervision_area',
),
] + [
migrations.RunSQL(
f"ALTER TABLE chronos_{model_name} drop column if exists site_id;"
) for model_name in
[
"absence",
"absencereason",
"automaticplan",
"break",
"event",
"exam",
"extralesson",
"holiday",
"lesson",
"lessonperiod",
"lessonsubstitution",
"subject",
"supervision",
"supervisionarea",
"supervisionsubstitution",
"timeperiod",
"validityrange"
]
] + [
migrations.AlterField(
model_name='absence',
name='comment',
field=models.TextField(blank=True, default='', verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='absencereason',
name='name',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Name'),
preserve_default=False,
),
migrations.AlterField(
model_name='absencereason',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='event',
name='title',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Title'),
preserve_default=False,
),
migrations.AlterField(
model_name='extralesson',
name='comment',
field=models.CharField(blank=True, default='', max_length=255, verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='holiday',
name='comments',
field=models.TextField(blank=True, default='', verbose_name='Comments'),
preserve_default=False,
),
migrations.AlterField(
model_name='lessonsubstitution',
name='comment',
field=models.TextField(blank=True, default='', verbose_name='Comment'),
preserve_default=False,
),
migrations.AlterField(
model_name='subject',
name='colour_bg',
field=colorfield.fields.ColorField(blank=True, default='', image_field=None, max_length=25, samples=None, verbose_name='Background colour'),
),
migrations.AlterField(
model_name='subject',
name='colour_fg',
field=colorfield.fields.ColorField(blank=True, default='', image_field=None, max_length=25, samples=None, verbose_name='Foreground colour'),
),
migrations.AlterField(
model_name='subject',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='supervisionarea',
name='colour_bg',
field=colorfield.fields.ColorField(default='#FFFFFF', image_field=None, max_length=25, samples=None),
),
migrations.AlterField(
model_name='supervisionarea',
name='colour_fg',
field=colorfield.fields.ColorField(default='#000000', image_field=None, max_length=25, samples=None),
),
migrations.AlterField(
model_name='supervisionarea',
name='short_name',
field=models.CharField(max_length=255, unique=True, verbose_name='Short name'),
),
migrations.AlterField(
model_name='timeperiod',
name='weekday',
field=models.PositiveSmallIntegerField(choices=[(0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday')], verbose_name='Week day'),
),
migrations.AddConstraint(
model_name='break',
constraint=models.UniqueConstraint(fields=('validity', 'short_name'), name='unique_short_name_per_validity_break'),
),
]
from datetime import date, time
from django.db import transaction
from django.db.models.signals import m2m_changed, post_delete, post_save, pre_delete
from django.test import TransactionTestCase, override_settings
import pytest
from aleksis.apps.chronos.models import (
Event,
ExtraLesson,
Lesson,
LessonPeriod,
LessonSubstitution,
Subject,
SupervisionSubstitution,
TimePeriod,
)
from aleksis.apps.chronos.util.change_tracker import TimetableDataChangeTracker
from aleksis.core.models import Group, Person, Room, SchoolTerm
pytestmark = pytest.mark.django_db
@override_settings(CELERY_BROKER_URL="memory://localhost//")
class NotificationTests(TransactionTestCase):
serialized_rollback = True
def setUp(self):
self.school_term = SchoolTerm.objects.create(
date_start=date(2020, 1, 1), date_end=date(2020, 12, 31)
)
self.teacher_a = Person.objects.create(
first_name="Teacher", last_name="A", short_name="A", email="test1@example.org"
)
self.teacher_b = Person.objects.create(
first_name="Teacher", last_name="B", short_name="B", email="test2@example.org"
)
self.student_a = Person.objects.create(
first_name="Student", last_name="A", email="test3@example.org"
)
self.student_b = Person.objects.create(
first_name="Student", last_name="B", email="test4@example.org"
)
self.student_c = Person.objects.create(
first_name="Student", last_name="C", email="test5@example.org"
)
self.student_d = Person.objects.create(
first_name="Student", last_name="D", email="test6@example.org"
)
self.student_e = Person.objects.create(
first_name="Student", last_name="E", email="test7@example.org"
)
self.group_a = Group.objects.create(
name="Class 9a", short_name="9a", school_term=self.school_term
)
self.group_a.owners.add(self.teacher_a)
self.group_a.members.add(self.student_a, self.student_b, self.student_c)
self.group_b = Group.objects.create(
name="Class 9b", short_name="9b", school_term=self.school_term
)
self.group_b.owners.add(self.teacher_b)
self.group_b.members.add(self.student_c, self.student_d, self.student_e)
self.time_period_a = TimePeriod.objects.create(
weekday=0, period=1, time_start=time(8, 0), time_end=time(9, 0)
)
self.time_period_b = TimePeriod.objects.create(
weekday=1, period=2, time_start=time(9, 0), time_end=time(10, 0)
)
self.subject_a = Subject.objects.create(name="English", short_name="En")
self.subject_b = Subject.objects.create(name="Deutsch", short_name="De")
self.room_a = Room.objects.create(short_name="004", name="Room 0.04")
self.room_b = Room.objects.create(short_name="005", name="Room 0.05")
self.lesson = Lesson.objects.create(subject=self.subject_a)
self.lesson.groups.set([self.group_a])
self.lesson.teachers.set([self.teacher_a])
self.period_1 = LessonPeriod.objects.create(
period=self.time_period_a, room=self.room_a, lesson=self.lesson
)
self.period_2 = LessonPeriod.objects.create(
period=self.time_period_b, room=self.room_a, lesson=self.lesson
)
def _parse_receivers(self, receivers):
return [str(r[1]) for r in receivers]
def test_signal_registration(self):
for model in [Event, LessonSubstitution, ExtraLesson, SupervisionSubstitution]:
assert "TimetableDataChangeTracker._handle_save" not in "".join(
[str(r) for r in post_save._live_receivers(model)]
)
for model in [Event, LessonSubstitution, ExtraLesson, SupervisionSubstitution]:
assert "TimetableDataChangeTracker._handle_delete" not in "".join(
[str(r) for r in post_delete._live_receivers(model)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(LessonSubstitution.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(Event.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(Event.groups.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(ExtraLesson.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(ExtraLesson.groups.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" not in "".join(
[str(r) for r in m2m_changed._live_receivers(ExtraLesson.groups.through)]
)
with transaction.atomic():
tracker = TimetableDataChangeTracker()
for model in [Event, LessonSubstitution, ExtraLesson, SupervisionSubstitution]:
assert "TimetableDataChangeTracker._handle_save" in "".join(
[str(r) for r in post_save._live_receivers(model)]
)
for model in [Event, LessonSubstitution, ExtraLesson, SupervisionSubstitution]:
assert "TimetableDataChangeTracker._handle_delete" in "".join(
[str(r) for r in pre_delete._live_receivers(model)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" in "".join(
[str(r) for r in m2m_changed._live_receivers(LessonSubstitution.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" in "".join(
[str(r) for r in m2m_changed._live_receivers(Event.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" in "".join(
[str(r) for r in m2m_changed._live_receivers(Event.groups.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" in "".join(
[str(r) for r in m2m_changed._live_receivers(ExtraLesson.teachers.through)]
)
assert "TimetableDataChangeTracker._handle_m2m_changed" in "".join(
[str(r) for r in m2m_changed._live_receivers(ExtraLesson.groups.through)]
)
def test_outside_transaction(self):
with pytest.raises(RuntimeError):
TimetableDataChangeTracker()
def test_create_detection(self):
with transaction.atomic():
tracker = TimetableDataChangeTracker()
assert not tracker.changes
lesson_substitution = LessonSubstitution.objects.create(
week=20, year=2020, lesson_period=self.period_1, cancelled=True
)
assert tracker.changes
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert change.created
assert not change.deleted
assert not change.changed_fields
lesson_substitution.cancelled = False
lesson_substitution.subject = self.subject_b
lesson_substitution.save()
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert change.created
assert not change.deleted
assert change.changed_fields
def test_change_detection(self):
with transaction.atomic():
lesson_substitution = LessonSubstitution.objects.create(
week=20, year=2020, lesson_period=self.period_1, cancelled=True
)
tracker = TimetableDataChangeTracker()
assert not tracker.changes
lesson_substitution.cancelled = False
lesson_substitution.subject = self.subject_b
lesson_substitution.save()
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert not change.created
assert not change.deleted
assert set(change.changed_fields.keys()) == {"cancelled", "subject_id"}
assert change.changed_fields["cancelled"]
assert change.changed_fields["subject_id"] is None
lesson_substitution.teachers.add(self.teacher_a)
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert not change.created
assert not change.deleted
assert set(change.changed_fields.keys()) == {"cancelled", "subject_id", "teachers"}
assert change.changed_fields["teachers"] == []
lesson_substitution.teachers.remove(self.teacher_a)
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert not change.created
assert not change.deleted
assert set(change.changed_fields.keys()) == {"cancelled", "subject_id", "teachers"}
assert change.changed_fields["teachers"] == []
with transaction.atomic():
lesson_substitution.teachers.add(self.teacher_a)
tracker = TimetableDataChangeTracker()
lesson_substitution.teachers.remove(self.teacher_a)
assert len(tracker.changes) == 1
change = tracker.changes[tracker.get_instance_key(lesson_substitution)]
assert change.instance == lesson_substitution
assert not change.created
assert not change.deleted
assert set(change.changed_fields.keys()) == {"teachers"}
assert change.changed_fields["teachers"] == [self.teacher_a]
def test_delete_detected(self):
lesson_substitution = LessonSubstitution.objects.create(
week=20, year=2020, lesson_period=self.period_1, cancelled=True
)
with transaction.atomic():
tracker = TimetableDataChangeTracker()
pk = lesson_substitution.pk
assert not tracker.changes
lesson_substitution.delete()
assert len(tracker.changes) == 1
change = tracker.changes[f"lessonsubstitution_{pk}"]
assert change.instance == lesson_substitution
assert not change.created
assert change.deleted
assert not change.changed_fields
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