Skip to content
Snippets Groups Projects
Commit 7b9e39f5 authored by Jonathan Weth's avatar Jonathan Weth :keyboard: Committed by root
Browse files

Merge pull request #59 from Katharineum/feature/substitutions-pdf

Substitutions PDF
parents 93b70919 c32311de
No related branches found
No related tags found
1 merge request!86Merge school-apps
......@@ -3,3 +3,7 @@ env/
*.pyc
secure*
.idea/workspace.xml
*.aux
*.log
class.pdf
class.tex
import os
import subprocess
from django.utils import timezone
from django.utils import formats
# LaTeX constants
TEX_HEADER = """\\documentclass[11pt]{article}
\\usepackage[ngerman]{babel}
\\usepackage[utf8]{inputenc}
\\usepackage[a4paper,left=1cm,right=1cm,top=2cm,bottom=2cm,bindingoffset=0mm]{geometry}
\\usepackage{fancyhdr}
\\usepackage{graphicx}
\\usepackage{longtable}
\\usepackage{multirow}
\\usepackage{color, colortbl}
\\usepackage{geometry}
\\usepackage{ulem, xpatch}
\\xpatchcmd{\\sout}
{\\bgroup}
{\\bgroup\def\\ULthickness{1.5pt}}
{}{}
\\usepackage[framemethod=tikz]{mdframed}
\\newmdenv[
roundcorner=5pt,
backgroundcolor=green,
linecolor=green,
skipabove=0pt,
skipbelow=0pt,
leftmargin=0pt,
rightmargin=0pt
]{badges}
\\usepackage{tcolorbox}
\\newtcbox{\\badge}{nobeforeafter,colframe=green,colback=green,boxrule=0.5pt,arc=4pt,
boxsep=0pt,left=5pt,right=5pt,top=5pt,bottom=5pt,tcbox raise base,
grow to left by=0pt,
grow to right by=-3pt,
enlarge top by=3pt,
enlarge bottom by=3pt,coltext=white}
\\usepackage{helvet} %Helvetica als Standardschriftart
\\renewcommand{\\familydefault}{\\sfdefault} %Helvetica als Standardschriftart
\\definecolor{grey}{rgb}{0.95,0.95,0.95}
\\definecolor{darkgrey}{rgb}{0.6,0.6,0.6}
\\definecolor{white}{rgb}{1,1,1}
\\definecolor{green}{RGB}{76,175,80}
\\pagestyle{fancy}
%\\renewcommand{\\sectionmark}[1]{#1}
%\\lhead{\\rightmark}
\\lhead{\\includegraphics[width=5cm]{static/common/logo.png}}
\\lfoot{Katharineum zu Lübeck}
\\cfoot{\\thepage}
\\rfoot{\\small Umsetzung: © 2018 by Computer-AG}
\\begin{document}"""
TEX_FOOTER = '\end{document}'
TEX_TABLE_HEADER_CLASS = """
\def\\arraystretch{1.5}
\\begin{longtable}{|p{20mm}|p{10mm}|p{32mm}|p{25mm}|p{30mm}|p{35mm}|}
\\hline\n
\\rowcolor{darkgrey}
\\color{white}\\textbf{Klasse} &
\\color{white}\\textbf{Std.} &
\\color{white}\\textbf{Lehrer} &
\\color{white}\\textbf{Fach} &
\\color{white}\\textbf{Raum} &
\\color{white}\\textbf{Hinweis}\\\\\\hline
"""
TEX_HEADER_CLASS = """
\\rhead{\\textbf{Vertretungen %s}\\\\Stand: %s\\\\ }
\\Large
\\subsubsection*{}
\\section*{\\Huge Vertretungen %s}
\n"""
def generate_pdf(tex, filename):
"""Generate a PDF by LaTeX code"""
# Read LaTeX file
tex_file = open(os.path.join("latex", filename + ".tex"), "w")
tex_file.write(tex)
tex_file.close()
# Execute pdflatex to generate the PDF
bash_command = "pdflatex -output-directory latex {}.tex".format(filename)
process = subprocess.Popen(bash_command.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
def tex_replacer(s):
"""Replace HTML tags by LaTeX tags"""
# Strong text
s = s.replace("<strong>", "\\textbf{")
s = s.replace("</strong>", "}")
# Struck out text
s = s.replace("<s>", "\\sout{")
s = s.replace("</s>", "}")
# Arrow
s = s.replace("", "$\\rightarrow$")
return s
def generate_class_tex(subs, date):
"""Generate LaTeX for a PDF by a substitution table"""
tex_body = ""
# Format dates
status_date = formats.date_format(date, format="j. F Y, \\K\\W W ")
current_date = formats.date_format(timezone.datetime.now(), format="j. F Y H:i")
head_date = formats.date_format(date, format="l, j. F Y")
# Generate header with dates
tex_body += TEX_HEADER_CLASS % (status_date, current_date, head_date)
# Begin table
tex_body += TEX_TABLE_HEADER_CLASS
color_background = True
for sub in subs:
# Color every second row in grey
if color_background:
tex_body += '\\rowcolor{grey}'
# Get color tag for row
color = "\color{%s}" % sub.color
# Print classes
tex_body += color
tex_body += '\\textbf{' + sub.classes + '} & '
# Print lesson number, teacher, subject and room
for i in [sub.lesson, sub.teacher, sub.subject, sub.room]:
tex_body += color
tex_body += tex_replacer(i) + ' & '
# Print badge (Cancellation)
if sub.badge is not None:
tex_body += """\\large\\badge{%s}""" % sub.badge
# Print notice and new line
tex_body += color
tex_body += "\\Large\\textit{%s}\\\\\\hline\n" % (sub.text or "")
# Change background
color_background = not color_background
# End table
tex_body += '\\end{longtable}'
# Connect header, body and footer
tex_content = TEX_HEADER + tex_body + TEX_FOOTER
return tex_content
......@@ -86,86 +86,96 @@
</tr>
</thead>
<tbody>
{% for sub in subs %}
{% for sub in sub_table %}
<tr
{% if sub.type == 1 or sub.type == 2 %}
class="green-text"
{% elif sub.type == 3 %}
class="blue-text"
{% endif %}
{# {% if sub.type == 1 or sub.type == 2 %}#}
{# class="green-text"#}
{# {% elif sub.type == 3 %}#}
{# class="blue-text"#}
{# {% endif %}#}
class="{{ sub.css_class }}"
>
<td>
<strong>
{% if sub.type == 3 %}
{{ sub.lesson|add:-1 }}./{{ sub.lesson }}.
{% else %}
{{ sub.lesson }}.
{% endif %}
{# {% if sub.type == 3 %}#}
{# {{ sub.lesson|add:-1 }}./{{ sub.lesson }}.#}
{# {% else %}#}
{# {{ sub.lesson }}.#}
{# {% endif %}#}
{{ sub.lesson }}
</strong>
</td>
<td>
{% for class_ in sub.classes %}
{{ class_.name }}
{% endfor %}
{# {% for class_ in sub.classes %}#}
{# {{ class_.name }}#}
{# {% endfor %}#}
{{ sub.classes }}
</td>
<td>
{% if sub.type == 1 %}
<s>{{ sub.teacher_old.shortcode }}</s>
{% elif sub.teacher_new and sub.teacher_old %}
<s>{{ sub.teacher_old.shortcode }}</s>
<strong>{{ sub.teacher_new.shortcode }}</strong>
{% elif sub.teacher_new and not sub.teacher_old %}
<strong>{{ sub.teacher_new.shortcode }}</strong>
{% else %}
<strong>{{ sub.teacher_old.shortcode }}</strong>
{% endif %}
{# {% if sub.type == 1 %}#}
{# <s>{{ sub.teacher_old.shortcode }}</s>#}
{# {% elif sub.teacher_new and sub.teacher_old %}#}
{# <s>{{ sub.teacher_old.shortcode }}</s> →#}
{# <strong>{{ sub.teacher_new.shortcode }}</strong>#}
{# {% elif sub.teacher_new and not sub.teacher_old %}#}
{# <strong>{{ sub.teacher_new.shortcode }}</strong>#}
{# {% else %}#}
{# <strong>{{ sub.teacher_old.shortcode }}</strong>#}
{# {% endif %}#}
{{ sub.teacher|safe }}
</td>
<td>
{% if sub.type == 3 %}
<span class="badge new blue">Aufsicht</span>
{% elif sub.type == 1 or sub.type == 2 %}
<s>{{ sub.subject_old.shortcode }}</s>
{% elif sub.subject_new and sub.subject_old %}
<s>{{ sub.subject_old.shortcode }}</s>
<strong>{{ sub.subject_new.shortcode }}</strong>
{% elif sub.subject_new and not sub.subject_old %}
<strong>{{ sub.subject_new.shortcode }}</strong>
{% else %}
<strong>{{ sub.subject_old.shortcode }}</strong>
{% endif %}
{# {% if sub.type == 3 %}#}
{# <span class="badge new blue">Aufsicht</span>#}
{# {% elif sub.type == 1 or sub.type == 2 %}#}
{# <s>{{ sub.subject_old.shortcode }}</s>#}
{# {% elif sub.subject_new and sub.subject_old %}#}
{# <s>{{ sub.subject_old.shortcode }}</s> →#}
{# <strong>{{ sub.subject_new.shortcode }}</strong>#}
{# {% elif sub.subject_new and not sub.subject_old %}#}
{# <strong>{{ sub.subject_new.shortcode }}</strong>#}
{# {% else %}#}
{# <strong>{{ sub.subject_old.shortcode }}</strong>#}
{# {% endif %}#}
{{ sub.subject|safe }}
</td>
<td>
{% if sub.type == 3 %}
{{ sub.corridor.name }}
{% elif sub.type == 1 or sub.type == 2 %}
{% elif sub.room_new and sub.room_old %}
<s>
{{ sub.room_old.shortcode }}
</s><strong>{{ sub.room_new.shortcode }}</strong>
{% elif sub.room_new and not sub.room_old %}
<strong>
{{ sub.room_new.shortcode }}
</strong>
{% else %}
<strong>
{{ sub.room_old.shortcode }}
</strong>
{% endif %}
{# {% if sub.type == 3 %}#}
{# {{ sub.corridor.name }}#}
{# {% elif sub.type == 1 or sub.type == 2 %}#}
{# {% elif sub.room_new and sub.room_old %}#}
{# <s>#}
{# {{ sub.room_old.shortcode }}#}
{# </s><strong>{{ sub.room_new.shortcode }}</strong>#}
{# {% elif sub.room_new and not sub.room_old %}#}
{# <strong>#}
{# {{ sub.room_new.shortcode }}#}
{# </strong>#}
{# {% else %}#}
{# <strong>#}
{# {{ sub.room_old.shortcode }}#}
{# </strong>#}
{# {% endif %}#}
{{ sub.room|safe }}
</td>
<td>
{# <em>{{ sub.text|default:"" }}</em>#}
<em>{{ sub.text|default:"" }}</em>
</td>
<td>
{% if sub.type == 1 %}
<span class="badge new green">
Schüler frei</span>
{% elif sub.type == 2 %}
<span class="badge new green">
Lehrer frei</span>
{# {% if sub.type == 1 %}#}
{# <span class="badge new green">#}
{# Schüler frei</span>#}
{# {% elif sub.type == 2 %}#}
{# <span class="badge new green">#}
{# Lehrer frei</span>#}
{# {% endif %}#}
{% if sub.badge %}
<span class="badge new green">{{ sub.badge }}</span>
{% endif %}
<small>{{ sub.id }} {{ sub.lesson_id }}</small>
{# <small>{{ sub.id }} {{ sub.lesson_id }}</small>#}
<small>{{ sub.extra }}</small>
</td>
</tr>
{# {{ sub.date }}#}
......
......@@ -6,5 +6,6 @@ urlpatterns = [
path('quick/', views.quicklaunch, name='timetable_quicklaunch'),
path('<str:plan_type>/<int:plan_id>/', views.plan, name='timetable_plan'),
path('substitutions/', views.substitutions, name='timetable_substitutions'),
path('substitutions/<int:year>/<int:month>/<int:day>/', views.substitutions, name='timetable_substitutions'),
path('substitutions/<int:year>/<int:month>/<int:day>/', views.substitutions, name='timetable_substitutions_date'),
path('class.pdf', views.sub_pdf, name="timetable_substitutions_pdf")
]
import datetime
import os
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.http import Http404, FileResponse
from django.shortcuts import render
from timetable.pdf import generate_class_tex, generate_pdf
from untisconnect.parse import *
from untisconnect.sub import get_substitutions_by_date, date_to_untis_date, untis_date_to_date
from untisconnect.sub import get_substitutions_by_date, date_to_untis_date, untis_date_to_date, generate_sub_table
from django.utils import timezone
try:
......@@ -62,18 +67,56 @@ def plan(request, plan_type, plan_id):
return render(request, 'timetable/plan.html', context)
def get_next_weekday(date):
"""Get the next weekday by a datetime object"""
if date.isoweekday() in {6, 7}:
if date.isoweekday() == 6:
plus = 2
else:
plus = 1
date += datetime.timedelta(days=plus)
return date
@login_required
def sub_pdf(request):
"""Show substitutions as PDF for the next weekday (specially for monitors)"""
# Get the next weekday
today = timezone.datetime.now()
first_day = get_next_weekday(today)
# Get subs and generate table
subs = get_substitutions_by_date(first_day)
sub_table = generate_sub_table(subs)
# Generate LaTeX
tex = generate_class_tex(sub_table, first_day)
# Generate PDF
generate_pdf(tex, "class")
# Read and response PDF
file = open(os.path.join("latex", "class.pdf"), "rb")
return FileResponse(file, content_type="application/pdf")
@login_required
def substitutions(request, year=None, day=None, month=None):
"""Show substitutions in a classic view"""
date = timezone.datetime.now()
if year is not None and day is not None and month is not None:
date = timezone.datetime(year=year, month=month, day=day)
print(date)
# Get subs and generate table
subs = get_substitutions_by_date(date)
sub_table = generate_sub_table(subs)
context = {
"subs": subs,
"sub_table": sub_table,
"date": date,
"date_js": int(date.timestamp()) * 1000
}
......
......@@ -22,6 +22,7 @@ TYPE_CANCELLATION = 1
TYPE_TEACHER_CANCELLATION = 2
TYPE_CORRIDOR = 3
def parse_type_of_untis_flags(flags):
type_ = TYPE_SUBSTITUTION
if "E" in flags:
......@@ -68,7 +69,7 @@ class Substitution(object):
# Lesson
# Teacher
print(db_obj.teacher_idlessn)
# print(db_obj.teacher_idlessn)
if db_obj.teacher_idlessn != 0:
self.teacher_old = get_teacher_by_id(db_obj.teacher_idlessn)
if db_obj.teacher_idsubst != 0:
......@@ -78,7 +79,7 @@ class Substitution(object):
self.teacher_new = None
self.lesson_element = get_lesson_element_by_id_and_teacher(self.lesson_id, self.teacher_old)
print(self.lesson)
# print(self.lesson)
# Subject
self.subject_old = self.lesson_element.subject if self.lesson_element is not None else None
......@@ -110,7 +111,7 @@ class Substitution(object):
self.classes = []
class_ids = untis_split_first(db_obj.classids, conv=int)
print(class_ids)
# print(class_ids)
for id in class_ids:
self.classes.append(get_class_by_id(id))
......@@ -129,6 +130,90 @@ def substitutions_sorter(sub):
return sort_by
class SubRow(object):
def __init__(self):
self.color = "black"
self.css_class = "black-text"
self.lesson = ""
self.classes = ""
self.teacher = ""
self.subject = ""
self.room = ""
self.text = ""
self.extra = ""
def generate_sub_table(subs):
sub_rows = []
for sub in subs:
sub_row = SubRow()
sub_row.color = "black"
if sub.type == 1 or sub.type == 2:
sub_row.css_class = "green-text"
sub_row.color = "green"
elif sub.type == 3:
sub_row.css_class = "blue-text"
sub_row.color = "blue"
if sub.type == 3:
sub_row.lesson = "{}./{}".format(sub.lesson - 1, sub.lesson)
else:
sub_row.lesson = "{}.".format(sub.lesson)
for class_ in sub.classes:
sub_row.classes = class_.name
if sub.type == 1:
sub_row.teacher = "<s>{}</s>".format(sub.teacher_old.shortcode)
elif sub.teacher_new and sub.teacher_old:
sub_row.teacher = "<s>{}</s> → <strong>{}</strong>".format(sub.teacher_old.shortcode,
sub.teacher_new.shortcode)
elif sub.teacher_new and not sub.teacher_old:
sub_row.teacher = "<strong>{}</strong>".format(sub.teacher_new.shortcode)
else:
sub_row.teacher = "<strong>{}</strong>".format(sub.teacher_old.shortcode)
if sub.type == 3:
sub_row.subject = "Aufsicht"
elif sub.type == 1 or sub.type == 2:
sub_row.subject = "<s>{}</s>".format(sub.subject_old.shortcode)
elif sub.subject_new and sub.subject_old:
sub_row.subject = "<s>{}</s> → <strong>{}</strong>".format(sub.subject_old.shortcode,
sub.subject_new.shortcode)
elif sub.subject_new and not sub.subject_old:
sub_row.subject = "<strong>{}</strong>".format(sub.subject_new.shortcode)
else:
sub_row.subject = "<strong>{}</strong>".format(sub.subject_old.shortcode)
if sub.type == 3:
sub_row.room = sub.corridor.name
elif sub.type == 1 or sub.type == 2:
pass
elif sub.room_new and sub.room_old:
sub_row.room = "<s>{}</s> → <strong>{}</strong>".format(sub.room_old.shortcode, sub.room_new.shortcode)
elif sub.room_new and not sub.room_old:
sub_row.room = sub.room_new.shortcode
elif not sub.room_new and not sub.room_old:
pass
else:
sub_row.room = sub.room_old.shortcode
sub_row.text = sub.text
sub_row.badge = None
if sub.type == 1:
sub_row.badge = "Schüler frei"
elif sub.type == 2:
sub_row.badge = "Lehrer frei"
sub_row.extra = "{} {}".format(sub.id, sub.lesson_id)
sub_rows.append(sub_row)
return sub_rows
def get_substitutions_by_date(date):
subs_raw = run_default_filter(
run_using(models.Substitution.objects.filter(date=date_to_untis_date(date)).order_by("classids", "lesson")),
......@@ -136,10 +221,10 @@ def get_substitutions_by_date(date):
# print(subs_raw)
subs = row_by_row_helper(subs_raw, Substitution)
print(subs)
for row in subs:
print(row.classes)
for class_ in row.classes:
print(class_.name)
# print(subs)
# for row in subs:
# print(row.classes)
# for class_ in row.classes:
# print(class_.name)
subs.sort(key=substitutions_sorter)
return subs
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