Implement Flask server to handle POST requests and decode FDF data

This commit is contained in:
Frederik Beimgraben 2025-07-20 00:15:09 +02:00
parent cf50ca6f88
commit 0ca47f96f7
5 changed files with 437 additions and 25 deletions

View File

@ -1,6 +1,6 @@
% !TEX root = ../Main.tex
\begin{Form}[action=mailto:asta@reutlingen-university.de?subject={Projektantrag},method=post]
\begin{Form}[action=http://localhost:5000/,method=post]
\paPage{Allgemeiner Teil}{
% Abschnitt 1: Antragsteller : entweder Institution oder Person
% -> aktiviert/deaktiviert zugehörige Felder (über radio buttons) mit JavaScript
@ -12,18 +12,24 @@
name=pa-applicant-type,
width=1em,
height=1em,
value=person
]{}{=person}} Ansprechperson & \raisebox{-1pt}{\ChoiceMenu[
radiosymbol=\ding{108}
]{}{=person}} Person & \raisebox{-1pt}{\ChoiceMenu[
radio,
name=pa-applicant-type,
width=1em,
height=1em
]{}{=institution}} Institution \\
% Fields for Institution (inactive by default)
height=1em,
radiosymbol=\ding{108}
]{}{=institution}} Institution
\end{tabular}
}
\FormSection{Institution (sofern vorhanden)}{%
% Radio buttons : horizontal oben
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Art der Institution} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomChoiceMenuDefault{pa-institution-type}{}{width=\linewidth,default=-,value=-}{-,Fachschaft=stud-fs,Referat=stud-rf,Hochschulgruppe=stud-hg,Fakultät=faculty,Hochschuleinrichtung=hs-institution}
\CustomChoiceMenuDefault{pa-institution-type}{}{width=\linewidth,default=-,value=-}{-,Fachschaft=stud-fs,STUPA-Referat=stud-rf,Studentische Hochschulgruppe=stud-hg,Fakultät=faculty,Hochschuleinrichtung=hs-institution}
} \\
\textbf{Institution} & \multicolumn{2}{p{0.73\textwidth}}{
\textbf{Name der Institution} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-institution}{}{Institution}{width=\linewidth}
} \\
\end{tabular}
@ -51,15 +57,65 @@
\textbf{Projektname} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-project-name}{}{Projektname}{width=\linewidth}
} \\
% Sofern zutreffend: Bekannte Anzahl der Teilnehmer
\multicolumn{2}{p{0.667\textwidth}}{\hspace{-6pt}\textbf{Anzahl der stud. Teilnehmer (sofern bekannt)}} & {
\CustomTextFieldDefault{pa-participants}{}{Anzahl der Teilnehmer}{width=\linewidth}
} \\
\textbf{Teilnehmende Fakultäten} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomChoiceMenuDefault{pa-participing-faculties}{}{width=\linewidth,default=-}{-,Hochschulöffentlich=ALL,INF,ESB,LS,TEC,TEX,NXT}
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-inf,
width=1em,
height=1em
]{}} INF\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-esb,
width=1em,
height=1em
]{}} ESB\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-ls,
width=1em,
height=1em
]{}} LS\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-tec,
width=1em,
height=1em
]{}} TEC\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-tex,
width=1em,
height=1em
]{}} TEX\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-nxt,
width=1em,
height=1em
]{}} NXT\quad
\raisebox{-1pt}{\CheckBox[
radio,
name=pa-participating-faculties-open,
width=1em,
height=1em
]{}} Öffentlich
} \\
\end{tabular}
}
% Abschnitt 4: Projektbeschreibung
\FormSection{Kurzbeschreibung}{%
\vspace{0.3em}
\end{tabular}\vspace{2em}
% Sofern zutreffend: Bekannte Anzahl der Teilnehmer
%\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
% \textbf{Anzahl der studentischen Teilnehmer (sofern bekannt)} & \multicolumn{2}{p{0.73\textwidth}}{
% \CustomTextFieldDefault{pa-participants}{}{Anzahl der Teilnehmer}{width=\linewidth}
% } \\
%\end{tabular}
\textbf{Kurzbeschreibung:}\\
\TextField[
name=pa-project-description,
multiline,
@ -72,15 +128,301 @@
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
% \Submit{Absenden}
}
% Informationen zum Projekttyp
\paPage{Allgemeiner Teil}{
% Abschnitt 5: Antragssumme und Gesamtzeitraum
\FormSection{Antragssumme und Gesamtzeitraum}{%
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Antragssumme (\euro)} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-requested-amount}{}{Antragssumme in €}{width=\linewidth}
} \\
\textbf{Projektzeitraum (von/bis)} & \CustomTextFieldDefault{pa-start-date}{}{von}{width=\linewidth,default=TT-MM-JJJJ} & \CustomTextFieldDefault{pa-end-date}{}{bis}{width=\linewidth,default=TT-MM-JJJJ} \\
\textbf{Antragssumme (insg.)} & & \hspace{\fill} \CustomTextFieldDefault{pa-requested-amount-euro}{}{Antragssumme (€)}{width=6em,align=2,default=0.00}~\euro \\
\textbf{Projektzeitraum (von, bis)} & & \hspace{\fill} \CustomTextFieldDefault{pa-start-date}{}{von}{width=0.4\linewidth,default=MM-JJJJ,align=1} \CustomTextFieldDefault{pa-end-date}{}{bis}{width=0.4\linewidth,default=MM-JJJJ,align=1}{\BeginAccSupp{ActualText=}\color{white}~\euro\EndAccSupp{}} \\
\end{tabular}
}
\FormSection{Verwendete Mittel}{%
%\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
% \textbf{Zahlungen} & \multicolumn{2}{p{0.73\textwidth}}{
% \CustomChoiceMenuDefault{pa-project-type}{}{width=\linewidth,default=-}{-,Einmalig=single,Gestaffelt=multi}
% } \\
%\end{tabular}
\begin{minipage}{1.05\textwidth}
%\begin{description}
% \setstretch{1.0}\color{gray}\dinfont\small
% \item[Einmalige Zahlung:] ~\\Die gesamte Summe wird auf einmal ausgezahlt.\\
% z.B. für Anschaffungen, Veranstaltungen, etc.
% \item[Gestaffelte Zahlung:] ~\\Die Summe wird in Teilen ausgezahlt.\\
% z.B. für Projekte, die sich über einen längeren Zeitraum erstrecken.\vspace{0.5em}\\
% \textbf{\small In diesem Fall muss das Beiblatt "Gestaffelte Zahlung" ausgefüllt werden.}
%\end{description}
% Radio: VS-Mittel oder QS-Mittel
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Finanzierung} & \raisebox{-1pt}{\ChoiceMenu[
radio,
name=pa-financing,
width=1em,
height=1em,
radiosymbol=\ding{108}
]{}{=vs}} VS-Mittel & \raisebox{-1pt}{\ChoiceMenu[
radio,
name=pa-financing,
width=1em,
height=1em,
radiosymbol=\ding{108}
]{}{=qs}} QS-Mittel \\
\end{tabular}
\begin{description}
\setstretch{1.0}\color{gray}\dinfont\small
\item[VS-Mittel:] ~\\Finanzierung durch die studentischen Beiträge zur Verfassten Studierendenschaft.
Diese Mittel werden direkt vom AStA oder STUPA genehmigt. Es müssen die Grundsätze des \href{https://www.landesrecht-bw.de/bsbw/document/jlr-HSchulGBWV28P65b}{Landeshochschulgesetzes (§65b)} eingehalten werden. \vspace{0.5em}\\
%\textbf{\small In diesem Fall muss das Beiblatt "VS-Mittel" ausgefüllt werden.}
\item[QS-Mittel:] ~\\Finanzierung durch die Qualitätssicherungsmittel, die der Hochschule vom Land zur Verfügung gestellt werden. Die Verfasste Studierendenschaft hat hierbei das Vorschlagsrecht, jedoch müssen Anträge vom Präsidium genehmigt werden. \vspace{0.5em}
\begin{center}
\textbf{\small Dieses Format ist am sinnvollsten für alle Veranstaltungen mit Lehrzwecken.}
\textbf{\small In diesem Fall muss das Beiblatt "QS-Mittel" ausgefüllt werden.}
\end{center}
\end{description}
\end{minipage}
}
\FormSection{Checkliste: Anhänge}{
\vspace{0.5em}
\begin{minipage}{1.05\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
\textbf{Hier bitte alle mit dem Dokument eingereichten Dokumente ankreuzen:}
\vspace{1em}
\end{minipage}
%% Tabelle; Checkboxen auf rechter Seite, Text links
\begin{tabular}{@{}p{0.03\textwidth}p{\textwidth}@{}}
\raisebox{-1pt}{\CheckBox[
name=pa-anh-kostenaufstellung,
width=1em,
height=1em
]{}} & Detaillierte Kostenaufstellung \\
\raisebox{-1pt}{\CheckBox[
name=pa-anh-vergleichsangebote,
width=1em,
height=1em
]{}} & Beiblatt Vergleichsangebote (jew. pro Leistung) \\
\raisebox{-1pt}{\CheckBox[
name=pa-anh-qsm,
width=1em,
height=1em
]{}} & Beiblatt QSM \\
% Exkursionen: Bestätigung der Fakultät
\raisebox{-1pt}{\CheckBox[
name=pa-anh-fakultaet,
width=1em,
height=1em
]{}} & Bestätigung der Fakultät (bei Exkursionen) \\
\end{tabular}
}
% \Submit{Absenden}
}
\paPage{Vergleichsangebote}{
\begin{minipage}{0.95\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
Zum Nachweis der Witschaftlichkeit müssen insgesamt mindestens drei vergleichbare Angebote eingeholt werden.
Diese sind in den folgenden Feldern einzutragen. Sollte dies nicht möglich sein, ist dies zu begründen.
\end{minipage}
\vspace{2em}
\FormSection{Anforderungen/Beschreibung}{
\vspace{0.5em}
\begin{minipage}{1.05\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
Hier ist zu beschreiben, für was das Angebot eingeholt wurde bzw. was genau benötigt wird.
Für jede weitere Leistung/Anschaffung mit eigenen Angeboten ist ein neues Dokument zu erstellen.
\vspace{1em}
\end{minipage}
\textbf{Beschreibung:}\vspace{0.5em}\\
\TextField[
name=pa-offer-description,
multiline,
width=1.055\textwidth,
height=4\baselineskip,
bordercolor=gray,
backgroundcolor=white,
charsize=12pt,
align=0,
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
\FormSection{Angebot 1 (bevorzugt)}{%
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Bezeichnung} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-offer-1-provider}{}{Anbieter}{width=\linewidth}
} \\
\textbf{Angebotssumme} & & \hspace{\fill} \CustomTextFieldDefault{pa-offer-1-amount-euro}{}{Angebotssumme (€)}{width=6em,align=2,default=0}.\CustomTextFieldDefault{pa-offer-1-amount-cent}{}{Angebotssumme (ct.)}{width=2em,default=00}~\euro \\
\end{tabular}
\vspace{0.5em}\\
\textbf{Kommentar:}\vspace{0.5em}\\
\TextField[
name=pa-offer-1-comment,
multiline,
width=1.055\textwidth,
height=3\baselineskip,
bordercolor=gray,
backgroundcolor=white,
charsize=12pt,
align=0,
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
\FormSection{Angebot 2}{%
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Bezeichnung} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-offer-2-provider}{}{Anbieter}{width=\linewidth}
} \\
\textbf{Angebotssumme} & & \hspace{\fill} \CustomTextFieldDefault{pa-offer-2-amount-euro}{}{Angebotssumme (€)}{width=6em,align=2,default=0}.\CustomTextFieldDefault{pa-offer-2-amount-cent}{}{Angebotssumme (ct.)}{width=2em,default=00}~\euro \\
\end{tabular}
\vspace{0.5em}\\
\textbf{Kommentar:}\vspace{0.5em}\\
\TextField[
name=pa-offer-2-comment,
multiline,
width=1.055\textwidth,
height=3\baselineskip,
bordercolor=gray,
backgroundcolor=white,
charsize=12pt,
align=0,
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
}
\paPage{Vergleichsangebote}{
\FormSection{Angebot 3}{%
\begin{tabular}{@{}p{0.3\textwidth}p{0.35\textwidth}p{0.35\textwidth}@{}}
\textbf{Bezeichnung} & \multicolumn{2}{p{0.73\textwidth}}{
\CustomTextFieldDefault{pa-offer-3-provider}{}{Anbieter}{width=\linewidth}
} \\
\textbf{Angebotssumme} & & \hspace{\fill} \CustomTextFieldDefault{pa-offer-3-amount-euro}{}{Angebotssumme (€)}{width=6em,align=2,default=0}.\CustomTextFieldDefault{pa-offer-3-amount-cent}{}{Angebotssumme (ct.)}{width=2em,default=00}~\euro \\
\end{tabular}
\vspace{0.5em}\\
\textbf{Kommentar:}\vspace{0.5em}\\
\TextField[
name=pa-offer-3-comment,
multiline,
width=1.055\textwidth,
height=3\baselineskip,
bordercolor=gray,
backgroundcolor=white,
charsize=12pt,
align=0,
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
}
% Beiblatt QS-Mittel
\paPage{Beiblatt QS-Mittel}{
\FormSection{Info}{%
\vspace{0.5em}
\begin{minipage}{1.05\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
Durch QS-Mittel finanzierte Projekte müssen der \href{https://www.landesrecht-bw.de/bsbw/document/VVBW-VVBW000034426}{Verwaltungsvorschrift des Landes} über die Verwendung selbiger entsprechen.
Dieses Beiblatt dient der Sicherstellung, dass die Anforderungen erfüllt werden.
\vspace{1em}
\end{minipage}
}
\FormSection{Checkliste}{
\vspace{0.5em}
\begin{minipage}{1.05\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
Die folgenden Felder sind wahrheitsgemäß zu beantworten. Bei nicht wahrheitsgemäßer oder unvollständiger Angabe wird Antrag abgelehnt.
\vspace{1em}
\end{minipage}
%% Tabelle; Checkboxen auf rechter Seite, Text links
\begin{tabular}{@{}p{\textwidth}p{0.05\textwidth}@{}}
% Der Antrag beinhaltet keine zeitlich unbefristeten Stellenfinanzierungen
\textbf{Die Maßnahme beinhaltet keine zeitlich unbefristeten Stellenfinanzierungen} & \raisebox{-1pt}{\CheckBox[
name=pa-qsm-stellenfinanzierungen,
width=1em,
height=1em
]{}} \\
% Die Maßnahme kommt den Studierenden zugute (vgl. VWV)
\textbf{Die Maßnahme kommt den Studierenden zugute (vgl. VWV)} & \raisebox{-1pt}{\CheckBox[
name=pa-qsm-studierende,
width=1em,
height=1em
]{}} \\
% Es findet keine individuelle Förderung von Studierenden statt
\textbf{Es findet keine individuelle Förderung von Studierenden statt} & \raisebox{-1pt}{\CheckBox[
name=pa-qsm-individuell,
width=1em,
height=1em
]{}} \\
\end{tabular}
}
% Bekannte Arten der Finanzierung nach VWV; Sofern die Maßnahme eine bekannte Art der Finanzierung nach VWV darstellt, kann diese zur besseren Einordnung angegeben werden.
% Diese sind:
% (Stufe 1)
% - Finanzierung zusätzlicher, auch fachübergreifender Lehr- und Seminarangebote
% - Fachspezifische Studienprojekte
% - Hochschuldidaktische Fort- und Weiterbildungsmaßnahmen
% (Stufe 2)
% - Verbesserung sowie Ausbau der Angebote von Serviceeinrichtungen der Hochschule sowie der lehr- und lernbezogenen Infrastruktur
% - Lehr- und Lernmaterialien
% - Durchführung von Exkursionen im Pflicht- und Wahlpflichtbereich sowie Exkursionen zur Vertiefung des Lehrinhalts
% - Finanzierung von infrastrukturellen Begleit- und Anpassungsmaßnahmen
% (Stufe 3)
% - Verbesserung der Beratungsangebote für Studierende
% - Studium Generale, fachübergreifende Lehrangebote
% - Sonstige Maßnahmen, die mittelbar der Verbesserung der Qualität von Studium und Lehre dienen und die Vielfalt der Studierendenschaft und Studienangebote widerspiegeln, hochschulübergreifende Projekte
%
% Falls keine zutrifft, muss eine Begründung, warum die Maßnahme trotzdem förderungswürdig ist, angegeben werden.
\FormSection{Art der Maßnahme}{
\vspace{0.5em}
\begin{minipage}{1.05\textwidth}
\setstretch{1.0}\color{gray}\dinfont\small
Sofern die Maßnahme eine bekannte Art der Finanzierung nach VWV darstellt, kann diese zur besseren Einordnung angegeben werden.
\vspace{1em}
\end{minipage}
% Drop-down menu
\CustomChoiceMenuDefault{pa-qsm-financing}{}{width=1.05\textwidth,default=-}{
{Andere (bitte begründen)=vwv-0},
{Finanzierung zusätzlicher Lehr- und Seminarangebote=vwv-3-2-1-1},
{Fachspezifische Studienprojekte=vwv-3-2-1-2},
{Hochschuldidaktische Fort- und Weiterbildungsmaßnahmen=vwv-3-2-1-3},
{Verbesserung/Ausbau von Serviceeinrichtungen sowie Infrastruktur=vwv-3-2-2-1},
{Lehr- und Lernmaterialien=vwv-3-2-2-2},
{Durchführung von Exkursionen=vwv-3-2-2-3},
{Finanzierung von infrastrukturellen Begleit- und Anpassungsmaßnahmen=vwv-3-2-2-4},
{Verbesserung der Beratungsangebote für Studierende=vwv-3-2-3-1},
{Studium Generale und fachübergreifende Lehrangebote=vwv-3-2-3-2},
{Sonstige Maßnahmen im Interesse der Studierendenschaft=vwv-3-2-3-3}
}
% Begründung
\textbf{Begründung oder Kommentar:}\vspace{0.5em}\\
\TextField[
name=pa-qsm-comment,
multiline,
width=1.055\textwidth,
height=5\baselineskip,
bordercolor=gray,
backgroundcolor=white,
charsize=12pt,
align=0,
readonly=\isReadOnlyVariant
]{}\vspace{-1.5em}
}
}
\end{Form}

View File

@ -8,7 +8,7 @@
print,
name=#1,
width=1.7cm,
color=gray,
color=black,
backgroundcolor=white,
bordercolor=white,
value=#2,
@ -25,7 +25,7 @@
\DeclareRobustCommand{\CustomChoiceMenu}[7]{\raisebox{#3}[#4][#5]{\ChoiceMenu[
name=#1,
color=gray,
color=black,
backgroundcolor=white,
value=#2,
align=1,
@ -36,11 +36,14 @@
]{}{#7}}}
\DeclareRobustCommand{\CustomTextFieldThuge}[4]{\CustomTextField{#1}{#2}{-5pt}{0pt}{0pt}{#3}{
charsize=20pt,
charsize=18pt,
height=1em,
width=3.6cm,
readonly=true,
bordercolor=gray,
backgroundcolor=black!5!white,
borderwidth=2pt,
color=gray,
#4
}}
@ -144,10 +147,10 @@
%
\node[anchor=north east, inner sep=0pt, xshift=-2cm, yshift=-5.5cm, opacity=0.3] (logo\the\numexpr\value{logoCounter}+1) at (current page.north east) {
\huge
\CustomTextFieldThuge{pa-id}{2025/0000}{Jahr/Antragsnummer}{}
\CustomTextFieldThuge{pa-key}{0000 0000 0000 0000}{Schlüssel}{
\CustomTextFieldThuge{pa-id}{}{Jahr/Antragsnummer}{width=3.8cm}
\CustomTextFieldThuge{pa-key}{}{}{
name=pa-key,
width=1pt,
width=0.1pt,
readonly=true,
bordercolor=white,
backgroundcolor=white,

View File

@ -8,6 +8,9 @@
\input{TeX/Preamble}
% Set Language to German
\selectlanguage{ngerman}
% ==== Document ====
\begin{document}

View File

@ -3,6 +3,9 @@
% ==== Imports ====
\usepackage{hyperref}
\usepackage[nameinlink, noabbrev]{cleveref}
\usepackage{csquotes}
\usepackage{makecell}
\MakeOuterQuote{"}
% ==== /Imports ====
% ==== Settings ====

61
test-server/main.py Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""
Host a simple Flask server and print the POST of any request to the terminal
"""
from flask import Flask, request
import sys
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
from pdfminer.pdftypes import resolve1
from pdfminer.psparser import PSLiteral
import json
import io
app = Flask(__name__)
# Decode FDF data and print to terminal
@app.route('/', methods=['POST'])
def post():
data = io.BytesIO(request.data)
# Decode the data
parser = PDFParser(data)
doc = PDFDocument(parser)
FDF = resolve1(doc.catalog['FDF'])
fields = resolve1(FDF.get('Fields'))
for i in fields:
field = resolve1(i)
value_psl: PSLiteral | bytes = field.get('V')
value = ''
if isinstance(value_psl, PSLiteral):
if value_psl.name.startswith('\\376\\377'): # Like: \\376\\377\\000p\\000e\\000r\\000s\\000o\\000n
value = ''.join(
c for c in value_psl.name.replace('\\376\\377', '').split('\\000') if c
)
else:
value = value_psl.name
elif isinstance(value_psl, bytes):
if value_psl.startswith(b'\xfe\xff'):
value = value_psl.decode('utf-16-be')
elif value_psl.startswith(b'\xff\xfe'):
value = value_psl.decode('utf-16-le')
else:
value = value_psl.decode('utf-8')
else:
print(f'Unknown type: {type(value_psl)}')
key = field.get('T').decode('utf-8')
print(f'{key}: {value}')
return '', 204
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)