diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c9a6fd37ea168680978ecc71b7b181c1fffe224e --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# pyenv +.python-version + +# Environments +.env +.venv +env/ +venv/ +ENV/ + +# Editors +*~ +DEADJOE +\#*# + +# Database +db.sqlite3 diff --git a/biscuit/apps/alsijil/forms.py b/biscuit/apps/alsijil/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..b7b29a28f5a12f8806cbe50c4f1572e914cf5b8d --- /dev/null +++ b/biscuit/apps/alsijil/forms.py @@ -0,0 +1,29 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from .models import LessonDocumentation, PersonalNote + + +class LessonDocumentationForm(forms.ModelForm): + class Meta: + model = LessonDocumentation + fields = ['topic', 'homework'] + + +class PersonalNoteForm(forms.ModelForm): + class Meta: + model = PersonalNote + fields = ['absent', 'late', 'excused', 'remarks'] + + person_name = forms.CharField(disabled=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + try: + self.fields['person_name'].initial = str(self.instance.person) + except: + pass + + +PersonalNoteFormSet = forms.modelformset_factory( + PersonalNote, form=PersonalNoteForm, max_num=0, extra=0) diff --git a/biscuit/apps/alsijil/migrations/0001_initial.py b/biscuit/apps/alsijil/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..183219e96b93fb4f186ec44dd0ad228c1ae0f33f --- /dev/null +++ b/biscuit/apps/alsijil/migrations/0001_initial.py @@ -0,0 +1,49 @@ +# Generated by Django 2.2.4 on 2019-08-22 20:47 + +import biscuit.core.util.core_helpers +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('chronos', '0004_auto_20190821_1550'), + ('core', '0014_remove_unique'), + ] + + operations = [ + migrations.CreateModel( + name='PersonalNote', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('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, to='core.Person')), + ('school', models.ForeignKey(default=biscuit.core.util.core_helpers.get_current_school, on_delete=django.db.models.deletion.CASCADE, to='core.School')), + ], + options={ + 'unique_together': {('school', 'lesson_period', 'week', 'person')}, + }, + ), + migrations.CreateModel( + name='LessonDocumentation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, 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, to='chronos.LessonPeriod')), + ('school', models.ForeignKey(default=biscuit.core.util.core_helpers.get_current_school, on_delete=django.db.models.deletion.CASCADE, to='core.School')), + ], + options={ + 'unique_together': {('school', 'lesson_period', 'week')}, + }, + ), + ] diff --git a/biscuit/apps/alsijil/models.py b/biscuit/apps/alsijil/models.py index fba3ece6792d56d518a4241b97b145d3bb0adae9..5e9094d756d45c8c5b4ab71fb400dc1fcbd94fe1 100644 --- a/biscuit/apps/alsijil/models.py +++ b/biscuit/apps/alsijil/models.py @@ -1,7 +1,6 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ -from biscuit.chronos.util import current_week from biscuit.core.mixins import SchoolRelated @@ -23,10 +22,10 @@ class PersonalNote(SchoolRelated): class LessonDocumentation(SchoolRelated): week = models.IntegerField() - lesson_period = models.ForeigbKey('chronos.LessonPeriod', models.CASCADE) + lesson_period = models.ForeignKey('chronos.LessonPeriod', models.CASCADE) - topic = models.CharField(verbose_name=_('Lesson topic'), max_length=200) - homework = models.CharField(verbose_name=_('Homework'), max_length=200) + topic = models.CharField(verbose_name=_('Lesson topic'), max_length=200, blank=True) + homework = models.CharField(verbose_name=_('Homework'), max_length=200, blank=True) class Meta: unique_together = [['school', 'lesson_period', 'week']] diff --git a/biscuit/apps/alsijil/templates/alsijil/lesson.html b/biscuit/apps/alsijil/templates/alsijil/lesson.html index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d8f3d3f8171dc9c0ab3fb19037bad20adad90c9c 100644 --- a/biscuit/apps/alsijil/templates/alsijil/lesson.html +++ b/biscuit/apps/alsijil/templates/alsijil/lesson.html @@ -0,0 +1,72 @@ +{# -*- engine:django -*- #} +{% extends "core/base.html" %} +{% load bootstrap4 i18n %} + +{% if lesson_period %} + {% block page_title %} + {% blocktrans %}Lesson{% endblocktrans %} + + - + + {% for group in lesson_period.get_groups.all %} + <span>{{ group.short_name }}</span>, + {% endfor %} + + {{ lesson_period.get_subject.name }}, + + {% for teacher in lesson_period.get_teachers.all %} + {{ teacher.short_name }} + {% endfor %} + {% endblock %} + + {% block content %} + <div class="card"> + <div class="card-header bg-light text-dark"> + {% blocktrans %}Lesson documentation{% endblocktrans %} + </div> + <div class="card-body"> + <form method="post"> + {% csrf_token %} + {% bootstrap_form lesson_documentation_form %} + <input type="hidden" name="action" value="lesson_documentation" /> + <input type="submit" value="Update" /> + </form> + </div> + </div> + + <div class="card"> + <div class="card-header bg-light text-dark"> + {% blocktrans %}Personal notes{% endblocktrans %} + </div> + <div class="card-body"> + <form method="post"> + {% csrf_token %} + {{ personal_note_formset.management_form }} + + <table class="table table-striped table-bordered table-hover table-condensed table-responsive w-100 d-block d-md-table"> + <tr> + <th>{% blocktrans %}Person{% endblocktrans %}</th> + <th>{% blocktrans %}Absent{% endblocktrans %}</th> + <th>{% blocktrans %}Tardiness{% endblocktrans %}</th> + <th>{% blocktrans %}Excused{% endblocktrans %}</th> + <th>{% blocktrans %}Remarks{% endblocktrans %}</th> + </tr> + {% for form in personal_note_formset %} + {% form.id %} + <tr> + <td>{{ form.person_name }}</td> + <td>{{ form.absent }}</td> + <td>{{ form.late }}</td> + <td>{{ form.excused }}</td> + <td>{{ form.remarks }}</td> + </tr> + {% endfor %} + </table> + + <input type="hidden" name="action" value="personal_notes" /> + <input type="submit" value="Update" /> + </form> + </div> + </div> + {% endblock %} +{% endif %} diff --git a/biscuit/apps/alsijil/views.py b/biscuit/apps/alsijil/views.py index 04cc7aeb455bdc0109000b23e370eccd98ce5399..4c6870ba2273d4c0cae12eeb0fb87432566e62da 100644 --- a/biscuit/apps/alsijil/views.py +++ b/biscuit/apps/alsijil/views.py @@ -8,15 +8,20 @@ from django.utils.translation import ugettext as _ from biscuit.apps.chronos.models import LessonPeriod from biscuit.apps.chronos.util import current_lesson_periods, current_week +from .forms import LessonDocumentationForm, PersonalNoteFormSet +from .models import LessonDocumentation, PersonalNote + @login_required def lesson(request: HttpRequest, week: Optional[int] = None, period_id: Optional[int] = None) -> HttpResponse: context = {} if week and period_id: + # Get a specific lesson period if provided in URL lesson_period = LessonPeriod.objects.get(pk=period_id) wanted_week = week else: + # Determine current lesson by current date and time lesson_period = current_lesson_periods().filter( lesson__teachers=request.user.person).first() wanted_week = current_week() @@ -24,4 +29,32 @@ def lesson(request: HttpRequest, week: Optional[int] = None, period_id: Optional context['lesson_period'] = lesson_period context['week'] = wanted_week + if lesson_period: + # Create or get lesson documentation object; can be empty when first opening lesson + lesson_documentation, created = LessonDocumentation.objects.get_or_create(lesson_period=lesson_period, week=wanted_week) + lesson_documentation_form = LessonDocumentationForm(request.POST or None, instance=lesson_documentation, prefix='leson_documentation') + + # Create all missing personal notes about members of all groups in lesson + for group in lesson_period.lesson.groups.all(): + for person in group.members.all(): + note, created = PersonalNote.objects.get_or_create(person=person, lesson_period=lesson_period, + week=wanted_week) + + # Create a formset that holds all personal notes for all persons in this lesson + persons_qs = PersonalNote.objects.filter(lesson_period=lesson_period, week=wanted_week) + personal_note_formset = PersonalNoteFormSet(request.POST or None, queryset=persons_qs, prefix='personal_notes') + + if request.method == 'POST': + if request.POST.get('action', None) == 'lesson_documentation': + # Save the lesson documentation + if lesson_documentation_form.is_valid(): + lesson_documentation_form.save() + elif request.POST.get('action', None) == 'personal_notes': + # Save all personal notes + if personal_note_formset.is_valid(): + personal_note_formset.save() + + context['lesson_documentation_form'] = lesson_documentation_form + context['personal_note_formset'] = personal_note_formset + return render(request, 'alsijil/lesson.html', context)