diff --git a/migrations/versions/0e5220a9f169_.py b/migrations/versions/0e5220a9f169_.py
new file mode 100644
index 0000000000000000000000000000000000000000..027be458abc7cfc6424dad5bfa31bea87ffbbf9b
--- /dev/null
+++ b/migrations/versions/0e5220a9f169_.py
@@ -0,0 +1,37 @@
+"""empty message
+
+Revision ID: 0e5220a9f169
+Revises: 188f389b2286
+Create Date: 2017-02-26 15:53:41.410353
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '0e5220a9f169'
+down_revision = '188f389b2286'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.create_table('decisiondocuments',
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('decision_id', sa.Integer(), nullable=True),
+    sa.Column('name', sa.String(), nullable=True),
+    sa.Column('filename', sa.String(), nullable=True),
+    sa.Column('is_compiled', sa.Boolean(), nullable=True),
+    sa.Column('is_private', sa.Boolean(), nullable=True),
+    sa.ForeignKeyConstraint(['decision_id'], ['decisions.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_table('decisiondocuments')
+    # ### end Alembic commands ###
diff --git a/models/database.py b/models/database.py
index e91c3f4531e35a05909654f60e9ff4f34d794d21..b041a2f0bf1a61f06345ae5dfe00530ca8a76c4b 100644
--- a/models/database.py
+++ b/models/database.py
@@ -289,10 +289,42 @@ class Document(db.Model):
 @event.listens_for(Document, "before_delete")
 def on_document_delete(mapper, connection, document):
     if document.filename is not None:
-        document_path = os.path.join(config.DOCUMENTS_PATH, document.filename)
+        document_path = document.get_filename()
         if os.path.isfile(document_path):
             os.remove(document_path)
 
+class DecisionDocument(db.Model):
+    __tablename__ = "decisiondocuments"
+    id = db.Column(db.Integer, primary_key=True)
+    decision_id = db.Column(db.Integer, db.ForeignKey("decisions.id"))
+    name = db.Column(db.String)
+    filename = db.Column(db.String)
+
+    def __init__(self, decision_id, name, filename):
+        self.decision_id = decision_id
+        self.name = name
+        self.filename = filename
+
+    def __repr__(self):
+        return "<DecisionDocument(id={}, decision_id={}, name={}, filename={})>".format(
+            self.id, self.decision_id, self.name, self.filename)
+
+    def get_filename(self):
+        return os.path.join(config.DOCUMENTS_PATH, self.filename)
+
+    def as_file_like(self):
+        with open(self.get_filename(), "rb") as file:
+            return BytesIO(file.read())
+
+@event.listens_for(DecisionDocument, "before_delete")
+def on_decisions_document_delete(mapper, connection, document):
+    if document.filename is not None:
+        document_path = document.get_filename()
+        if os.path.isfile(document_path):
+            os.remove(document_path)
+
+
+
 class Todo(db.Model):
     __tablename__ = "todos"
     id = db.Column(db.Integer, primary_key=True)
@@ -381,6 +413,8 @@ class Decision(db.Model):
     protocol_id = db.Column(db.Integer, db.ForeignKey("protocols.id"))
     content = db.Column(db.String)
 
+    document = relationship("DecisionDocument", backref=backref("decision"), cascade="all, delete-orphan", uselist=False)
+
     def __init__(self, protocol_id, content):
         self.protocol_id = protocol_id
         self.content = content
@@ -433,7 +467,7 @@ class Error(db.Model):
         lines = self.description.splitlines()
         if len(lines) <= 4:
             return "\n".join(lines)
-        return "\n".join(lines[:2], "…", lines[-2:])
+        return "\n".join([*lines[:2], "…", *lines[-2:]])
 
 class TodoMail(db.Model):
     __tablename__ = "todomails"
diff --git a/parser.py b/parser.py
index ec8dd56539ab33af557e7ed4cc752de4722ab4f7..069aa807b4a5c7fa9c8be3a1e27bf255762fc8ea 100644
--- a/parser.py
+++ b/parser.py
@@ -94,7 +94,9 @@ class Element:
         current.append(element)
         if isinstance(element, Fork):
             return element
-        return current
+        else:
+            element.fork = current
+            return current
 
     PATTERN = r"x(?<!x)" # yes, a master piece, but it should never be called
 
@@ -123,14 +125,14 @@ class Content(Element):
         if match.group("content") is None:
             raise ParserException("Content is missing its content!", linenumber)
         content = match.group("content")
-        element = Content.from_content(content, linenumber)
+        element = Content.from_content(content, current, linenumber)
         if len(content) == 0:
             return current, linenumber
         current = Element.parse_outer(element, current)
         return current, linenumber
 
     @staticmethod
-    def from_content(content, linenumber):
+    def from_content(content, current, linenumber):
         children = []
         while len(content) > 0:
             matched = False
@@ -138,7 +140,7 @@ class Content(Element):
                 match = pattern.match(content)
                 if match is not None:
                     matched = True
-                    children.append(TEXT_PATTERNS[pattern](match, linenumber))
+                    children.append(TEXT_PATTERNS[pattern](match, current, linenumber))
                     content = content[len(match.group()):]
                     break
             if not matched:
@@ -151,9 +153,10 @@ class Content(Element):
     PATTERN = r"\s*(?<content>(?:[^\[\];\r\n]+)?(?:\[[^\]\r\n]+\][^;\[\]\r\n]*)*);?"
 
 class Text:
-    def __init__(self, text, linenumber):
+    def __init__(self, text, linenumber, fork):
         self.text = text
         self.linenumber = linenumber
+        self.fork = fork
 
     def render(self, render_type, show_private, level=None, protocol=None):
         if render_type == RenderType.latex:
@@ -171,22 +174,23 @@ class Text:
         print("{}text: {}".format(" " * level, self.text))
 
     @staticmethod
-    def parse(match, linenumber):
+    def parse(match, current, linenumber):
         if match is None:
             raise ParserException("Text is not actually a text!", linenumber)
         content = match.group("text")
         if content is None:
             raise ParserException("Text is empty!", linenumber)
-        return Text(content, linenumber)
+        return Text(content, linenumber, current)
 
     PATTERN = r"(?<text>[^\[]+)(?:(?=\[)|$)"
 
 
 class Tag:
-    def __init__(self, name, values, linenumber):
+    def __init__(self, name, values, linenumber, fork):
         self.name = name
         self.values = values
         self.linenumber = linenumber
+        self.fork = fork
 
     def render(self, render_type, show_private, level=None, protocol=None):
         if render_type == RenderType.latex:
@@ -222,14 +226,14 @@ class Tag:
         print("{}tag: {}: {}".format(" " * level, self.name, "; ".join(self.values)))
 
     @staticmethod
-    def parse(match, linenumber):
+    def parse(match, current, linenumber):
         if match is None:
             raise ParserException("Tag is not actually a tag!", linenumber)
         content = match.group("content")
         if content is None:
             raise ParserException("Tag is empty!", linenumber)
         parts = content.split(";")
-        return Tag(parts[0], parts[1:], linenumber)
+        return Tag(parts[0], parts[1:], linenumber, current)
 
     PATTERN = r"\[(?<content>(?:[^;\]]*;)*(?:[^;\]]*))\]"
 
@@ -377,6 +381,11 @@ class Fork(Element):
     def is_root(self):
         return self.parent is None
 
+    def get_top(self):
+        if self.is_root() or self.parent.is_root():
+            return self
+        return self.parent.get_top()
+
     @staticmethod
     def create_root():
         return Fork(None, None, None, 0)
diff --git a/server.py b/server.py
index 2caa76e28cd24903f903aff17c11ee56e22f6d7c..da4f0c2b121654fc760e4f2c14e5e0cab8166d21 100755
--- a/server.py
+++ b/server.py
@@ -21,7 +21,7 @@ import math
 import config
 from shared import db, date_filter, datetime_filter, date_filter_long, time_filter, ldap_manager, security_manager, current_user, check_login, login_required, group_required, class_filter
 from utils import is_past, mail_manager, url_manager, get_first_unused_int, set_etherpad_text, get_etherpad_text, split_terms, optional_int_arg
-from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail
+from models.database import ProtocolType, Protocol, DefaultTOP, TOP, Document, Todo, Decision, MeetingReminder, Error, TodoMail, DecisionDocument
 from views.forms import LoginForm, ProtocolTypeForm, DefaultTopForm, MeetingReminderForm, NewProtocolForm, DocumentUploadForm, KnownProtocolSourceUploadForm, NewProtocolSourceUploadForm, ProtocolForm, TopForm, SearchForm, NewProtocolFileUploadForm, NewTodoForm, TodoForm, TodoMailForm
 from views.tables import ProtocolsTable, ProtocolTypesTable, ProtocolTypeTable, DefaultTOPsTable, MeetingRemindersTable, ErrorsTable, TodosTable, DocumentsTable, DecisionsTable, TodoTable, ErrorTable, TodoMailsTable
 
@@ -86,8 +86,13 @@ def index():
         if protocol.date is not None:
             return protocol.date
         return datetime.now().date()
+    current_day = datetime.now().date()
     open_protocols = sorted(
-        [protocol for protocol in protocols if not protocol.done],
+        [
+            protocol for protocol in protocols
+            if not protocol.done
+            and (protocol.date - current_day).days < config.MAX_INDEX_DAYS
+        ],
         key=_sort_key
     )
     finished_protocols = sorted(
@@ -660,7 +665,6 @@ def new_top(protocol_id):
         db.session.commit()
         return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=protocol.id))
     else:
-        print(form.number.data)
         current_numbers = list(map(lambda t: t.number, protocol.tops))
         suggested_number = get_first_unused_int(current_numbers)
         form.number.data = suggested_number
@@ -967,6 +971,21 @@ def print_document(document_id):
     flash("Das Dokument {} wird gedruckt.".format(document.name), "alert-success")
     return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=document.protocol.id))
 
+@app.route("/decision/print/<int:document_id>")
+@login_required
+def print_decision(document_id):
+    user = current_user()
+    document = DecisionDocument.query.filter_by(id=document_id).first()
+    if document is None or not document.decision.protocol.protocoltype.has_modify_right(user):
+        flash("Invalides Dokument oder keine Berechtigung.", "alert-error")
+        return redirect(request.args.get("next") or url_for("index"))
+    if not config.PRINTING_ACTIVE:
+        flash("Die Druckfunktion ist nicht aktiviert.", "alert-error")
+        return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=document.decision.protocol.id))
+    tasks.print_file(document.get_filename(), document.decision.protocol)
+    flash("Das Dokument {} wird gedruckt.".format(document.name), "alert-success")
+    return redirect(request.args.get("next") or url_for("show_protocol", protocol_id=document.decision.protocol.id))
+
 @app.route("/errors/list")
 @login_required
 def list_errors():
diff --git a/tasks.py b/tasks.py
index 5ea7a53cb7adf66e9a084e857b6e727c87431f30..4bfdca1fc4ab92b2555f63b3724248825dbed041 100644
--- a/tasks.py
+++ b/tasks.py
@@ -5,7 +5,7 @@ import subprocess
 import shutil
 import tempfile
 
-from models.database import Document, Protocol, Error, Todo, Decision, TOP, DefaultTOP, MeetingReminder, TodoMail
+from models.database import Document, Protocol, Error, Todo, Decision, TOP, DefaultTOP, MeetingReminder, TodoMail, DecisionDocument
 from models.errors import DateNotMatchingException
 from server import celery, app
 from shared import db, escape_tex, unhyphen, date_filter, datetime_filter, date_filter_long, date_filter_short, time_filter, class_filter
@@ -182,6 +182,9 @@ def parse_protocol_async(protocol_id, encoded_kwargs):
                 decision = Decision(protocol_id=protocol.id, content=decision_tag.values[0])
                 db.session.add(decision)
                 db.session.commit()
+                decision_content = texenv.get_template("decision.tex").render(render_type=RenderType.latex, decision=decision, protocol=protocol, top=decision_tag.fork.get_top(), show_private=False)
+                print(decision_content)
+                compile_decision(decision_content, decision)
             old_tops = list(protocol.tops)
             for top in old_tops:
                 protocol.tops.remove(top)
@@ -229,12 +232,21 @@ def push_to_wiki_async(protocol_id, content, summary):
             error = protocol.create_error("Pushing to Wiki", "Pushing to Wiki failed.", str(exc))
 
 def compile(content, protocol, show_private):
-    compile_async.delay(content, protocol.id, show_private)
+   compile_async.delay(content, protocol.id, show_private=show_private)
+
+def compile_decision(content, decision):
+    compile_async.delay(content, decision.id, use_decision=True)
 
 @celery.task
-def compile_async(content, protocol_id, show_private):
+def compile_async(content, protocol_id, show_private=False, use_decision=False):
     with tempfile.TemporaryDirectory() as compile_dir, app.app_context():
-        protocol = Protocol.query.filter_by(id=protocol_id).first()
+        decision = None
+        protocol = None
+        if use_decision:
+            decision = Decision.query.filter_by(id=protocol_id).first()
+            protocol = decision.protocol
+        else:
+            protocol = Protocol.query.filter_by(id=protocol_id).first()
         try:
             current = os.getcwd()
             protocol_source_filename = "protocol.tex"
@@ -255,17 +267,22 @@ def compile_async(content, protocol_id, show_private):
             subprocess.check_call(command, universal_newlines=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
             subprocess.check_call(command, universal_newlines=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
             os.chdir(current)
-            for old_document in [document for document in protocol.documents if document.is_compiled and document.is_private == show_private]:
-                protocol.documents.remove(old_document)
-            db.session.commit()
-            document = Document(protocol.id, name="protokoll{}_{}_{}.pdf".format("_intern" if show_private else "", protocol.protocoltype.short_name, date_filter_short(protocol.date)), filename="", is_compiled=True, is_private=show_private)
+            document = None
+            if not use_decision:
+                for old_document in [document for document in protocol.documents if document.is_compiled and document.is_private == show_private]:
+                    protocol.documents.remove(old_document)
+                db.session.commit()
+                document = Document(protocol.id, name="protokoll{}_{}_{}.pdf".format("_intern" if show_private else "", protocol.protocoltype.short_name, date_filter_short(protocol.date)), filename="", is_compiled=True, is_private=show_private)
+            else:
+                document = DecisionDocument(decision.id, name="beschluss_{}_{}_{}.pdf".format(protocol.protocoltype.short_name, date_filter_short(protocol.date), decision.id), filename="")
             db.session.add(document)
             db.session.commit()
             target_filename = "compiled-{}-{}.pdf".format(document.id, "internal" if show_private else "public")
+            if use_decision:
+                target_filename = "decision-{}-{}-{}.pdf".format(protocol.id, decision.id, document.id)
             document.filename = target_filename
             shutil.copy(os.path.join(compile_dir, protocol_target_filename), os.path.join(config.DOCUMENTS_PATH, target_filename))
             db.session.commit()
-            #shutil.copy(os.path.join(compile_dir, log_filename), "/tmp")
         except subprocess.SubprocessError:
             log = ""
             total_log_filename = os.path.join(compile_dir, log_filename)
diff --git a/templates/decision.tex b/templates/decision.tex
new file mode 100644
index 0000000000000000000000000000000000000000..8cc7a93f2e205041ab99b7392e7f64c730f80aca
--- /dev/null
+++ b/templates/decision.tex
@@ -0,0 +1,41 @@
+\documentclass[11pt,twoside]{protokoll2}
+%\usepackage{bookman}
+%\usepackage{newcent}
+%\usepackage{palatino}
+\usepackage{pdfpages}
+\usepackage{eurosym}
+%\usepackage[utf8]{inputenc}
+\usepackage[pdfborder={0 0 0}]{hyperref}
+%\usepackage{ngerman}
+% \usepackage[left]{lineno}
+%\usepackage{footnote}
+%\usepackage{times}
+\renewcommand{\thefootnote}{\fnsymbol{footnote}}
+\renewcommand{\thempfootnote}{\fnsymbol{mpfootnote}}
+%\renewcommand{\familydefault}{\sfdefault}
+\newcommand{\einrueck}[1]{\hfill\begin{minipage}{0.95\linewidth}#1\end{minipage}}
+
+
+\begin{document}
+%\thispagestyle{plain}   %ggf kommentarzeichen entfernen
+\Titel{
+\large Protokoll: \VAR{protocol.protocoltype.name|escape_tex}
+\\\normalsize \VAR{protocol.protocoltype.organization|escape_tex}
+}{}
+\begin{tabular}{rp{14cm}}
+{\bf Datum:} & \VAR{protocol.date|datify_long|escape_tex}\\
+{\bf Ort:} & \VAR{protocol.location|escape_tex}\\
+{\bf Protokollant:} & \VAR{protocol.author|escape_tex}\\
+{\bf Anwesend:} & \VAR{protocol.participants|escape_tex}\\
+\end{tabular}
+\normalsize
+
+\section*{Beschluss}
+\begin{itemize}
+    \item \VAR{decision.content|escape_tex}
+\end{itemize}
+
+\TOP{\VAR{top.name|escape_tex}}
+\VAR{top.render(render_type=render_type, level=0, show_private=show_private, protocol=protocol)}
+
+\end{document}
diff --git a/templates/protocol-show.html b/templates/protocol-show.html
index 79da04135f1aa22c2a5a832d5fbf3bd26d56d3f1..8ff11867f3a0ad3db1f1732ffc72fd8ec2002a03 100644
--- a/templates/protocol-show.html
+++ b/templates/protocol-show.html
@@ -74,7 +74,12 @@
             <ul>
                 {% if protocol.decisions|length > 0 %}
                     {% for decision in protocol.decisions %}
-                        <li>{{decision.content}}</li>
+                        <li>
+                            {{decision.content}}
+                            {% if config.PRINTING_ACTIVE and has_private_view_right and decision.document is not none %}
+                                <a href="{{url_for("print_decision", document_id=decision.document.id)}}">Drucken</a>
+                            {% endif %}
+                        </li>
                     {% endfor %}
                 {% else %}
                     <li>Keine Beschlüsse</li>
diff --git a/views/tables.py b/views/tables.py
index f7ab1f9ae83e572e04f471b4511cb38bb5875bda..288d1b9040e8aee81909c6d33706dddb1e1ffa74 100644
--- a/views/tables.py
+++ b/views/tables.py
@@ -209,7 +209,7 @@ class ErrorsTable(Table):
             Table.link(url_for("show_error", error_id=error.id), error.name),
             datetime_filter(error.datetime),
             error.get_short_description(),
-            Table.link(url_for("delete_error", error_id=error.id), "Löschen", confirm="Bist du dir sicher, dass du den Fehler löschen möchtest?")
+            Table.link(url_for("delete_error", error_id=error.id, next=request.path), "Löschen", confirm="Bist du dir sicher, dass du den Fehler löschen möchtest?")
         ]
 
 class ErrorTable(SingleValueTable):
@@ -287,12 +287,18 @@ class DecisionsTable(Table):
         super().__init__("Beschlüsse", decisions)
 
     def headers(self):
-        return ["Sitzung", "Beschluss"]
+        return ["Sitzung", "Beschluss", ""]
 
     def row(self, decision):
+        user = current_user()
         return [
             Table.link(url_for("show_protocol", protocol_id=decision.protocol.id), decision.protocol.get_identifier()),
-            decision.content
+            decision.content,
+            Table.link(url_for("print_decision", document_id=decision.document.id), "Drucken")
+                if config.PRINTING_ACTIVE
+                and decision.protocol.protocoltype.has_modify_right(user)
+                and decision.document is not None 
+                else ""
         ]
 
 class DocumentsTable(Table):