Skip to content
Snippets Groups Projects
Verified Commit 2b83a633 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[Reformat} Run isort and black

parent 874b76b4
No related branches found
No related tags found
No related merge requests found
import pkg_resources import pkg_resources
try: try:
__version__ = pkg_resources.get_distribution('BiscuIT-App-Alsijil').version __version__ = pkg_resources.get_distribution("BiscuIT-App-Alsijil").version
except Exception: except Exception:
__version__ = 'unknown' __version__ = "unknown"
default_app_config = 'biscuit.apps.alsijil.apps.AlsijilConfig' default_app_config = "biscuit.apps.alsijil.apps.AlsijilConfig"
...@@ -2,5 +2,5 @@ from biscuit.core.util.apps import AppConfig ...@@ -2,5 +2,5 @@ from biscuit.core.util.apps import AppConfig
class AlsijilConfig(AppConfig): class AlsijilConfig(AppConfig):
name = 'biscuit.apps.alsijil' name = "biscuit.apps.alsijil"
verbose_name = 'BiscuIT - Alsijil (Class register)' verbose_name = "BiscuIT - Alsijil (Class register)"
from datetime import datetime
from django import forms from django import forms
from django.db.models import Count from django.db.models import Count
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django_select2.forms import Select2Widget from django_select2.forms import Select2Widget
from datetime import datetime
from biscuit.apps.chronos.models import Room from biscuit.apps.chronos.models import Room
from biscuit.core.models import Group, Person from biscuit.core.models import Group, Person
...@@ -13,54 +15,75 @@ from .models import LessonDocumentation, PersonalNote, PersonalNoteFilter ...@@ -13,54 +15,75 @@ from .models import LessonDocumentation, PersonalNote, PersonalNoteFilter
class LessonDocumentationForm(forms.ModelForm): class LessonDocumentationForm(forms.ModelForm):
class Meta: class Meta:
model = LessonDocumentation model = LessonDocumentation
fields = ['topic', 'homework'] fields = ["topic", "homework"]
class PersonalNoteForm(forms.ModelForm): class PersonalNoteForm(forms.ModelForm):
class Meta: class Meta:
model = PersonalNote model = PersonalNote
fields = ['absent', 'late', 'excused', 'remarks'] fields = ["absent", "late", "excused", "remarks"]
person_name = forms.CharField(disabled=True) person_name = forms.CharField(disabled=True)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['person_name'].widget.attrs.update( self.fields["person_name"].widget.attrs.update(
{'class': 'alsijil-lesson-personal-note-name'}) {"class": "alsijil-lesson-personal-note-name"}
)
if self.instance and getattr(self.instance, 'person', None): if self.instance and getattr(self.instance, "person", None):
self.fields['person_name'].initial = str(self.instance.person) self.fields["person_name"].initial = str(self.instance.person)
class SelectForm(forms.Form): class SelectForm(forms.Form):
group = forms.ModelChoiceField( group = forms.ModelChoiceField(
queryset=Group.objects.annotate(lessons_count=Count('lessons')).filter(lessons_count__gt=0), queryset=Group.objects.annotate(lessons_count=Count("lessons")).filter(
label=_('Group'), required=False, widget=Select2Widget) lessons_count__gt=0
),
label=_("Group"),
required=False,
widget=Select2Widget,
)
teacher = forms.ModelChoiceField( teacher = forms.ModelChoiceField(
queryset=Person.objects.annotate(lessons_count=Count( queryset=Person.objects.annotate(
'lessons_as_teacher')).filter(lessons_count__gt=0), lessons_count=Count("lessons_as_teacher")
label=_('Teacher'), required=False, widget=Select2Widget) ).filter(lessons_count__gt=0),
label=_("Teacher"),
required=False,
widget=Select2Widget,
)
room = forms.ModelChoiceField( room = forms.ModelChoiceField(
queryset=Room.objects.annotate(lessons_count=Count( queryset=Room.objects.annotate(lessons_count=Count("lesson_periods")).filter(
'lesson_periods')).filter(lessons_count__gt=0), lessons_count__gt=0
label=_('Room'), required=False, widget=Select2Widget) ),
label=_("Room"),
required=False,
widget=Select2Widget,
)
PersonalNoteFormSet = forms.modelformset_factory( PersonalNoteFormSet = forms.modelformset_factory(
PersonalNote, form=PersonalNoteForm, max_num=0, extra=0) PersonalNote, form=PersonalNoteForm, max_num=0, extra=0
)
class RegisterAbsenceForm(forms.Form): class RegisterAbsenceForm(forms.Form):
date_start = forms.DateField(label=_('Start date'), widget=forms.SelectDateWidget, initial=datetime.today) date_start = forms.DateField(
date_end = forms.DateField(label=_('End date'), widget=forms.SelectDateWidget, initial=datetime.today) label=_("Start date"), widget=forms.SelectDateWidget, initial=datetime.today
from_period = forms.IntegerField(label=_('From period'), initial=0, min_value=0) )
person = forms.ModelChoiceField(label=_('Person'), queryset=Person.objects.all(), widget=Select2Widget) date_end = forms.DateField(
absent = forms.BooleanField(label=_('Absent'), initial=True, required=False) label=_("End date"), widget=forms.SelectDateWidget, initial=datetime.today
excused = forms.BooleanField(label=_('Excused'), initial=True, required=False) )
remarks = forms.CharField(label=_('Remarks'), max_length=30, required=False) from_period = forms.IntegerField(label=_("From period"), initial=0, min_value=0)
person = forms.ModelChoiceField(
label=_("Person"), queryset=Person.objects.all(), widget=Select2Widget
)
absent = forms.BooleanField(label=_("Absent"), initial=True, required=False)
excused = forms.BooleanField(label=_("Excused"), initial=True, required=False)
remarks = forms.CharField(label=_("Remarks"), max_length=30, required=False)
class PersonalNoteFilterForm(forms.ModelForm): class PersonalNoteFilterForm(forms.ModelForm):
class Meta: class Meta:
model = PersonalNoteFilter model = PersonalNoteFilter
fields = ['identifier', 'description', 'regex'] fields = ["identifier", "description", "regex"]
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
MENUS = { MENUS = {
'NAV_MENU_CORE': [ "NAV_MENU_CORE": [
{ {
'name': _('Class register'), "name": _("Class register"),
'url': '#', "url": "#",
'root': True, "root": True,
'validators': ['menu_generator.validators.is_authenticated', 'biscuit.core.util.core_helpers.has_person'], "validators": [
'submenu': [ "menu_generator.validators.is_authenticated",
"biscuit.core.util.core_helpers.has_person",
],
"submenu": [
{ {
'name': _('Current lesson'), "name": _("Current lesson"),
'url': 'lesson', "url": "lesson",
'validators': ['menu_generator.validators.is_authenticated'] "validators": ["menu_generator.validators.is_authenticated"],
}, },
{ {
'name': _('Current week'), "name": _("Current week"),
'url': 'week_view', "url": "week_view",
'validators': ['menu_generator.validators.is_authenticated'] "validators": ["menu_generator.validators.is_authenticated"],
}, },
{ {
'name': _('Register absence'), "name": _("Register absence"),
'url': 'register_absence', "url": "register_absence",
'validators': ['menu_generator.validators.is_superuser'] "validators": ["menu_generator.validators.is_superuser"],
}, },
{ {
'name': _('Personal note filters'), "name": _("Personal note filters"),
'url': 'list_personal_note_filters', "url": "list_personal_note_filters",
'validators': ['menu_generator.validators.is_superuser'] "validators": ["menu_generator.validators.is_superuser"],
} },
] ],
} }
] ]
} }
# Generated by Django 2.2.5 on 2019-09-03 18:30 # Generated by Django 2.2.5 on 2019-09-03 18:30
import biscuit.core.util.core_helpers
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
import biscuit.core.util.core_helpers
class Migration(migrations.Migration): class Migration(migrations.Migration):
...@@ -10,42 +11,114 @@ class Migration(migrations.Migration): ...@@ -10,42 +11,114 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('chronos', '0001_initial'), ("chronos", "0001_initial"),
('core', '0001_initial'), ("core", "0001_initial"),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='PersonalNote', name="PersonalNote",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('week', models.IntegerField()), "id",
('absent', models.BooleanField(default=False)), models.AutoField(
('late', models.IntegerField(default=0)), auto_created=True,
('excused', models.BooleanField(default=False)), primary_key=True,
('remarks', models.CharField(blank=True, max_length=200)), serialize=False,
('lesson_period', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='chronos.LessonPeriod')), verbose_name="ID",
('person', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='personal_notes', to='core.Person')), ),
('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')), ),
("week", models.IntegerField()),
("absent", models.BooleanField(default=False)),
("late", models.IntegerField(default=0)),
("excused", models.BooleanField(default=False)),
("remarks", models.CharField(blank=True, max_length=200)),
(
"lesson_period",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="chronos.LessonPeriod",
),
),
(
"person",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="personal_notes",
to="core.Person",
),
),
(
"school",
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
to="core.School",
),
),
], ],
options={ options={
'ordering': ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday', 'lesson_period__period__period', 'person__last_name', 'person__first_name'], "ordering": [
'unique_together': {('school', 'lesson_period', 'week', 'person')}, "lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
"person__last_name",
"person__first_name",
],
"unique_together": {("school", "lesson_period", "week", "person")},
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='LessonDocumentation', name="LessonDocumentation",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('week', models.IntegerField()), "id",
('topic', models.CharField(blank=True, max_length=200, verbose_name='Lesson topic')), models.AutoField(
('homework', models.CharField(blank=True, max_length=200, verbose_name='Homework')), auto_created=True,
('lesson_period', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documentations', to='chronos.LessonPeriod')), primary_key=True,
('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')), serialize=False,
verbose_name="ID",
),
),
("week", models.IntegerField()),
(
"topic",
models.CharField(
blank=True, max_length=200, verbose_name="Lesson topic"
),
),
(
"homework",
models.CharField(
blank=True, max_length=200, verbose_name="Homework"
),
),
(
"lesson_period",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="documentations",
to="chronos.LessonPeriod",
),
),
(
"school",
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
to="core.School",
),
),
], ],
options={ options={
'ordering': ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday', 'lesson_period__period__period'], "ordering": [
'unique_together': {('school', 'lesson_period', 'week')}, "lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
],
"unique_together": {("school", "lesson_period", "week")},
}, },
), ),
] ]
# Generated by Django 2.2.5 on 2019-11-20 14:21 # Generated by Django 2.2.5 on 2019-11-20 14:21
import django.db.models.deletion
from django.db import migrations, models
import biscuit.apps.alsijil.models import biscuit.apps.alsijil.models
import biscuit.core.util.core_helpers import biscuit.core.util.core_helpers
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('core', '0003_school_logo'), ("core", "0003_school_logo"),
('alsijil', '0001_initial'), ("alsijil", "0001_initial"),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='PersonalNoteFilter', name="PersonalNoteFilter",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('identifier', models.CharField(max_length=30, validators=[biscuit.apps.alsijil.models.isidentifier], verbose_name='Identifier')), "id",
('description', models.CharField(blank=True, max_length=60, verbose_name='Description')), models.AutoField(
('regex', models.CharField(max_length=100, verbose_name='Match expression')), auto_created=True,
('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"identifier",
models.CharField(
max_length=30,
validators=[biscuit.apps.alsijil.models.isidentifier],
verbose_name="Identifier",
),
),
(
"description",
models.CharField(
blank=True, max_length=60, verbose_name="Description"
),
),
(
"regex",
models.CharField(max_length=100, verbose_name="Match expression"),
),
(
"school",
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
to="core.School",
),
),
], ],
options={ options={
'ordering': ['identifier'], "ordering": ["identifier"],
'unique_together': {('school', 'regex'), ('school', 'description'), ('school', 'identifier')}, "unique_together": {
("school", "regex"),
("school", "description"),
("school", "identifier"),
},
}, },
), ),
] ]
...@@ -10,7 +10,14 @@ from .models import PersonalNote ...@@ -10,7 +10,14 @@ from .models import PersonalNote
@Person.method @Person.method
def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excused: bool = False, remarks: str = ''): def mark_absent(
self,
day: date,
from_period: int = 0,
absent: bool = True,
excused: bool = False,
remarks: str = "",
):
""" Mark a person absent for all lessons in a day, optionally starting with """ Mark a person absent for all lessons in a day, optionally starting with
a selected period number. a selected period number.
...@@ -27,9 +34,7 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu ...@@ -27,9 +34,7 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu
wanted_week = CalendarWeek.from_date(day) wanted_week = CalendarWeek.from_date(day)
# Get all lessons of this person on the specified day # Get all lessons of this person on the specified day
lesson_periods = self.lesson_periods_as_participant.on_day( lesson_periods = self.lesson_periods_as_participant.on_day(day).filter(
day
).filter(
period__period__gte=from_period period__period__gte=from_period
) )
...@@ -39,15 +44,12 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu ...@@ -39,15 +44,12 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu
person=self, person=self,
lesson_period=lesson_period, lesson_period=lesson_period,
week=wanted_week.week, week=wanted_week.week,
defaults={ defaults={"absent": absent, "excused": excused},
'absent': absent,
'excused': excused
}
) )
if remarks: if remarks:
if personal_note.remarks: if personal_note.remarks:
personal_note.remarks += '; %s' % remarks personal_note.remarks += "; %s" % remarks
else: else:
personal_note.remarks = remarks personal_note.remarks = remarks
personal_note.save() personal_note.save()
...@@ -69,22 +71,25 @@ def get_personal_notes(self, wanted_week: CalendarWeek): ...@@ -69,22 +71,25 @@ def get_personal_notes(self, wanted_week: CalendarWeek):
# Find all persons in the associated groups that do not yet have a personal note for this lesson # Find all persons in the associated groups that do not yet have a personal note for this lesson
missing_persons = Person.objects.annotate( missing_persons = Person.objects.annotate(
no_personal_notes=~Exists(PersonalNote.objects.filter( no_personal_notes=~Exists(
week=wanted_week.week, PersonalNote.objects.filter(
lesson_period=self, week=wanted_week.week, lesson_period=self, person__pk=OuterRef("pk")
person__pk=OuterRef('pk') )
)) )
).filter( ).filter(
member_of__in=Group.objects.filter(pk__in=self.lesson.groups.all()), member_of__in=Group.objects.filter(pk__in=self.lesson.groups.all()),
is_active=True, is_active=True,
no_personal_notes=True no_personal_notes=True,
) )
# Create all missing personal notes # Create all missing personal notes
PersonalNote.objects.bulk_create([ PersonalNote.objects.bulk_create(
PersonalNote(person=person, lesson_period=self, [
week=wanted_week.week) for person in missing_persons PersonalNote(person=person, lesson_period=self, week=wanted_week.week)
]) for person in missing_persons
]
)
return PersonalNote.objects.select_related('person').filter( return PersonalNote.objects.select_related("person").filter(
lesson_period=self, week=wanted_week.week) lesson_period=self, week=wanted_week.week
)
...@@ -13,10 +13,14 @@ class PersonalNote(models.Model): ...@@ -13,10 +13,14 @@ class PersonalNote(models.Model):
absences, excuses and remarks about a student in a single lesson period. absences, excuses and remarks about a student in a single lesson period.
""" """
person = models.ForeignKey('core.Person', models.CASCADE, related_name='personal_notes') person = models.ForeignKey(
"core.Person", models.CASCADE, related_name="personal_notes"
)
week = models.IntegerField() week = models.IntegerField()
lesson_period = models.ForeignKey('chronos.LessonPeriod', models.CASCADE, related_name='personal_notes') lesson_period = models.ForeignKey(
"chronos.LessonPeriod", models.CASCADE, related_name="personal_notes"
)
absent = models.BooleanField(default=False) absent = models.BooleanField(default=False)
late = models.IntegerField(default=0) late = models.IntegerField(default=0)
...@@ -25,9 +29,15 @@ class PersonalNote(models.Model): ...@@ -25,9 +29,15 @@ class PersonalNote(models.Model):
remarks = models.CharField(max_length=200, blank=True) remarks = models.CharField(max_length=200, blank=True)
class Meta: class Meta:
unique_together = [['lesson_period', 'week', 'person']] unique_together = [["lesson_period", "week", "person"]]
ordering = ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday', ordering = [
'lesson_period__period__period', 'person__last_name', 'person__first_name'] "lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
"person__last_name",
"person__first_name",
]
class LessonDocumentation(CRUDMixin): class LessonDocumentation(CRUDMixin):
...@@ -37,27 +47,38 @@ class LessonDocumentation(CRUDMixin): ...@@ -37,27 +47,38 @@ class LessonDocumentation(CRUDMixin):
week = models.IntegerField() week = models.IntegerField()
lesson_period = models.ForeignKey( lesson_period = models.ForeignKey(
'chronos.LessonPeriod', models.CASCADE, related_name='documentations') "chronos.LessonPeriod", models.CASCADE, related_name="documentations"
)
topic = models.CharField(verbose_name=_('Lesson topic'), max_length=200, blank=True) topic = models.CharField(verbose_name=_("Lesson topic"), max_length=200, blank=True)
homework = models.CharField(verbose_name=_('Homework'), max_length=200, blank=True) homework = models.CharField(verbose_name=_("Homework"), max_length=200, blank=True)
class Meta: class Meta:
unique_together = [['lesson_period', 'week']] unique_together = [["lesson_period", "week"]]
ordering = ['lesson_period__lesson__date_start', 'week', ordering = [
'lesson_period__period__weekday', 'lesson_period__period__period'] "lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
]
class PersonalNoteFilter(models.Model): class PersonalNoteFilter(models.Model):
""" A filter definition that can generate statistics on personal note texts. """ """ A filter definition that can generate statistics on personal note texts. """
identifier = models.CharField(verbose_name=_('Identifier'), max_length=30, identifier = models.CharField(
validators=[isidentifier], unique=True) verbose_name=_("Identifier"),
description = models.CharField(verbose_name=_('Description'), max_length=60, max_length=30,
blank=True, unique=True) validators=[isidentifier],
unique=True,
)
description = models.CharField(
verbose_name=_("Description"), max_length=60, blank=True, unique=True
)
regex = models.CharField(verbose_name=_('Match expression'), max_length=100, regex = models.CharField(
unique=True) verbose_name=_("Match expression"), max_length=100, unique=True
)
class Meta: class Meta:
ordering = ['identifier'] ordering = ["identifier"]
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
import django_tables2 as tables import django_tables2 as tables
from django_tables2.utils import A from django_tables2.utils import A
class PersonalNoteFilterTable(tables.Table): class PersonalNoteFilterTable(tables.Table):
class Meta: class Meta:
attrs = {'class': 'table table-striped table-bordered table-hover table-responsive-xl'} attrs = {
"class": "table table-striped table-bordered table-hover table-responsive-xl"
}
identifier = tables.Column() identifier = tables.Column()
description = tables.Column() description = tables.Column()
regex = tables.Column() regex = tables.Column()
edit_filter = tables.LinkColumn( edit_filter = tables.LinkColumn(
'edit_personal_note_filter', args=[A('id')], text=_('Edit')) "edit_personal_note_filter", args=[A("id")], text=_("Edit")
)
...@@ -2,24 +2,37 @@ from django.urls import path ...@@ -2,24 +2,37 @@ from django.urls import path
from . import views from . import views
urlpatterns = [ urlpatterns = [
path('lesson', views.lesson, name='lesson'), path("lesson", views.lesson, name="lesson"),
path('lesson/<int:year>/<int:week>/<int:period_id>', views.lesson, path(
name='lesson_by_week_and_period'), "lesson/<int:year>/<int:week>/<int:period_id>",
path('week', views.week_view, name='week_view'), views.lesson,
path('week/<int:year>/<int:week>', views.week_view, name="lesson_by_week_and_period",
name='week_view_by_week'), ),
path('print/group/<int:id_>', views.full_register_group, path("week", views.week_view, name="week_view"),
name='full_register_group'), path("week/<int:year>/<int:week>", views.week_view, name="week_view_by_week"),
path('absence/new', views.register_absence, path(
name='register_absence'), "print/group/<int:id_>", views.full_register_group, name="full_register_group"
path('filters/list', views.list_personal_note_filters, ),
name='list_personal_note_filters'), path("absence/new", views.register_absence, name="register_absence"),
path('filters/create', views.edit_personal_note_filter, path(
name='create_personal_note_filter'), "filters/list",
path('filters/edit/<int:id>', views.edit_personal_note_filter, views.list_personal_note_filters,
name='edit_personal_note_filter'), name="list_personal_note_filters",
path('filters/delete/<int:id_>', views.delete_personal_note_filter, ),
name='delete_personal_note_filter') path(
"filters/create",
views.edit_personal_note_filter,
name="create_personal_note_filter",
),
path(
"filters/edit/<int:id>",
views.edit_personal_note_filter,
name="edit_personal_note_filter",
),
path(
"filters/delete/<int:id_>",
views.delete_personal_note_filter,
name="delete_personal_note_filter",
),
] ]
This diff is collapsed.
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