Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
AlekSIS-App-Alsijil
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
AlekSIS®
Official
AlekSIS-App-Alsijil
Merge requests
!422
Resolve "Add export functionality to course book"
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Resolve "Add export functionality to course book"
258-add-export-functionality-to-course-book
into
master
Overview
45
Commits
105
Pipelines
47
Changes
1
Merged
permcu
requested to merge
258-add-export-functionality-to-course-book
into
master
5 months ago
Overview
37
Commits
105
Pipelines
47
Changes
1
Expand
Closes
#258 (closed)
0
0
Merge request reports
Viewing commit
9af9c13c
Show latest version
1 file
+
186
−
186
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
9af9c13c
Revert "Comment out task"
· 9af9c13c
permcu
authored
5 months ago
This reverts commit
b3c63074
.
aleksis/apps/alsijil/tasks.py
+
162
−
181
Options
#
from
copy
import d
eepcopy
#
from
datetime import date, timedelta
from
datetime
import
d
ate
from
typing
import
List
,
Optional
#
from django.db.models import Q
#
from django.utils.translation import gettext as _
from
django.db.models
import
Prefetch
,
Q
from
django.utils.translation
import
gettext
as
_
# from calendarweek import CalendarWeek
# from celery.result import allow_join_result
# from celery.states import SUCCESS
from
celery.result
import
allow_join_result
from
celery.states
import
SUCCESS
# from aleksis.core.models import Group, PDFFile
from
aleksis.apps.cursus.models
import
Course
from
aleksis.apps.kolego.models.absence
import
AbsenceReason
from
aleksis.core.models
import
Group
,
PDFFile
from
aleksis.core.util.celery_progress
import
ProgressRecorder
,
recorded_task
from
aleksis.core.util.pdf
import
generate_pdf_from_template
# from aleksis.core.util.pdf import generate_pdf_from_template
# from .models import ExtraMark
from
.model_extensions
import
annotate_person_statistics_from_documentations
from
.models
import
Documentation
,
ExtraMark
,
NewPersonalNote
,
ParticipationStatus
@recorded_task
def
generate_full_register_printout
(
group
:
int
,
file_object
:
int
,
recorder
:
ProgressRecorder
):
"""
Generate a full register printout as PDF for a group.
"""
# context = {}
# _number_of_steps = 8
# recorder.set_progress(1, _number_of_steps, _("Load data ..."))
# group = Group.objects.get(pk=group)
# file_object = PDFFile.objects.get(pk=file_object)
# groups_q = (
# Q(lesson_period__lesson__groups=group)
# | Q(lesson_period__lesson__groups__parent_groups=group)
# | Q(extra_lesson__groups=group)
# | Q(extra_lesson__groups__parent_groups=group)
# | Q(event__groups=group)
# | Q(event__groups__parent_groups=group)
# )
# personal_notes = (
# PersonalNote.objects.prefetch_related(
# "lesson_period__substitutions", "lesson_period__lesson__teachers"
# )
# .not_empty()
# .filter(groups_q)
# .filter(groups_of_person=group)
# )
# documentations = LessonDocumentation.objects.not_empty().filter(groups_q)
# recorder.set_progress(2, _number_of_steps, _("Sort data ..."))
# sorted_documentations = {"extra_lesson": {}, "event": {}, "lesson_period": {}}
# sorted_personal_notes = {"extra_lesson": {}, "event": {}, "lesson_period": {}, "person": {}}
# for documentation in documentations:
# key = documentation.register_object.label_
# sorted_documentations[key][documentation.register_object_key] = documentation
# for note in personal_notes:
# key = note.register_object.label_
# sorted_personal_notes[key].setdefault(note.register_object_key, [])
# sorted_personal_notes[key][note.register_object_key].append(note)
# sorted_personal_notes["person"].setdefault(note.person.pk, [])
# sorted_personal_notes["person"][note.person.pk].append(note)
# recorder.set_progress(3, _number_of_steps, _("Load lesson data ..."))
# # Get all lesson periods for the selected group
# lesson_periods = LessonPeriod.objects.filter_group(group).distinct()
# events = Event.objects.filter_group(group).distinct()
# extra_lessons = ExtraLesson.objects.filter_group(group).distinct()
# weeks = CalendarWeek.weeks_within(group.school_term.date_start, group.school_term.date_end)
# register_objects_by_day = {}
# for extra_lesson in extra_lessons:
# day = extra_lesson.date
# register_objects_by_day.setdefault(day, []).append(
# (
# extra_lesson,
# sorted_documentations["extra_lesson"].get(extra_lesson.pk),
# sorted_personal_notes["extra_lesson"].get(extra_lesson.pk, []),
# None,
# )
# )
# for event in events:
# day_number = (event.date_end - event.date_start).days + 1
# for i in range(day_number):
# day = event.date_start + timedelta(days=i)
# event_copy = deepcopy(event)
# event_copy.annotate_day(day)
# # Skip event days if it isn't inside the timetable schema
# if not (event_copy.raw_period_from_on_day and event_copy.raw_period_to_on_day):
# continue
# register_objects_by_day.setdefault(day, []).append(
# (
# event_copy,
# sorted_documentations["event"].get(event.pk),
# sorted_personal_notes["event"].get(event.pk, []),
# None,
# )
# )
# recorder.set_progress(4, _number_of_steps, _("Sort lesson data ..."))
# weeks = CalendarWeek.weeks_within(
# group.school_term.date_start,
# group.school_term.date_end,
# )
# for lesson_period in lesson_periods:
# for week in weeks:
# day = week[lesson_period.period.weekday]
# if (
# lesson_period.lesson.validity.date_start
# <= day
# <= lesson_period.lesson.validity.date_end
# ):
# filtered_documentation = sorted_documentations["lesson_period"].get(
# f"{lesson_period.pk}_{week.week}_{week.year}"
# )
# filtered_personal_notes = sorted_personal_notes["lesson_period"].get(
# f"{lesson_period.pk}_{week.week}_{week.year}", []
# )
# substitution = lesson_period.get_substitution(week)
# register_objects_by_day.setdefault(day, []).append(
# (lesson_period, filtered_documentation, filtered_personal_notes, substitution)
# )
# recorder.set_progress(5, _number_of_steps, _("Load statistics ..."))
# persons = group.members.prefetch_related(None).select_related(None)
# persons = group.generate_person_list_with_class_register_statistics(persons)
# prefetched_persons = []
# for person in persons:
# person.filtered_notes = sorted_personal_notes["person"].get(person.pk, [])
# prefetched_persons.append(person)
# context["school_term"] = group.school_term
# context["persons"] = prefetched_persons
# context["excuse_types"] = ExcuseType.objects.filter(count_as_absent=True)
# context["excuse_types_not_absent"] = ExcuseType.objects.filter(count_as_absent=False)
# context["extra_marks"] = ExtraMark.objects.all()
# context["group"] = group
# context["weeks"] = weeks
# context["register_objects_by_day"] = register_objects_by_day
# context["register_objects"] = list(lesson_periods) + list(events) + list(extra_lessons)
# context["today"] = date.today()
# context["lessons"] = (
# group.lessons.all()
# .select_related(None)
# .prefetch_related(None)
# .select_related("validity", "subject")
# .prefetch_related("teachers", "lesson_periods")
# )
# context["child_groups"] = (
# group.child_groups.all()
# .select_related(None)
# .prefetch_related(None)
# .prefetch_related(
# "lessons",
# "lessons__validity",
# "lessons__subject",
# "lessons__teachers",
# "lessons__lesson_periods",
# )
# )
# recorder.set_progress(6, _number_of_steps, _("Generate template ..."))
# file_object, result = generate_pdf_from_template(
# "alsijil/print/full_register.html", context, file_object=file_object
# )
# recorder.set_progress(7, _number_of_steps, _("Generate PDF ..."))
# with allow_join_result():
# result.wait()
# file_object.refresh_from_db()
# if not result.status == SUCCESS and file_object.file:
# raise Exception(_("PDF generation failed"))
# recorder.set_progress(8, _number_of_steps)
def
generate_full_register_printout
(
groups
:
List
[
int
],
file_object
:
int
,
recorder
:
ProgressRecorder
,
include_cover
:
Optional
[
bool
]
=
True
,
include_abbreviations
:
Optional
[
bool
]
=
True
,
include_members_table
:
Optional
[
bool
]
=
True
,
include_teachers_and_subjects_table
:
Optional
[
bool
]
=
True
,
include_person_overviews
:
Optional
[
bool
]
=
True
,
include_coursebook
:
Optional
[
bool
]
=
True
,
):
"""
Generate a configurable register printout as PDF for a group.
"""
def
prefetch_notable_participations
(
select_related
=
None
,
prefetch_related
=
None
):
if
not
select_related
:
select_related
=
[]
if
not
prefetch_related
:
prefetch_related
=
[]
return
Prefetch
(
"
participations
"
,
to_attr
=
"
notable_participations
"
,
queryset
=
ParticipationStatus
.
objects
.
filter
(
Q
(
absence_reason__tags__short_name
=
"
class_register
"
)
|
Q
(
tardiness__isnull
=
False
)
)
.
select_related
(
"
absence_reason
"
,
*
select_related
)
.
prefetch_related
(
*
prefetch_related
),
)
def
prefetch_personal_notes
(
name
,
select_related
=
None
,
prefetch_related
=
None
):
if
not
select_related
:
select_related
=
[]
if
not
prefetch_related
:
prefetch_related
=
[]
return
Prefetch
(
name
,
queryset
=
NewPersonalNote
.
objects
.
filter
(
Q
(
note__gt
=
""
)
|
Q
(
extra_mark__isnull
=
False
))
.
select_related
(
"
extra_mark
"
,
*
select_related
)
.
prefetch_related
(
*
prefetch_related
),
)
context
=
{}
context
[
"
include_cover
"
]
=
include_cover
context
[
"
include_abbreviations
"
]
=
include_abbreviations
context
[
"
include_members_table
"
]
=
include_members_table
context
[
"
include_teachers_and_subjects_table
"
]
=
include_teachers_and_subjects_table
context
[
"
include_person_overviews
"
]
=
include_person_overviews
context
[
"
include_coursebook
"
]
=
include_coursebook
context
[
"
today
"
]
=
date
.
today
()
_number_of_steps
=
5
+
len
(
groups
)
recorder
.
set_progress
(
1
,
_number_of_steps
,
_
(
"
Loading data ...
"
))
groups
=
Group
.
objects
.
filter
(
pk__in
=
groups
).
order_by
(
"
name
"
)
if
include_cover
:
groups
=
groups
.
select_related
(
"
school_term
"
)
if
include_abbreviations
or
include_members_table
:
context
[
"
absence_reasons
"
]
=
AbsenceReason
.
objects
.
filter
(
tags__short_name
=
"
class_register
"
,
count_as_absent
=
True
)
context
[
"
absence_reasons_not_counted
"
]
=
AbsenceReason
.
objects
.
filter
(
tags__short_name
=
"
class_register
"
,
count_as_absent
=
False
)
context
[
"
extra_marks
"
]
=
ExtraMark
.
objects
.
all
()
if
include_members_table
or
include_person_overviews
:
groups
=
groups
.
prefetch_related
(
"
members
"
)
if
include_teachers_and_subjects_table
:
groups
=
groups
.
prefetch_related
(
Prefetch
(
"
courses
"
,
queryset
=
Course
.
objects
.
select_related
(
"
subject
"
)),
"
courses__teachers
"
,
"
child_groups
"
,
Prefetch
(
"
child_groups__courses
"
,
queryset
=
Course
.
objects
.
select_related
(
"
subject
"
)),
"
child_groups__courses__teachers
"
,
)
recorder
.
set_progress
(
2
,
_number_of_steps
,
_
(
"
Loading groups ...
"
))
for
i
,
group
in
enumerate
(
groups
,
start
=
1
):
recorder
.
set_progress
(
2
+
i
,
_number_of_steps
,
_
(
f
"
Loading group
{
group
.
short_name
or
group
.
name
}
...
"
)
)
if
include_members_table
or
include_person_overviews
or
include_coursebook
:
documentations
=
Documentation
.
objects
.
filter
(
Q
(
datetime_start__date__gte
=
group
.
school_term
.
date_start
)
&
Q
(
datetime_end__date__lte
=
group
.
school_term
.
date_end
)
&
Q
(
pk__in
=
Documentation
.
objects
.
filter
(
course__groups
=
group
)
.
values_list
(
"
pk
"
,
flat
=
True
)
.
union
(
Documentation
.
objects
.
filter
(
course__groups__parent_groups
=
group
).
values_list
(
"
pk
"
,
flat
=
True
)
)
)
)
if
include_members_table
or
include_person_overviews
:
group
.
members_with_stats
=
annotate_person_statistics_from_documentations
(
group
.
members
.
all
(),
documentations
)
if
include_person_overviews
:
doc_query_set
=
documentations
.
select_related
(
"
subject
"
).
prefetch_related
(
"
teachers
"
)
group
.
members_with_stats
=
group
.
members_with_stats
.
prefetch_related
(
prefetch_notable_participations
(
prefetch_related
=
[
Prefetch
(
"
related_documentation
"
,
queryset
=
doc_query_set
)]
),
prefetch_personal_notes
(
"
new_personal_notes
"
,
prefetch_related
=
[
Prefetch
(
"
documentation
"
,
queryset
=
doc_query_set
)],
),
)
if
include_teachers_and_subjects_table
:
group
.
as_list
=
[
group
]
if
include_coursebook
:
group
.
documentations
=
documentations
.
order_by
(
"
datetime_start
"
).
prefetch_related
(
prefetch_notable_participations
(
select_related
=
[
"
person
"
]),
prefetch_personal_notes
(
"
personal_notes
"
,
select_related
=
[
"
person
"
]),
)
context
[
"
groups
"
]
=
groups
recorder
.
set_progress
(
3
+
len
(
groups
),
_number_of_steps
,
_
(
"
Generating template ...
"
))
file_object
,
result
=
generate_pdf_from_template
(
"
alsijil/print/register_for_group.html
"
,
context
,
file_object
=
PDFFile
.
objects
.
get
(
pk
=
file_object
),
)
recorder
.
set_progress
(
4
+
len
(
groups
),
_number_of_steps
,
_
(
"
Generating PDF ...
"
))
with
allow_join_result
():
result
.
wait
()
file_object
.
refresh_from_db
()
if
not
result
.
status
==
SUCCESS
and
file_object
.
file
:
raise
Exception
(
_
(
"
PDF generation failed
"
))
recorder
.
set_progress
(
5
+
len
(
groups
),
_number_of_steps
)
Loading