From bbfa780288951673de661fafd9a84a7af57732c9 Mon Sep 17 00:00:00 2001 From: magicfelix <felix@felix-zauberer.de> Date: Tue, 17 Sep 2024 10:53:29 +0200 Subject: [PATCH] Implement models --- aleksis/apps/maka/migrations/0001_initial.py | 248 +++++++++++++++++++ aleksis/apps/maka/models/__init__.py | 115 +++++++++ 2 files changed, 363 insertions(+) create mode 100644 aleksis/apps/maka/migrations/0001_initial.py diff --git a/aleksis/apps/maka/migrations/0001_initial.py b/aleksis/apps/maka/migrations/0001_initial.py new file mode 100644 index 0000000..b717138 --- /dev/null +++ b/aleksis/apps/maka/migrations/0001_initial.py @@ -0,0 +1,248 @@ +# Generated by Django 5.1.1 on 2024-09-17 17:15 + +import colorfield.fields +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ("core", "0065_calendarevent_update_timezone_constraints"), + ] + + operations = [ + migrations.CreateModel( + name="EffortType", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ( + "managed_by_app_label", + models.CharField( + blank=True, + editable=False, + max_length=255, + verbose_name="App label of app responsible for managing this instance", + ), + ), + ("extended_data", models.JSONField(default=dict, editable=False)), + ("name", models.CharField(max_length=255, verbose_name="Name")), + ( + "color", + colorfield.fields.ColorField( + blank=True, + default="", + image_field=None, + max_length=25, + samples=None, + verbose_name="Color", + ), + ), + ( + "icon", + models.CharField( + blank=True, choices=[("", "")], max_length=50, verbose_name="Icon" + ), + ), + ("default", models.BooleanField(verbose_name="Default")), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="GradeSet", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ( + "managed_by_app_label", + models.CharField( + blank=True, + editable=False, + max_length=255, + verbose_name="App label of app responsible for managing this instance", + ), + ), + ("extended_data", models.JSONField(default=dict, editable=False)), + ("name", models.CharField(max_length=255, unique=True, verbose_name="Name")), + ( + "groups", + models.ManyToManyField( + blank=True, + null=True, + related_name="grade_sets", + to="core.group", + verbose_name="Groups using this grade set", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="GradeChoice", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ( + "managed_by_app_label", + models.CharField( + blank=True, + editable=False, + max_length=255, + verbose_name="App label of app responsible for managing this instance", + ), + ), + ("extended_data", models.JSONField(default=dict, editable=False)), + ("name", models.CharField(max_length=255, verbose_name="Name")), + ("value", models.CharField(max_length=255, verbose_name="Value")), + ("order", models.PositiveSmallIntegerField(verbose_name="Order")), + ( + "grade_set", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="grade_choices", + to="maka.gradeset", + verbose_name="Grade set", + ), + ), + ], + options={ + "verbose_name": "Grade choice", + "verbose_name_plural": "Grade choices", + }, + ), + migrations.CreateModel( + name="Effort", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ( + "managed_by_app_label", + models.CharField( + blank=True, + editable=False, + max_length=255, + verbose_name="App label of app responsible for managing this instance", + ), + ), + ("extended_data", models.JSONField(default=dict, editable=False)), + ("name", models.CharField(max_length=255, verbose_name="Name")), + ("weight", models.PositiveSmallIntegerField(default=1, verbose_name="Weight")), + ( + "grade_set", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="+", + to="maka.gradeset", + verbose_name="Grade set", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="efforts", + to="core.group", + verbose_name="Group", + ), + ), + ( + "effort_type", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="efforts", + to="maka.efforttype", + verbose_name="Effort type", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="Grade", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ( + "managed_by_app_label", + models.CharField( + blank=True, + editable=False, + max_length=255, + verbose_name="App label of app responsible for managing this instance", + ), + ), + ("extended_data", models.JSONField(default=dict, editable=False)), + ( + "person", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="grades", + to="core.person", + verbose_name="Person", + ), + ), + ( + "grade", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="+", + to="maka.gradechoice", + verbose_name="Grade", + ), + ), + ( + "effort", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="grades", + to="maka.effort", + verbose_name="Effort", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.AddConstraint( + model_name="gradechoice", + constraint=models.UniqueConstraint( + fields=("grade_set", "name"), name="unique_gradeset_name" + ), + ), + migrations.AddConstraint( + model_name="gradechoice", + constraint=models.UniqueConstraint( + fields=("grade_set", "value"), name="unique_gradeset_value" + ), + ), + ] diff --git a/aleksis/apps/maka/models/__init__.py b/aleksis/apps/maka/models/__init__.py index e69de29..cd729e0 100644 --- a/aleksis/apps/maka/models/__init__.py +++ b/aleksis/apps/maka/models/__init__.py @@ -0,0 +1,115 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from colorfield.fields import ColorField + +from aleksis.core.mixins import ExtensibleModel +from aleksis.core.models import Group, Person +from aleksis.core.util.model_helpers import ICONS + + +class GradeSet(ExtensibleModel): + """Set of grades.""" + name = models.CharField(verbose_name=_("Name"), max_length=255, unique=True) + groups = models.ManyToManyField( + "core.Group", + verbose_name=_("Groups using this grade set"), + blank=True, + null=True, + related_name="grade_sets", + ) + + +class GradeChoice(ExtensibleModel): + """Single grade choice in a set of grades.""" + grade_set = models.ForeignKey( + GradeSet, + on_delete=models.CASCADE, + verbose_name=_("Grade set"), + related_name="grade_choices", + ) + name = models.CharField(verbose_name=_("Name"), max_length=255) + value = models.CharField(verbose_name=_("Value"), max_length=255) + order = models.PositiveSmallIntegerField(verbose_name=_("Order")) + + class Meta: + verbose_name = _("Grade choice") + verbose_name_plural = _("Grade choices") + constraints = [ + models.UniqueConstraint( + fields=["grade_set", "name"], + name="unique_gradeset_name", + ), + models.UniqueConstraint( + fields=["grade_set", "value"], + name="unique_gradeset_value", + ), + ] + + +class EffortType(ExtensibleModel): + """Abstract type that can be rated.""" + name = models.CharField(verbose_name=_("Name"), max_length=255) + color = ColorField(verbose_name=_("Color"), blank=True) + icon = models.CharField( + max_length=50, blank=True, choices=[("", "")] + ICONS, verbose_name=_("Icon") + ) + default = models.BooleanField(verbose_name=_("Default")) + + def save(self, *args, **kwargs): + if self.default: + # select all other active items + qs = EffortType.objects.filter(default=True) + # except self (if self already exists) + if self.pk: + qs = qs.exclude(pk=self.pk) + # and deactive them + qs.update(default=False) + + super().save(*args, **kwargs) + + +class Effort(ExtensibleModel): + """Concrete occurence of a effort type.""" + name = models.CharField(verbose_name=_("Name"), max_length=255) + weight = models.PositiveSmallIntegerField(verbose_name=_("Weight"), default=1) + effort_type = models.ForeignKey( + EffortType, + on_delete=models.CASCADE, + verbose_name=_("Effort type"), + related_name="efforts", + ) + group = models.ForeignKey( + Group, + on_delete=models.PROTECT, + verbose_name=_("Group"), + related_name="efforts", + ) + grade_set = models.ForeignKey( + GradeSet, + on_delete=models.CASCADE, + verbose_name=_("Grade set"), + related_name="+", + ) + + +class Grade(ExtensibleModel): + """Grade of a person for a effort.""" + person = models.ForeignKey( + Person, + on_delete=models.CASCADE, + verbose_name=_("Person"), + related_name="grades", + ) + grade = models.ForeignKey( + GradeChoice, + on_delete=models.CASCADE, + verbose_name=_("Grade"), + related_name="+", + ) + effort = models.ForeignKey( + Effort, + on_delete=models.CASCADE, + verbose_name=_("Effort"), + related_name="grades", + ) -- GitLab