Compare commits

...

7 Commits

Author SHA1 Message Date
151c2fa7d7 feat: implement next feedback 2023-03-24 17:32:59 +01:00
e8371e4a6c built pdf 2023-03-24 00:16:48 +01:00
dc14ac7592 bump config 2023-03-24 00:16:33 +01:00
12548fdf9d fix: wir 2023-03-24 00:16:24 +01:00
57061dc0c7 fix: man 2023-03-24 00:13:34 +01:00
85276999a3 singleview jap wine 2023-03-24 00:11:47 +01:00
d18f0f197c feat: pdf gen 2023-03-23 22:24:47 +01:00
7 changed files with 173 additions and 42 deletions

View File

@@ -101,9 +101,8 @@ Die wichtigsten Erkenntnisse des Interviews sind:
und in der Einzelansicht der \acp{JAP} sollen alle Weine aufgelistet sein, die dieser \ac{JAP} angehören.
Diese Weine sind ebenso anklickbar und führen zu einer Einzelansicht der Weine.
\item[Genaue Nutzerführung für Teilnehmer]\hfill\\
Die exakten Schritte, die ein Teilnehmer durchlaufen muss, um einen Prozess zu durchlaufen.
Hierbei betrachten wir den Registrerungsprozess, um ein Teilnehmer zu werden und den Anmeldeprozess
eines Weines. Diese Prozesse sind detailliert in \fullref{chap:umsetzung} beschrieben.
Die exakten Schritte, die ein Teilnehmer tätigen muss, um verschiedene Prozess zu durchlaufen.
Diese Prozesse sind detailliert in \fullref{chap:umsetzung} beschrieben.
\item[Nutzerführung für \ac{WM}-Angestellte]\hfill\\
Gescanne QR-Codes von Weinen sollen den Wein als eingegangen markieren und anschließend dem
Mitarbeiter zeigen, welcher Wein eingechecked wurde. Somit dient das Scannen eines Codes ebenso zur

View File

