Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AlekSIS/official/AlekSIS-App-Alsijil
  • sunweaver/AlekSIS-App-Alsijil
  • 8tincsoVluke/AlekSIS-App-Alsijil
  • perfreicpo/AlekSIS-App-Alsijil
  • noifobarep/AlekSIS-App-Alsijil
  • 7ingannisdo/AlekSIS-App-Alsijil
  • unmruntartpa/AlekSIS-App-Alsijil
  • balrorebta/AlekSIS-App-Alsijil
  • comliFdifwa/AlekSIS-App-Alsijil
  • 3ranaadza/AlekSIS-App-Alsijil
10 results
Show changes
Commits on Source (1)
import pkg_resources
try:
__version__ = pkg_resources.get_distribution('BiscuIT-App-Alsijil').version
__version__ = pkg_resources.get_distribution("BiscuIT-App-Alsijil").version
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
class AlsijilConfig(AppConfig):
name = 'biscuit.apps.alsijil'
verbose_name = 'BiscuIT - Alsijil (Class register)'
name = "biscuit.apps.alsijil"
verbose_name = "BiscuIT - Alsijil (Class register)"
from datetime import datetime
from django import forms
from django.db.models import Count
from django.utils.translation import ugettext_lazy as _
from django_select2.forms import Select2Widget
from datetime import datetime
from biscuit.apps.chronos.models import Room
from biscuit.core.models import Group, Person
......@@ -13,54 +15,75 @@ from .models import LessonDocumentation, PersonalNote, PersonalNoteFilter
class LessonDocumentationForm(forms.ModelForm):
class Meta:
model = LessonDocumentation
fields = ['topic', 'homework']
fields = ["topic", "homework"]
class PersonalNoteForm(forms.ModelForm):
class Meta:
model = PersonalNote
fields = ['absent', 'late', 'excused', 'remarks']
fields = ["absent", "late", "excused", "remarks"]
person_name = forms.CharField(disabled=True)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['person_name'].widget.attrs.update(
{'class': 'alsijil-lesson-personal-note-name'})
self.fields["person_name"].widget.attrs.update(
{"class": "alsijil-lesson-personal-note-name"}
)
if self.instance and getattr(self.instance, 'person', None):
self.fields['person_name'].initial = str(self.instance.person)
if self.instance and getattr(self.instance, "person", None):
self.fields["person_name"].initial = str(self.instance.person)
class SelectForm(forms.Form):
group = forms.ModelChoiceField(
queryset=Group.objects.annotate(lessons_count=Count('lessons')).filter(lessons_count__gt=0),
label=_('Group'), required=False, widget=Select2Widget)
queryset=Group.objects.annotate(lessons_count=Count("lessons")).filter(
lessons_count__gt=0
),
label=_("Group"),
required=False,
widget=Select2Widget,
)
teacher = forms.ModelChoiceField(
queryset=Person.objects.annotate(lessons_count=Count(
'lessons_as_teacher')).filter(lessons_count__gt=0),
label=_('Teacher'), required=False, widget=Select2Widget)
queryset=Person.objects.annotate(
lessons_count=Count("lessons_as_teacher")
).filter(lessons_count__gt=0),
label=_("Teacher"),
required=False,
widget=Select2Widget,
)
room = forms.ModelChoiceField(
queryset=Room.objects.annotate(lessons_count=Count(
'lesson_periods')).filter(lessons_count__gt=0),
label=_('Room'), required=False, widget=Select2Widget)
queryset=Room.objects.annotate(lessons_count=Count("lesson_periods")).filter(
lessons_count__gt=0
),
label=_("Room"),
required=False,
widget=Select2Widget,
)
PersonalNoteFormSet = forms.modelformset_factory(
PersonalNote, form=PersonalNoteForm, max_num=0, extra=0)
PersonalNote, form=PersonalNoteForm, max_num=0, extra=0
)
class RegisterAbsenceForm(forms.Form):
date_start = forms.DateField(label=_('Start date'), widget=forms.SelectDateWidget, initial=datetime.today)
date_end = forms.DateField(label=_('End 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)
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)
date_start = forms.DateField(
label=_("Start date"), widget=forms.SelectDateWidget, initial=datetime.today
)
date_end = forms.DateField(
label=_("End 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
)
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 Meta:
model = PersonalNoteFilter
fields = ['identifier', 'description', 'regex']
fields = ["identifier", "description", "regex"]
from django.utils.translation import ugettext_lazy as _
MENUS = {
'NAV_MENU_CORE': [
"NAV_MENU_CORE": [
{
'name': _('Class register'),
'url': '#',
'root': True,
'validators': ['menu_generator.validators.is_authenticated', 'biscuit.core.util.core_helpers.has_person'],
'submenu': [
"name": _("Class register"),
"url": "#",
"root": True,
"validators": [
"menu_generator.validators.is_authenticated",
"biscuit.core.util.core_helpers.has_person",
],
"submenu": [
{
'name': _('Current lesson'),
'url': 'lesson',
'validators': ['menu_generator.validators.is_authenticated']
"name": _("Current lesson"),
"url": "lesson",
"validators": ["menu_generator.validators.is_authenticated"],
},
{
'name': _('Current week'),
'url': 'week_view',
'validators': ['menu_generator.validators.is_authenticated']
"name": _("Current week"),
"url": "week_view",
"validators": ["menu_generator.validators.is_authenticated"],
},
{
'name': _('Register absence'),
'url': 'register_absence',
'validators': ['menu_generator.validators.is_superuser']
"name": _("Register absence"),
"url": "register_absence",
"validators": ["menu_generator.validators.is_superuser"],
},
{
'name': _('Personal note filters'),
'url': 'list_personal_note_filters',
'validators': ['menu_generator.validators.is_superuser']
}
]
"name": _("Personal note filters"),
"url": "list_personal_note_filters",
"validators": ["menu_generator.validators.is_superuser"],
},
],
}
]
}
# 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
from django.db import migrations, models
import biscuit.core.util.core_helpers
class Migration(migrations.Migration):
......@@ -10,42 +11,114 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('chronos', '0001_initial'),
('core', '0001_initial'),
("chronos", "0001_initial"),
("core", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='PersonalNote',
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, related_name='personal_notes', to='core.Person')),
('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
(
"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,
related_name="personal_notes",
to="core.Person",
),
),
(
"school",
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
to="core.School",
),
),
],
options={
'ordering': ['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')},
"ordering": [
"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(
name='LessonDocumentation',
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, related_name='documentations', to='chronos.LessonPeriod')),
('school', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='core.School')),
(
"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,
related_name="documentations",
to="chronos.LessonPeriod",
),
),
(
"school",
models.ForeignKey(
default=1,
on_delete=django.db.models.deletion.CASCADE,
to="core.School",
),
),
],
options={
'ordering': ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday', 'lesson_period__period__period'],
'unique_together': {('school', 'lesson_period', 'week')},
"ordering": [
"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
import django.db.models.deletion
from django.db import migrations, models
import biscuit.apps.alsijil.models
import biscuit.core.util.core_helpers
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('core', '0003_school_logo'),
('alsijil', '0001_initial'),
("core", "0003_school_logo"),
("alsijil", "0001_initial"),
]
operations = [
migrations.CreateModel(
name='PersonalNoteFilter',
name="PersonalNoteFilter",
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')),
('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')),
(
"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",
),
),
(
"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={
'ordering': ['identifier'],
'unique_together': {('school', 'regex'), ('school', 'description'), ('school', 'identifier')},
"ordering": ["identifier"],
"unique_together": {
("school", "regex"),
("school", "description"),
("school", "identifier"),
},
},
),
]
......@@ -10,7 +10,14 @@ from .models import PersonalNote
@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
a selected period number.
......@@ -27,9 +34,7 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu
wanted_week = CalendarWeek.from_date(day)
# Get all lessons of this person on the specified day
lesson_periods = self.lesson_periods_as_participant.on_day(
day
).filter(
lesson_periods = self.lesson_periods_as_participant.on_day(day).filter(
period__period__gte=from_period
)
......@@ -39,15 +44,12 @@ def mark_absent(self, day: date, from_period: int = 0, absent: bool = True, excu
person=self,
lesson_period=lesson_period,
week=wanted_week.week,
defaults={
'absent': absent,
'excused': excused
}
defaults={"absent": absent, "excused": excused},
)
if remarks:
if personal_note.remarks:
personal_note.remarks += '; %s' % remarks
personal_note.remarks += "; %s" % remarks
else:
personal_note.remarks = remarks
personal_note.save()
......@@ -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
missing_persons = Person.objects.annotate(
no_personal_notes=~Exists(PersonalNote.objects.filter(
week=wanted_week.week,
lesson_period=self,
person__pk=OuterRef('pk')
))
no_personal_notes=~Exists(
PersonalNote.objects.filter(
week=wanted_week.week, lesson_period=self, person__pk=OuterRef("pk")
)
)
).filter(
member_of__in=Group.objects.filter(pk__in=self.lesson.groups.all()),
is_active=True,
no_personal_notes=True
no_personal_notes=True,
)
# Create all missing personal notes
PersonalNote.objects.bulk_create([
PersonalNote(person=person, lesson_period=self,
week=wanted_week.week) for person in missing_persons
])
PersonalNote.objects.bulk_create(
[
PersonalNote(person=person, lesson_period=self, week=wanted_week.week)
for person in missing_persons
]
)
return PersonalNote.objects.select_related('person').filter(
lesson_period=self, week=wanted_week.week)
return PersonalNote.objects.select_related("person").filter(
lesson_period=self, week=wanted_week.week
)
......@@ -13,10 +13,14 @@ class PersonalNote(models.Model):
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()
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)
late = models.IntegerField(default=0)
......@@ -25,9 +29,15 @@ class PersonalNote(models.Model):
remarks = models.CharField(max_length=200, blank=True)
class Meta:
unique_together = [['lesson_period', 'week', 'person']]
ordering = ['lesson_period__lesson__date_start', 'week', 'lesson_period__period__weekday',
'lesson_period__period__period', 'person__last_name', 'person__first_name']
unique_together = [["lesson_period", "week", "person"]]
ordering = [
"lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
"person__last_name",
"person__first_name",
]
class LessonDocumentation(CRUDMixin):
......@@ -37,27 +47,38 @@ class LessonDocumentation(CRUDMixin):
week = models.IntegerField()
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)
homework = models.CharField(verbose_name=_('Homework'), 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)
class Meta:
unique_together = [['lesson_period', 'week']]
ordering = ['lesson_period__lesson__date_start', 'week',
'lesson_period__period__weekday', 'lesson_period__period__period']
unique_together = [["lesson_period", "week"]]
ordering = [
"lesson_period__lesson__date_start",
"week",
"lesson_period__period__weekday",
"lesson_period__period__period",
]
class PersonalNoteFilter(models.Model):
""" A filter definition that can generate statistics on personal note texts. """
identifier = models.CharField(verbose_name=_('Identifier'), max_length=30,
validators=[isidentifier], unique=True)
description = models.CharField(verbose_name=_('Description'), max_length=60,
blank=True, unique=True)
identifier = models.CharField(
verbose_name=_("Identifier"),
max_length=30,
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,
unique=True)
regex = models.CharField(
verbose_name=_("Match expression"), max_length=100, unique=True
)
class Meta:
ordering = ['identifier']
ordering = ["identifier"]
from django.utils.translation import ugettext_lazy as _
import django_tables2 as tables
from django_tables2.utils import A
class PersonalNoteFilterTable(tables.Table):
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()
description = tables.Column()
regex = tables.Column()
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
from . import views
urlpatterns = [
path('lesson', views.lesson, name='lesson'),
path('lesson/<int:year>/<int:week>/<int:period_id>', views.lesson,
name='lesson_by_week_and_period'),
path('week', views.week_view, name='week_view'),
path('week/<int:year>/<int:week>', views.week_view,
name='week_view_by_week'),
path('print/group/<int:id_>', views.full_register_group,
name='full_register_group'),
path('absence/new', views.register_absence,
name='register_absence'),
path('filters/list', views.list_personal_note_filters,
name='list_personal_note_filters'),
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')
path("lesson", views.lesson, name="lesson"),
path(
"lesson/<int:year>/<int:week>/<int:period_id>",
views.lesson,
name="lesson_by_week_and_period",
),
path("week", views.week_view, name="week_view"),
path("week/<int:year>/<int:week>", views.week_view, name="week_view_by_week"),
path(
"print/group/<int:id_>", views.full_register_group, name="full_register_group"
),
path("absence/new", views.register_absence, name="register_absence"),
path(
"filters/list",
views.list_personal_note_filters,
name="list_personal_note_filters",
),
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.