@@ -65,30 +65,30 @@ Unterkategorien \enquote{Trockener Riesling} und \enquote{Halbtrockener Riesling
\enquote{Riesling}.
Rebsorten, Geschmack, Weineigenschaften und Qualität sollen eigene Datentypen
anstatt einfacher Zeichenfolgen sein.
Ziel davon ist, dass sich Nutzer für einen vorgefertigten, nominalen Eintrag in einem Dropdown-Menü
Ziel dessen ist, dass sich Nutzer für einen vorgefertigten, nominalen Eintrag in einem Dropdown-Menü
entscheiden müssen und diese Auswahlmöglichkeiten immer noch im TYPO3-Backend pflegbar sind.
Weinlagen sind im Brown-Field-Projekt bereits vorhanden, also sollen hierfür existierenden Daten
eingebunden werden.
Pro Wein sollen beliebig viele Weineigenschaften auswählbar sein, Wettbewerbskategorien,
Je Wein sollen beliebig viele Weineigenschaften auswählbar sein, Wettbewerbskategorien,
Geschmacksrichtung, etc, jeweils nur ein Element.
Weitere Notizen zu diesem Gespräch sind im Anhang unter \fullref{chap:anhang-notizen-digitization}
zu finden.
\\
\\
Da das Klassendiagramm gegeben lesbare Schrift nicht auf eine Textseite passt,
Da das Klassendiagramm nicht auf eine Textseite passt,
befindet es sich vollseitig im Anhang unter \fullref{chap:anhang-class-diagram}.
Die weitere Implementation der Datenobjekte ist unkompliziert und besteht hauptsächlich aus
repetitivem Schreiben von SQL-Tabellen, Domain-Model-Klassen und \acp{TCA}.
Um $m,n$-Beziehungen wie Beispielsweise der Menge der für eine Probe zugelassenen Kategorien
\enquote{allowedCategories} zwischen $m$ \enquote{Jahresauswahlprobe}-Objekten und
Um $m,n$-Beziehungen, wie beispielsweise der Menge der für eine Probe zugelassenen Kategorien
\enquote{allowedCategories}, zwischen $m$ \enquote{Jahresauswahlprobe}-Objekten und
$n$ \enquote{Category}-Objekten zu ermöglichen, werden MM-Tabellen (many-to-many) benötigt,
diese Beziehungen in Form zweier Foreign Keys speichern.
um diese Beziehungen in Form zweier Foreign Keys zu speichern.
Die Repository-Klassen können \enquote{leer} gelassen werden,
da zu diesem Zeitpunkt keine erweiterte Auswahllogik für Datenbankanfragen benötigt wird.
Wichtig ist hierbei, dass eine Repository-Klasse existiert. Alle unverzichtbaren
Schnittstellen werden über die Basisklasse \enquote{Repository} geerbt
\cite{bib:typo3-docs-extdev-tut-tea-repositories}.
Mit Abschluss der Digitization können alle Datenstrukturen im TYPO3-Backend händisch angelegt,
Mit Abschluss der Phase der Digitization können alle Datenstrukturen im TYPO3-Backend händisch angelegt,
eingesehen, gelöscht und bearbeitet werden.
@@ -119,8 +119,8 @@ Der mit dem \ac{PO} ausgearbeitete UX-Flow der Registrierung sieht vor, dass der
ob er Mitglied sei oder nicht. Hierzu gibt es je einen Button. Ist der Nutzer ein Mitglied,
wird er auf ein Loginform, mit der Option zur Registrierung weitergeleitet.
Nach erfolgreichem Login, wird ein Teilnehmerobjekt erstellt.
Wählt der Nutzer \enquote{Nein, ich bin kein Mitglied} aus, würde er auf ein Registrierungsformular
weitergeleitet, auf um sich einen Nicht-Mitgliederaccount anzulegen. Im Zuge dieser Registrierung werden
Wählt der Nutzer \enquote{Nein, ich bin kein Mitglied} aus, wird er auf ein Registrierungsformular
weitergeleitet, um einen Nicht-Mitgliederaccount anzulegen. Im Zuge dieser Registrierung werden
Stammdaten zum Weingut angefragt.
Dieser Schritt übersetzt unter anderem den \enquote{Einreicher}-Teil des ursprünglichen Anmeldeformulares,
anbei in \fullref{chap:anhang-anmeldeformular}.
@@ -138,7 +138,6 @@ werden auf diese Lösungen zurückgegriffen, um einen einheitlichen Workflow bei
Frontend-Nutzer-Login gelöst werden. Das ist explizit von femanager so angedacht:
\quotecite{Note: Login and a I forgot my password function is part of the core and not part of femanager.}
\cite{bib:typo3-docs-femanager}.
Im Folgenden wird der Registrierungsprozess im Detail beschrieben:\\
Grundlegend gibt es drei relevante Nutzerzustände vor der Registrierung:
\begin{enumerate}
@@ -167,7 +166,7 @@ Teilnehmer-Eintrag für den Frontend-Nutzer und fügt den Frontend-Nutzer der Nu
Damit ist die Teilnehmerregistrierung abgeschlossen.
\subsubsection*{Mitglied, ohne Konto}
Ist ein Nutzer ein Mitglied und hat noch kein Mitgliedskonto, muss dieser auf der Registrierungsseite
Ist ein Nutzer ein Mitglied, hat aber kein Mitgliedskonto, muss dieser auf der Registrierungsseite
\enquote{Ich bin ein Mitglied} auswählen. An dieser Stelle navigiert der Browser zu einem Login-Formular.
Auf diesem Login-Formular existiert ein Button \enquote{Jetzt registrieren}, sowie ein Hinsweistext dazu.
Da der Nutzer noch keinen Account hat, muss dieser auf \enquote{Jetzt registrieren} klicken.
@@ -180,34 +179,34 @@ freigegeben und es öffnet sich ein Login-Formular, beschrieben in \enpointy{Mit
Zunächst wurde ein simples Weichen-Content-Element erstellt.
Dieses Content-Element hat die Parameter \enquote{question}, \enquote{answ-1-link}, \enquote{answ-1-text},
\enquote{answ-2-link} sowie \enquote{answ-2-text}.
Der Zweck dieses Content-Elementes ist es, Nutzer basierend auf einer ausformilierten Frage auf eine
Der Zweck dieses Content-Elementes ist es, Nutzer basierend auf einer ausformulierten Frage auf eine
von zwei Seiten weiterzuleiten. Anschließend wurden Registrierungen über Femanager-Plugin-Content-Elemente
realisiert.
Anpassungen der versendeten Emails erfolgen durch Überschreiben der Email-Templates von Femanager.
Weiterleitungen zu bestimmten Seiten nachdem ein Nutzer spezielle Events ausgelöst hat können über TypoScript
Weiterleitungen zu bestimmten Seiten, nachdem ein Nutzer spezielle Events ausgelöst hat, können über TypoScript
konfiguriert werden \cite{bib:typo3-docs-femanager}. Logins werden über das TYPO3-Native Loginformular
gelöst. Im TYPO3-Loginformular kann man Weiterleitungen zu spezialisierten Seiten im Backend-UI festlegen
gelöst. Im TYPO3-Loginformular können Weiterleitungen zu spezialisierten Seiten im Backend-UI festgelegt werden.
\cite{bib:typo3-docs-felogin}.
Für alle funktionalen Belange wurde ein TYPO3-Plugin registriert. Dieses Plugin verfügt über einen
Für alle funktionalen Belange wird ein TYPO3-Plugin registriert. Dieses Plugin verfügt über einen
ActionController, der Nutzeranfragen an PHP-Funktionen (\enquote{Actions})
bindet.
In diesen Actions wird Fehlerbehandlung durchgeführt, Datenmodelle der Domäne erstellt und in der
Datenbank persistiert sowie Daten für die Anzeige im Frontend aufbereitet \cite{bib:typo3-docs-extbase}.
In diesen Actions werden Fehlerbehandlungen durchgeführt, Datenmodelle der Domäne erstellt und in der
Datenbank persistiert, sowie Daten für die Anzeige im Frontend aufbereitet \cite{bib:typo3-docs-extbase}.
Neue Datenobjekte werden in Repositories registriert \cite{bib:typo3-docs-extdev-tut-tea-repositories}. Diese Repositories sind Aggregate des Controllers,
werden jedoch nach dem \enquote{Inversion of Control}-Prinzip via Dependency Injection instanziiert und
der ActionController-Klasse über Methode übergeben \cite{bib:typo3-docs-di}.
Als problematisch erweisen sich bidirektionale Verbindungen zwischen Datenmodellen, wenn die Foreign Keys
über das SQL-Schlüsselwort \enquote{AUTO\_INCREMENT} in der Datenbank definiert werden.
In diesem Fall wollen wir
einen MasterRecord, der Betriebsinformationen speichert, bidirektional an ein Teilnehmerobjekt linken.
Als ForeignKeys werden hierfür ihre jeweiligen Uids herangezogen, da diese Werte durch
\enquote{AUTO\_INCREMENT} auf der Datenbankebene gehandhabt werden.
Es gilt also, dass ein MasterRecord $a$ die TeilnehmerUid von einem Teilnehmer $b$ hält und dass
$b$ die MasterRecordUid von $a$ hält.
Die Problematik hierbei ist, dass diese Uids erst nach dem persistieren in der Datenbank bekannt sind,
da diese Werte erst im Zuge der Persistierung erstellt werden. Das ist so, da das
\enquote{AUTO\_INCREMENT}-Schlüsselwort lediglich zu SQL gehört und SQL nur von der Datenbank ausgeführt wird.
Die Lösung hierfür ist es, beide Elemente zu erstellen und zu persistieren, danach ihre Uids gegenseitig
Als problematisch erweisen sich hierbei bidirektionale Verbindungen zwischen Datenmodellen, wenn die Foreign Keys
über das SQL-Schlüsselwort \enquote{AUTO\_INCREMENT} in der Datenbank generiert werden.
Beispielsweise, muss ein MasterRecord, der Betriebsinformationen speichert, bidirektional an ein Teilnehmerobjekt
gebunden werden. Hierzu wird jedem der Elemente jeweils der Foreign Key des anderen übergeben.
Als Foreign Keys werden hierfür die jeweiligen \acp{UID} herangezogen, da diese Werte durch
\enquote{AUTO\_INCREMENT} auf der Datenbankebene erzeugt werden und garantiert einzigartig je Datenbanktabelle sind
\cite{bib:w3schools-auto-increment}.
Es gilt also, dass ein MasterRecord $a$ die Teilnehmer\ac{UID} von einem Teilnehmer $b$ hält und dass
$b$ die MasterRecord\ac{UID} von $a$ hält.
Die Problematik hierbei ist, dass diese \acp{UID} erst nach dem Persistieren in der Datenbank bekannt sind,
da diese Werte erst im Zuge der Persistierung erstellt werden \cite{bib:w3schools-auto-increment}.
Die Lösung hierfür ist, beide Elemente zu erstellen und zu persistieren, erst danach ihre \acp{UID} gegenseitig
bekannt machen um sie danach erneut zu persistieren.
\subsection{Weinregistrierung}
@@ -286,14 +285,15 @@ Damit sieht das Drop-Down-Menü aus wie eine Baumstruktur.
Diese Herangehensweise erzeugt schlüssigen und lesbaren Programmcode und lässt sich unkompliziert umsetzen.
Das senkt Entwicklungskosten und erhöht den Profit des Endkunden, da hierdurch weniger Zeit aufgewandt wird.
Rekursiv aufgerufene For-Schleifen, die sich selbst erneut für alle Elemente aufrufen,
können jedoch zu einem Performanzproblem führen \cite{bib:schwarzer-vorlesung-alg}.
können zu einem Performanzproblem führen \cite{bib:schwarzer-vorlesung-alg}.
Daher wird im Folgenden die Zeitkomplexität dieser Rekursionsfunktion betrachtet.
Grundlegend, kann für diese Funktion kein Master-Theorem angewandt werden,
da es sich hierbei nicht um einen Divide-and-Conquer-Algorithmus handelt \cite{bib:schwarzer-vorlesung-alg}.
da es sich hierbei nicht um einen Divide-and-Conquer-Algorithmus handelt.
Das ist so, da das in der Rekursion weitergereichte Problem nicht kleiner wird,
sondern gleich groß bleibt.
Das verletzt die Bedingung $b>1$ des Master-Theorem, dargestellt als\\$T(n) = a*T(\frac{n}{b})+f(n)$.
Betrachten wir den Algortihmus, besteht er aus $m, m \in \mathbb{N}$ verschachtelten For-Schleifen
Das verletzt die Bedingung $b>1$ des Master-Theorem, definiert als $T(n) = a*T(\frac{n}{b})+f(n)$
\cite{bib:schwarzer-vorlesung-alg}.
Der Algortihmus besteht aus $m, m \in \mathbb{N}$ verschachtelten For-Schleifen
gleicher Länge.
Somit ist die Zeitkomplexität $O(n^m)$. Normiert dargestellt beträgt die Zeitkomplexität $O(n^2)$. Das lässt sich experimentell bestätigen.
@@ -306,12 +306,12 @@ Somit ist die Zeitkomplexität $O(n^m)$. Normiert dargestellt beträgt die Zeitk
Auf Optgroup-HTML-Tags wurde bewusst verzichtetet.
Grund dafür ist, dass Optgroup-Titel an sich nicht als Option auswählbar sind.
Grund dafür ist, dass Optgroup-Elemente an sich nicht im Dropdown auswählbar sind.
Das stellt ein Problem dar, da beispielsweise die Kategorie \enquote{Riesling},
die die Unterkategorien \enquote{Trockener Riesling} und \enquote{Halbtrockener Riesling} beinhalten könnte,
auch direkt auswählbar sein sollte. Zudem besitzen Kategorie-Elemente kein Attribut das auf die Präsenz
von Unterkategorien hindeutet \cite{bib:typo3-docs-sys-category}, womit eine Unterscheidung zwischen
Baumblättern und -Zweigen nicht ohne weiteres möglich ist. Diese Entscheidung wäre jedoch
Baumblättern und -Zweigen nicht ohne weiteres möglich wäre. Diese Entscheidung wäre jedoch
benötigt, um zwischen einem Optgroup-Tag und einem Option-Tag abzuwägen.
\paragraph*{SelectMultiple} sind Formfelder, die dem Nutzer eine Auswahl aus $n$ Elementen aus einer anderen
@@ -329,10 +329,95 @@ Hierfür wird die eingebaute PHP-Funktion \enquote{array\_keys} verwendet. Diese
Keys eines Arrays in Form eines numerisch indizierten Arrays zurück.
Der optionale Parameter \enquote{filter\_values} bestimmt, dass ausschließlich die Keys
der Key-Value-Pairs, die einen bestimmten
Wert tragen, extrahiert werden. D.h., der Funktionsaufruf filtert alle Keys und somit alle Formfeld-IDs des Formfeldparameter-Arrays heraus, die den Wert \enquote{<formfeldname>-true} haben. Das ist eine Liste
Wert tragen, extrahiert werden \cite{bib:php-array-keys}. D.h., der Funktionsaufruf filtert alle Keys und somit alle
Formfeld-IDs des Formfeldparameter-Arrays heraus, die den Wert \enquote{<formfeldname>-true} haben. Das ist eine Liste
aller Formfeld-IDs der Checkboxen des SelectMultiples, die angehakt wurden.
Mit der eingebauten PHP-Funktion \enquote{array\_map} wenden wir nun eine Operation auf alle Schlüssel
der Liste an, die \enquote{strlen('formfeldname-')} Zeichen, von links ausgehend, von der Formfeld-ID
Mit der eingebauten PHP-Funktion \enquote{array\_map} wird nun eine Operation auf alle Schlüssel
der Liste angewandt, die \enquote{strlen('formfeldname-')} Zeichen, von links ausgehend, von der Formfeld-ID
entfernt. Somit wird beispielsweise die Formfeld-ID \enquote{winekind-18} zu \enquote{18} transformiert. Übrig bleiben die \acp{UID} aller angehakten Elemente $a$, in Form einer Zeichenkente.
Über die eingebaute PHP-Funktion \enquote{intval} ist es trivial diese zu Zahlen zu übersetzen,
wodurch die tatsächlichen Objekte aus der Datenbank angefragt werden können.
\subsection{PDF- und QR-Code-Generierung}
Das dynamische Erstellen und Ausgeben des Versandbeilageblattes als PDF ist ein essenzieller Bestandteil des
Jahresauswahlprobenwerkzeuges, da dieses PDF die Schnittstelle zwischen ankommenden Weinen und dem System darstellt.
Daher ist der Profit, der durch dieses Werkzeug generiert wird, ohne dieses PDF stark eingeschränkt, da
einkommende Weine händisch, von Mitarbeitern, zugeordnet werden müssten.
Wie im \fullref{chap:stand-der-forschung} erläutert, werden für die dynamische
Generierung dieses PDFs die Bibliotheken \enquote{chillerlan/php-qrcode} und
\enquote{mpdf/mpdf} herangezogen und über Composer installiert.
\subsubsection{QR-Code-Generierung}
Der QR-Code beinhaltet lediglich die Wein-\ac{UID} anstatt einer vollständigen URL. Hintergrund dessen ist, dass
die URL, die benötigt ist, um einen Wein einzuscannen, bis auf die Wein-\ac{UID} immer identisch ist.
Somit wird redundanz vermieden.
Es ist Aufgabe der QR-Code-App, die den Code einscannt, aus der Wein-\ac{UID} eine vollständige URL herzuleiten.
Um Resourcen zu sparen und somit den Profit zu erhöhen, wird der QR-Code zu einem Base64-kodiertem Bild gerendert.
Das ist der Standardrückgabewert des QR-Code-Generators
und erfordert somit keine nähere Konfiguration. Ebenfalls lässt sich ein Base64-kodiertes Bild als Quellurl eines
IMG-HTML-Tags angeben, womit das Bild eingebettet ist. Hier wird der Profit erhöht, indem Arbeitszeit gespart wird,
die sonst in das anderweitige Einbetten eines Bildes in einem PDF mit \enquote{mpdf} fließen müsste.
Die QR-Codegenerierung funktioniert konkret, indem ein neues QRCode-Objekt der QRCode-Klasse erstellt wird.
Diese Klasse nimmt ein QROptions-Objekt im Konstruktor, das in diesem Falle einige Stilattribute mit sich trägt.
Das QRCode-Objekt bietet nun eine Methode \enquote{render} an, die, sofern nicht anders konfiguriert, den QR-Code als
Base64-kodiertes Bild zurückgibt \cite{bib:chillerlan-php-qrcode}.
\subsubsection{PDF-Generierung}
Firmenintern ist es Standard das Aussehen sowie die Inhalte der PDF-Dokumente, die \enquote{mpdf} erzeugt, mit HTML zu definieren,
das an \enquote{mpdf} gereicht wird. Um die Gestaltung und die Präsentation von Variablen in der HTML-Zeichenfolge technisch
kontinuierlich mit dem restlichen Projekt zu halten und um eine gute Wartbarkeit zu gewährleisten,
wird diese HTML-Zeichenfolge mit TYPO3-Fluid getemplated. Das heißt, dass eine HTML-Templatedatei bereitgestellt wird,
diese mit TYPO3-Fluid befüllt wird und in PHP gerendert wird, um eine HTML-Zeichenkette als Ergebnis zu erhalten.
Hierfür wird ein TYPO3-StandaloneView des instanziiert, mit einem Pfad zur Template-Datei ausgestattet, Variablen angegeben,
die in Fluid verfügbar sein sollen und anschließend über die \enquote{render}-Methode zu einem String gerendert
\cite{bib:typo3-ref-standalone-view}.
Anschließend wird ein \enquote{mpdf}-Objekt erstellt und mit einer rudimentären Konfiguration in Form eines Arrays im Konstruktor
konfiguriert. Diese Konfiguration definiert in diesem Falle Seitenabstände, Papierformat, Zeichenkodierung und Schriftarten.
Abschließend wird dem \enquote{mpdf}-Objekt das zuvor generierte HTML übergeben und über die Methode \enquote{OutputBinaryData}
als Bytes zurückgegeben und in einer Variable gespeichert \cite{bib:mpdf-ref}.
Um dieses PDF-Dokument über die Verbindung an den Nutzer zu übertragen, wird ein TYPO3-Response-Objekt erstellt.
Über dieses Response-Objekt werden einige Header gesetzt und direkt übertragen. Dieser Header sind Content-Type und Content-Length.
Abschließend werden als Response-Body die Bytes des generierten PDFs abgeschickt. Damit ist die Verbindung beendet und das
PDF zum Nutzer übertragen.
\subsection{Schnittstelle QR-Code-Scanner}
Es ist angedacht, dass Mitarbeiter über die App \enquote{QRBot} den QR-Code auf dem Einlieferungsschein einscannen.
Diese App ermöglicht es Nutzern für jeden eingescannten Code eine URL zu öffnen und den Wert des QR-Codes anstelle eines Platzhalters
in der URL einzufügen.
Hierfür bietet das Jahresauswahlprobenwerkzeug eine Schnittstelle bzw. eine Seite an, die eine Wein-\ac{UID} als
URL-kodierten GET-Parameter annimmt und diesen Wein als \enquote{eingegangen} markiert.
Um sicherzustellen, dass Weine nicht unautorisiert markiert werden, müssen sich Mitarbeiter mit einem Nutzerkonto
authentifizieren. Dieses Nutzerkonto muss Teil einer Mitarbeiter-Nutzergruppe sein.
Das Nutzerkonto wird von Redakteuren oder Administratoren im TYPO3-Backend erstellt und benötigt keiner Registrierung.
Nach einer Anmeldung bleibt diese Sitzung aktiv und verfällt erst nach längerer Inaktivität.
Wird ein Wein als \enquote{eingegangen} markiert, wird der betroffene Teilnehmer per Email informiert.
Hierzu wird die FluidEmail-Klasse des TYPO3-Cores herangezogen.
Sollte ein Wein bereits als \enquote{eingegangen} markiert sein, wird keine Email verschickt und dem Mitarbeiter wird kommuniziert,
dass keine Änderungen vorgenommen wurden.
Abschließend werden im Frontend allgemeine Daten über den Wein angezeigt, damit Mitarbeiter sich sicher sein können,
den richtigen Wein eingescanned zu haben.
\subsection{Jahresauswahlproben- und Wein-Detailansichten}
Weine und Jahresauswahlproben sollen unter bestimmten Gegebenheiten einsichtig sein.
Hierzu gibt es eine Auflistung aller Jahresauswahlproben. Diese sind anklickbar, um eine Detailansicht der ausgewählten
Jahresauswahlprobe zu öffnen. Hier wird neben Metadaten der Jahresauswahlprobe eine Liste aller zur Einsicht berechtiger Weine
angezeigt. Diese Weine sind anklickbar, um auf eine Detailansicht der Weine zu gelangen.
Die Detailansichten für Jahresauswahlproben und Weine benötigen spezieller Autorisierung.
Diese sind: Jahresauswahlproben sind nur einsichtig, wenn sich das aktuelle Datum innerhalb des
Sichtbarkeitszeitraumes der Jahresauswahlprobe befindet.
Detailansichten für Weine sind immer für den zugehörigen Teilnehmer einsichtig.
Nach Abschluss einer Jahresauswahlprobe sind alle ihr angehörigen Weine öffentlich einsichtig.
Das hat den Hintergrund, dass Jahresauswahlproben Blindverkostungen sind
und niemand die Möglichkeit haben sollte, im Voraus Informationen über die teilnehmenden Weine in Erfahrung zu bringen.
Die Ergebnisse der Jahresauswahlproben sind öffentlich, also sind es die Weine nach Abschluss einer \ac{JAP} auch.
Mitarbeiter von Weinland Mosel, wenn mit einem solchen Account angemeldet, haben immer Einsicht in Wein-Detailansichten.
Die Wein-Detailseite verfügt außerdem über einen \enquote{Versandetikett drucken}-Button, der auf das Versand-PDF verlinkt.
Dieser Button ist nur für den zugehörigen Teilnehmer und Mitarbeiter verfügbar.
Diese Daten, Fakten und Restriktionen werden serverseitig kontrolliert, um Manipulationen des Nutzers auszuschließen.
Um das zu realisieren werden Daten mit Fluid-Templates konditionell dargestellt und über Fluid-ViewHelper Links
zu anderen Ansichten generiert. Diese ViewHelper übergeben Parameter. Die hierfür relevanten Parameter der verschiedenen
Ansichten sind beispielsweise Wein-\acp{UID} und \ac{JAP}-\acp{UID}. Um Informationen über den angemeldeten Nutzer,
wie beispielsweise seiner Teilnehmernummer oder seiner Nutzergruppenzugehörigkeit, zu erlangen, wird sich
der Extbase-nativej Domain-Model-FrontendUser-Klasse bedient \cite{bib:typo3-ref-extbase-model-feuser}.
\subsection{CSV-Export}

View File

@@ -10,7 +10,7 @@
\newcommand{\cfgDocClassification}{Abschlussarbeit}
% Document version
\newcommand{\cfgDocVersion}{1.3}
\newcommand{\cfgDocVersion}{1.5}
% Last modification date
\newcommand{\cfgDateLastModification}{22. Dezember 2022}

View File

@@ -162,6 +162,15 @@
note = {Zugriff: Januar 2023}
}
@misc{bib:w3schools-auto-increment,
author = {{W3Schools}},
howpublished = "\url{https://www.w3schools.com/sql/sql_autoincrement.asp}",
title = {{SQL AUTO INCREMENT Field}},
year = {2023},
note = {Zugriff: März 2023}
}
@misc{bib:larsjung-jquery-qrcode,
author = {Lars Jung},
howpublished = "\url{https://github.com/lrsjng/jquery-qrcode/blob/master/README.md}",
@@ -319,6 +328,14 @@
note = {Zugriff: März 2023}
}
@misc{bib:mpdf-ref,
author = {{Mpdf Contributors}},
howpublished = "\url{https://mpdf.github.io/reference/mpdf-functions/overview.html}",
title = {{Overview mPDF Functions by Category}},
year = {2023},
note = {Zugriff: März 2023}
}
@misc{bib:qrbot,
author = {{TeaCapps}},
howpublished = "\url{https://qrbot.net}",
@@ -335,6 +352,14 @@
note = {Zugriff: März 2023}
}
@misc{bib:php-array-keys,
author = {{The PHP Group}},
howpublished = "\url{https://www.php.net/manual/en/function.array-keys.php}",
title = {{PHP: array-keys - Manual}},
year = {2023},
note = {Zugriff: März 2023}
}
@misc{bib:typo3-fluid,
author = {{TYPO3 Association}},
howpublished = "\url{https://typo3.org/fluid}",
@@ -438,3 +463,19 @@
year = {2023},
note = {Zugriff: März 2023}
}
@misc{bib:typo3-ref-standalone-view,
author = {{TYPO3 Contributors}},
howpublished = "\url{https://api.typo3.org/10.4/class_t_y_p_o3_1_1_c_m_s_1_1_fluid_1_1_view_1_1_standalone_view.html}",
title = {{TYPO3\\CMS\\Fluid\\View\\StandaloneView Class Reference}},
year = {2023},
note = {Zugriff: März 2023}
}
@misc{bib:typo3-ref-extbase-model-feuser,
author = {{TYPO3 Contributors}},
howpublished = "\url{https://api.typo3.org/10.4/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_domain_1_1_model_1_1_frontend_user.html}",
title = {{TYPO3\\CMS\\Extbase\\Domain\\Model\\FrontendUser Class Reference}},
year = {2023},
note = {Zugriff: März 2023}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 312 KiB

View File

@@ -156,6 +156,8 @@ class Jahresauswahlprobe #IMPLEMENTED_COLOR {
-dateAllowRegistration_end: Date
-dateAllowShow_start: Date
-dateAllowShow_end: Date
-date_start: Date
-date_end: Date
+getAllowedCategories(): List<Category>
+setAllowedCategories(allowedCategories: List<Category>): void
+getName(): String
@@ -170,6 +172,10 @@ class Jahresauswahlprobe #IMPLEMENTED_COLOR {
+setDateAllowShowStart(dateAllowShowStart: Date): void
+getDateAllowShowEnd(): Date
+setDateAllowShowEnd(dateAllowShowEnd: Date): void
+getDateStart(): Date
+setDateStart(dateStart: Date): void
+getDateEnd(): Date
+setDateEnd(dateEnd: Date): void
+getUid(): Int
+setUid(uid: Int): void
}

BIN
main.pdf

Binary file not shown.