Merge pull request 'docs: clean up, remove clearpages' (!318) from c4-diagrams into main
All checks were successful
Build docs / build-docs (push) Successful in 15s
Reviewed-on: #318 Reviewed-by: Constantin Simonis <constantin@simonis.lol>
|
@ -13,27 +13,7 @@
|
|||
% Die Option (in den eckigen Klammern) enthält das längste Label oder
|
||||
% einen Platzhalter der die Breite der linken Spalte bestimmt.
|
||||
\begin{acronym}[WWWWW]
|
||||
\acro{API}{Application Programming Interface}
|
||||
\acro{CI}{Continuous Integration}
|
||||
\acro{CI/CD}{Continuous Integration/Continuous Deployment}
|
||||
\acro{CLI}{Command Line Interface}
|
||||
\acro{CRM}{Customer Relationship Management}
|
||||
\acro{CRON}{Vorgangsausführung gemäß geplanten Zeitabläufen für UNIX Programme}
|
||||
\acro{E2E}{End-to-End}
|
||||
\acro{eCommerce}{Electronic Commerce}
|
||||
\acro{ERM}{Entity-Relationship-Model}
|
||||
\acro{GUI}{Graphical User Interface}
|
||||
\acro{HTTP}{Hypertext Transfer Protocol}
|
||||
\acro{IDE}{Integrated Development Environment}
|
||||
\acro{IX}{Intex Fusion Pro Omnichannel CRM}
|
||||
\acro{JSON}{JavaScript Object Notation}
|
||||
\acro{M2}{\textsc{Magento 2} eCommerce Platform}
|
||||
\acro{NSD}{\textsc{neusta software development} GmbH}
|
||||
\acro{NXP}{\textsc{neusta experience} GmbH}
|
||||
\acro{PHP}{Hypertext Preprocessor}\acused{PHP}
|
||||
\acro{SQL}{Structured Query Language}
|
||||
\acro{URL}{Uniform Resource Locator}\acused{URL}
|
||||
\acro{VM}{Virtual Machine}
|
||||
\acro{XML}{Extensible Markup Language}
|
||||
\acro{JWT}{JSON Web Token}
|
||||
\end{acronym}
|
||||
|
|
|
@ -1,17 +1,5 @@
|
|||
% !TEX root = Projektdokumentation.tex
|
||||
\section{Anhang}
|
||||
\subsection{Detaillierte Zeitplanung}
|
||||
\label{app:Zeitplanung}
|
||||
|
||||
\tabelleAnhang{ZeitplanungKomplett}
|
||||
|
||||
\input{Anhang/AnhangLastenheft.tex}
|
||||
|
||||
\clearpage
|
||||
|
||||
\input{Anhang/AnhangRessourcen.tex}
|
||||
|
||||
\clearpage
|
||||
|
||||
\subsection{Implementierungsbeispiele}
|
||||
\label{app:CodeSchichten}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
%PDF-1.5
|
||||
%µí®û
|
||||
3 0 obj
|
||||
<< /Length 4 0 R
|
||||
/Filter /FlateDecode
|
||||
>>
|
||||
stream
|
||||
xœm“MŽ1…÷9EÖ,L;Çਤ™YàþÏŽSÝ
¨¥ê|ñOÞsª~¦’í÷ë=ý^òûïT•–®Ü˜jþ‘™‰kËÐÔ‰<YÔÊ¢6jkæKäèðgG„Jáœî¥]V6$<08>y¨
|
||||
¸»{>Úì:×}}ÉXw„ûôuÑü¬ÿÊî§ö¬<C3B6>f1G–Ýêæ¶ûð‰ÆA<>=HÌMløïÝ›néÁ,4ÍÁ.U’mÏú¦M×Ι´ç<e=Ñ«Œf)M–«Q™ùÕØÿ¬¾¥º\…LÒfÞÑ Œ\ul‹Òh|4aÂ85\A„Ù%ŸÒ ï{ÔBºÆ©ÔŠAËÃûÆë{Â[Ò)}Öë–^
¼}I8kà<6B>XTðBº%=ô„ÁfA®Ö8ÅF b›CS«6{cŒYÌ;áX©ÔÙ7«vGPj7ŠƒÑCo¢_ 'ôôÚ]ÆVw¢L#HlCŸ’ã[ˆ(&45Nàå•÷ñ Š«yF<79><46>t£6ÆoÛA1’ôŠ.Â|ß#üøûp%ßÒ—<>Ò'
|
||||
endstream
|
||||
endobj
|
||||
4 0 obj
|
||||
414
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/ExtGState <<
|
||||
/a0 << /CA 1 /ca 1 >>
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Type /Page
|
||||
/Parent 1 0 R
|
||||
/MediaBox [ 0 0 51.200001 51.200001 ]
|
||||
/Contents 3 0 R
|
||||
/Group <<
|
||||
/Type /Group
|
||||
/S /Transparency
|
||||
/CS /DeviceRGB
|
||||
>>
|
||||
/Resources 2 0 R
|
||||
>>
|
||||
endobj
|
||||
1 0 obj
|
||||
<< /Type /Pages
|
||||
/Kids [ 5 0 R ]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<< /Creator (cairo 1.10.2 (http://cairographics.org))
|
||||
/Producer (cairo 1.10.2 (http://cairographics.org))
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 1 0 R
|
||||
>>
|
||||
endobj
|
||||
xref
|
||||
0 8
|
||||
0000000000 65535 f
|
||||
0000000812 00000 n
|
||||
0000000528 00000 n
|
||||
0000000015 00000 n
|
||||
0000000506 00000 n
|
||||
0000000600 00000 n
|
||||
0000000877 00000 n
|
||||
0000001004 00000 n
|
||||
trailer
|
||||
<< /Size 8
|
||||
/Root 7 0 R
|
||||
/Info 6 0 R
|
||||
>>
|
||||
startxref
|
||||
1056
|
||||
%%EOF
|
|
@ -1,68 +0,0 @@
|
|||
%PDF-1.5
|
||||
%µí®û
|
||||
3 0 obj
|
||||
<< /Length 4 0 R
|
||||
/Filter /FlateDecode
|
||||
>>
|
||||
stream
|
||||
xœmRIŽÜ0¼ëz#nZž‘'fæ09$ù?<3F>"¥v÷<04>[%’eY¿J«ñü~¯ß~´úþ§ˆÑ²U<C2B2>IêÏÊL,^½Ñ´‰<]ämá N¾f½pDŽ<44>|wD¨5®áÞä +ʆf^ëTp³œù ÙuÙËaÌóHǺ#Ügž›Õ×þ¯ú‘z¤Wë4[(Šl—<6C>}óð#zþqÚ¤¡æ\ä‡÷í<C3B7>îÖf¥
|
||||
v©‘nyÁ[6ºvÎ<ÁxÏGÙO΄àjÃ#Åue7¦³~ö?©o…<6F>lAÆ8,Ö)ÙÕÁŸ• ŒB^X„°í;,<2C>ÌÛ|¹˜fU´(S4¢Fb@=NM,ÖÓ‰a“Àvls‡Ÿ;YA*ó<>Á³ÂeçhøsxÅ¢©÷htö*8.7o hºBŒÏžá4át /jÚ! ü!•i ˜+ ÛŒÉ8µpµC鈪ÿóSSp”´76Ó5ázævñß5otK8%ŽÈÊ~×!âƒÒåËÇuô&‰¦%¡è#V2ÙÆ¾èù?“þRª˜ã“¸a¬3°,Ll»¤h§æ«~5Më_½•ïå/ÅÏÕ
|
||||
endstream
|
||||
endobj
|
||||
4 0 obj
|
||||
447
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/ExtGState <<
|
||||
/a0 << /CA 1 /ca 1 >>
|
||||
>>
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<< /Type /Page
|
||||
/Parent 1 0 R
|
||||
/MediaBox [ 0 0 51.200001 51.200001 ]
|
||||
/Contents 3 0 R
|
||||
/Group <<
|
||||
/Type /Group
|
||||
/S /Transparency
|
||||
/CS /DeviceRGB
|
||||
>>
|
||||
/Resources 2 0 R
|
||||
>>
|
||||
endobj
|
||||
1 0 obj
|
||||
<< /Type /Pages
|
||||
/Kids [ 5 0 R ]
|
||||
/Count 1
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<< /Creator (cairo 1.10.2 (http://cairographics.org))
|
||||
/Producer (cairo 1.10.2 (http://cairographics.org))
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 1 0 R
|
||||
>>
|
||||
endobj
|
||||
xref
|
||||
0 8
|
||||
0000000000 65535 f
|
||||
0000000845 00000 n
|
||||
0000000561 00000 n
|
||||
0000000015 00000 n
|
||||
0000000539 00000 n
|
||||
0000000633 00000 n
|
||||
0000000910 00000 n
|
||||
0000001037 00000 n
|
||||
trailer
|
||||
<< /Size 8
|
||||
/Root 7 0 R
|
||||
/Info 6 0 R
|
||||
>>
|
||||
startxref
|
||||
1089
|
||||
%%EOF
|
Before Width: | Height: | Size: 65 KiB |
BIN
projektdokumentation/Bilder/component-diagram.drawio.png
Normal file
After Width: | Height: | Size: 261 KiB |
BIN
projektdokumentation/Bilder/container-diagram.drawio.png
Normal file
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 347 KiB |
Before Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
|
@ -1,11 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Abnahmephase}
|
||||
\label{sec:Abnahmephase}
|
||||
|
||||
Die Anwendung wurde gemäß der in Abschnitt~\ref{sec:Entwicklungsprozess}: \nameref{sec:Entwicklungsprozess} agilen Entwicklung stetig von Mitarbeitern der \ac{NSD}
|
||||
per Code Review abgenommen. Die Code Review erfolgte über das webbasierte Development Operations Lebenszyklus Tool GitLab \footnote{GitLab - \url{https://gitlab.com}}, in dessen Repository die Anwendung per git \footnote{git - \url{https://git-scm.com/}}
|
||||
versioniert wurde. Sofern ein neues Feature vom Autor fertiggestellt wurde, erstellte der Autor einen sogenannten Merge Request in GitLab. Dieser Merge Request hat zur Folge,
|
||||
dass ein zugeteilter Mitarbeiter der \ac{NSD} den Code freigeben muss und dieser dann erst in den Quellcode der Anwendung übernommen werden kann.
|
||||
|
||||
Teil der Abnahmebedingungen war, dass der zu implementierende Code sinnvoll mit Unit Tests abgedeckt ist. Exemplarisch hierfür steht der \Anhang{app:UnitTest}, welcher
|
||||
einen beispielhaften Unit Test für die Komponente neusta-m2-intex-client-config zeigt.
|
|
@ -1,105 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Analysephase}
|
||||
\label{sec:Analysephase}
|
||||
|
||||
|
||||
\subsection{Ist-Analyse}
|
||||
\label{sec:IstAnalyse}
|
||||
Ein Direktimport über Schnittstellen wird für \ac{M2} nicht zur Verfügung gestellt.
|
||||
Derzeit werden solche Importer per Modul für jeden Webshop individuell selbst entwickelt und angepasst.
|
||||
Als Modul bezeichnet man im \ac{M2} Umfeld eine Erweiterung des Frameworks durch neue Funktionalitäten.
|
||||
Die hierfür neu entwickelnden Module stellen \acs{API}-Abfragen an \ac{IX} und importieren die Daten ohne temporäres Zwischenspeichern in \ac{M2}.
|
||||
Vorhandene Fehlerquellen sind hier die benötigte Verbindung zur \ac{IX}-\acs{API} und die unbedingte Richtigkeit der übertragenen Daten.
|
||||
Kommen Fehler beim Import aufgrund von fehlender oder unvollständiger Datensätze zustande, bricht der komplette Import ab.
|
||||
Gleiches gilt für die Export Funktionen zum Exportieren von Bestellungen von \ac{M2} zu \ac{IX}.
|
||||
|
||||
|
||||
\subsection{Wirtschaftlichkeitsanalyse}
|
||||
\label{sec:Wirtschaftlichkeitsanalyse}
|
||||
Aufgrund des in den Abschnitten~\ref{sec:Projektbegruendung}: \nameref{sec:Projektbegruendung} und~\ref{sec:IstAnalyse}: \nameref{sec:IstAnalyse}
|
||||
geschilderten und erläuterten derzeitigen Zustandes von Import/Export-Modulen in Abhängigkeit zum \ac{CRM} \ac{IX} für \ac{M2}, ist die Umsetzung
|
||||
des Projektes unbedingt erforderlich. Eine gerechtfertigte Realisierung aus wirtschaftlichen Gesichtspunkten wird in den folgenden Abschnitten analysiert.
|
||||
|
||||
\subsubsection{\gqq{Make or Buy}-Entscheidung}
|
||||
\label{sec:MakeOrBuyEntscheidung}
|
||||
Bei dem Projekt handelt es sich um die Erfüllung von kundenspezifischen Anforderungen, sofern \ac{IX} als \ac{CRM} genutzt wird.
|
||||
Hierfür lässt sich auf dem Markt keine Lösung finden, die eine Integration der Warenwirtschaft in ein \ac{M2} ermöglicht.
|
||||
Daher soll das Projekt in Eigenentwicklung durchgeführt und durch Nutzung von Open Source Anwendungen erweitert werden.
|
||||
|
||||
|
||||
\subsubsection{Projektkosten}
|
||||
\label{sec:Projektkosten}
|
||||
Im folgenden sollen die Kosten kalkuliert werden, die während der Entwicklung des Projektes anfallen. Neben Personalkosten, die durch die Umsetzung
|
||||
des Projektes verursacht werden, mussten auch Aufwendungen für die in Abschnitt~\ref{sec:Ressourcenplanung}: \nameref{sec:Ressourcenplanung} genannten Ressourcen
|
||||
berücksichtigt werden. Da Personalkosten im Original nicht herausgegeben werden dürfen, erfolgte die Kalkulation anhand von unterstellten Werten.
|
||||
|
||||
Die Durchführungszeit des Projekts beträgt 70 Stunden.
|
||||
Unterstellt wurde ein Stundensatz in Höhe von \eur{10} für Auszubildende sowie \eur{25} für Mitarbeiter.
|
||||
Für die o.g. Ressourcennutzung wurde ein pauschaler Satz von \eur{15} angenommen.
|
||||
|
||||
Eine Aufstellung der Kosten lassen sich der Tabelle~\ref{tab:Kostenaufstellung} entnehmen und betragen insgesamt \eur{2910}.
|
||||
\tabelle{Kostenaufstellung}{tab:Kostenaufstellung}{Kostenaufstellung.tex}
|
||||
|
||||
|
||||
\subsubsection{Amortisationsdauer}
|
||||
\label{sec:Amortisationsdauer}
|
||||
Der folgende Abschnitt dient zur Ermittlung des Zeitpunktes, ab welchem sich die Entwicklung der Anwendung amortisiert hat.
|
||||
Anhand dieses Wertes kann beurteilt werden, ob die Umsetzung des Projektes aus wirtschaftlicher Sicht sinnvoll ist und sich hieraus
|
||||
Kostenvorteile ergeben.
|
||||
|
||||
Nachfolgend soll nun die Amortisationsdauer berechnet werden. Diese gibt an, ab welchem Zeitpunkt die Anschaffungs- und Entwicklungskosten durch die
|
||||
Zeitersparnis beglichen werden kann.
|
||||
|
||||
\tabelle{Zeitersparnis}{tab:Zeitersparnis}{Zeitersparnis} \\
|
||||
|
||||
\textbf{Berechnung der Amortisationsdauer:}
|
||||
\begin{align}
|
||||
415\ \frac{min}{Monat} \cdot 12\ \frac{Monate}{Jahr} = 4980\ \frac{min}{Jahr} = 83\ \frac{h}{Jahr}
|
||||
\end{align}
|
||||
\begin{align}
|
||||
83\ \frac{h}{Jahr} \cdot (\eur{25} + \eur{15}) = 3320\ \frac{\eur{}}{Jahr}
|
||||
\end{align}
|
||||
\begin{align}
|
||||
\frac{\eur{3320}}{2910 \frac{\eur{}}{Jahr}} = 1,14\ Jahre \approx 1\ Jahr\ \&\ 1,5\ Monate
|
||||
\end{align}
|
||||
|
||||
Zusätzlich wurde die Amortisation grafisch dargestellt. Das Diagramm enthält die variablen Kosten (pro Jahr) der neuen Lösung sowie die Kosten,
|
||||
die für die Entwicklung der neuen Umsetzung angefallen sind. Die Grafik findet sich im~\Anhang{app:Amortisation}.
|
||||
|
||||
Anhand der Amortisationsrechnung ergibt sich für das Projekt eine Amortisationsdauer von einem Jahr und ca. eineinhalb Monaten. Dies definiert den Zeitraum, über den
|
||||
die neue Anwendung mindestens eingesetzt werden muss, um Anschaffungskosten und Kosteneinsparung auszugleichen. Da das Projekt von der \ac{NSD} langfristig eingesetzt
|
||||
werden soll, kann das Projekt unter wirtschaftlichen Gesichtspunkten als sinnvoll eingestuft werden.
|
||||
|
||||
\subsection{Nutzwertanalyse}
|
||||
\label{sec:Nutzwertanalyse}
|
||||
Durch die in den Abschnitten~\ref{sec:Projektkosten}: \nameref{sec:Projektkosten} und~\ref{sec:Amortisationsdauer}: \nameref{sec:Amortisationsdauer} aufgeführten Ergebnisse wird die Realisierung
|
||||
des Projektes bereits ausreichend gerechtfertigt. Hierdurch soll an dieser Stelle auf eine detaillierte Analyse nicht-monetärer Vorteile verzichtet werden.
|
||||
Nicht-monetäre Vorteile der Anwendung wären aber \zB die angenehmere Wartbarkeit durch bessere Übersicht der neu implementierten Modulstruktur sowie die Implementierung von aussagekräftigeren Fehlermeldungen
|
||||
und der Möglichkeit, die Anwendung schnell für individuelle Wünsche anzupassen.
|
||||
|
||||
|
||||
\subsection{Anwendungsfälle}
|
||||
\label{sec:Anwendungsfaelle}
|
||||
Eine grobe Übersicht über die von der Anwendung abzudeckenden Anwendungsfälle wurde im Laufe der Analysephase per Use-Case-Diagramm dargestellt.
|
||||
Dieses Diagramm befindet sich im \Anhang{app:UseCase} und bildet alle Funktionen ab, welche aus Anwendersicht benötigt werden.
|
||||
|
||||
Dem Entwickler stehen der Vollimport sowie die Teilimporte der Daten für Nutzer- und Produktdaten zur Verfügung. Die Teilimporte sind erforderlich,
|
||||
um mögliche Fehlimporte im Kleinen neu anstoßen zu können und so einen erneuten Vollimport zu verhindern.
|
||||
|
||||
Beim Auslösen des Import-Vorgangs werden die Daten von der \ac{IX}-\acs{API} angefordert und zwischengespeichert, um abermalige Requests zu verhindern.
|
||||
Die zwischengespeicherten Daten werden dann zu \ac{M2} importiert und dem Webshop zur Verfügung gestellt.
|
||||
|
||||
Der Vorgang des Vollimports wird außerdem auch über einen \acs{CRON}-Job in geplanten Zeitabständen zur Verfügung gestellt, um ein abermaliges, manuelles
|
||||
Anstoßen zu umgehen.
|
||||
|
||||
\subsection{Qualitätsanforderungen}
|
||||
\label{sec:Qualitaetsanforderungen}
|
||||
Die Anwendung soll unter Green Development \footnote{Sustainable Web Design - \url{https://sustainablewebdesign.org/}} Grundsätzen entwickelt werden. Dies bedeutet, dass auf effiziente Datenabfragen sowie auf Minderung von Komplexität während
|
||||
der Entwicklung geachtet wird. Weitere Punkte der Qualitätsanforderungen sind die Möglichkeit nachvollziehbare Logs einzusehen, falls Fehler während
|
||||
eines Importes entstehen sowie die Wartbarkeit der Anwendung durch modulare und entkoppelte Entwicklung. Außerdem soll die Anwendung mit Unit-Tests abgedeckt sein,
|
||||
um die Funktionalität des Codes zu gewährleisten.
|
||||
|
||||
\subsection{Lastenheft/Fachkonzept}
|
||||
\label{sec:Lastenheft}
|
||||
Am Ende der Analysephase wurde mit den Mitarbeitern der \ac{NSD} sowie der \ac{NXP} ein Lastenheft erstellt. Dieses umfasst alle Anforderungen,
|
||||
welche an die neue Anwendung gestellt werden. Ein Auszug aus dem erstellten Lastenheft befindet sich im \Anhang{app:Lastenheft}.
|
|
@ -1,4 +1,3 @@
|
|||
\clearpage
|
||||
\section{Coinflip}
|
||||
|
||||
\subsection{Was ist Coinflip?}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
\clearpage
|
||||
\section{Dice}
|
||||
|
||||
\subsection{Was ist Dice?}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Dokumentation}
|
||||
\label{sec:Dokumentation}
|
||||
Die Dokumentation der Anwendung besteht aus zwei Bestandteilen: der Projektdokumentation, in welcher der Autor die einzelnen
|
||||
Phasen, die während der Projektumsetzung durchlaufen wurden, beschreibt sowie der Entwicklerdokumentation, bei der es sich um eine
|
||||
detaillierte Beschreibung der Klassen, die von der Anwendung genutzt werden, handelt. Außerdem werden auch deren Attribute und Methoden sowie die
|
||||
Abhängigkeiten der jeweiligen Klassen untereinander erläutert.
|
|
@ -1,12 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Einführungsphase}
|
||||
\label{sec:Einfuehrungsphase}
|
||||
|
||||
Durch die in Abschnitt~\ref{sec:ImplementierungGeschaeftslogik}: \nameref{sec:ImplementierungGeschaeftslogik} vorgenommene Implementierung
|
||||
der Anwendung als Composer basierte Packages, ist das zur Verfügung stellen der Anwendung an den \ac{NSD} internen Satis \footnote{Composer Satis - \url{https://github.com/composer/satis}} Server angebunden.
|
||||
Der interne Satis dient als Composer Repository und stellt so eigen entwickelte Module für die \ac{NSD} für alle Kundenprojekte zur Verfügung.
|
||||
|
||||
Die Komponenten der Anwendung werden dort aufgeführt und können in die realen Kundenprojekte nach Fertigstellung der ausgelassenen
|
||||
Funktionen per Composer implementiert werden. Hier kommt nun auch der größte Vorteil zu tragen, da eine Änderung der Module lediglich
|
||||
in der Grundversion, die dem Satis zur Verfügung steht, vorgenommen muss und somit automatisch per Composer bei Deployments für Live Umgebungen übernommen werden.
|
||||
So müssen Änderungen nicht code-seitig an den Projekten vorgenommen werden.
|
|
@ -1,73 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Entwurfsphase}
|
||||
\label{sec:Entwurfsphase}
|
||||
|
||||
\subsection{Zielplattform}
|
||||
\label{sec:Zielplattform}
|
||||
Das Abschlussprojekt soll, wie in Abschnitt~\ref{sec:Projektziel}: \nameref{sec:Projektziel} beschrieben, aufgrund des Aspektes der Fehlerminimierung als \ac{M2}-Modul
|
||||
umgesetzt werden. Zur temporären Zwischenspeicherung der importierten Datensätze von \ac{IX} wird eine Tabelle in das
|
||||
bestehende Datenbank-System der \ac{M2} Instanz implementiert.
|
||||
|
||||
Die Auswahl der Programmiersprache, mit der das Projekt realisiert werden soll, wurde anhand der Anforderungen von \ac{M2}
|
||||
als \ac{eCommerce} Platform durchgeführt. Um eine Fehler minimierende Einbindung in bestehende Shops zu garantieren, wurde beschlossen,
|
||||
auf eine Nutzwertanalyse zu verzichten und den genannten Anforderungen von \ac{M2} Folge zu leisten.
|
||||
|
||||
Daher ist die Programmiersprache \ac{PHP}, unter Berücksichtigung der genannten Gesichtspunkte, am besten geeignet und soll für die Umsetzung des Projektes verwendet werden.
|
||||
|
||||
|
||||
\subsection{Architekturdesign}
|
||||
\label{sec:Architekturdesign}
|
||||
Die Implementierung der einzelnen Import-Funktionen für Benutzer- und Produktdaten sollen auf Basis des Factory Design Pattern \footnote{PHP the Right Way - Factory Pattern - \url{https://phptherightway.com/pages/Design-Patterns.html}}
|
||||
umgesetzt werden. Demnach wird jede Import-Komponente durch eine zugehörige Factory per Singleton Prinzip instanziiert.
|
||||
So wird sichergestellt, dass jeweils nur eine Instanz des Imports vorhanden ist und Rechenlast während der Nutzung der Anwendung
|
||||
minimiert wird.
|
||||
|
||||
Zusätzlich wird jede Funktionalität modular als Composer \footnote{Composer - \url{https://getcomposer.org}} Package eingebunden, sodass die einzelnen Komponenten nur eine Basis-Komponente zum
|
||||
Funktionieren benötigen. Die Basis-Komponente bindet alle gewünschten Komponenten ein und kann sie anhand des o.g. Factory Patterns instanziieren.
|
||||
|
||||
Diese Modularität bildet eine übersichtliche Anwendungsgestaltung, die nachträglich - ohne viel Aufwand - um mehr Funktionalität erweitert werden kann.
|
||||
|
||||
\subsection{Entwurf der Benutzeroberfläche}
|
||||
\label{sec:Benutzeroberflaeche}
|
||||
Der Autor hat sich auf Grund des festgelegten Projektumfangs sowie des festgelegten Nutzerkreises, der aus Mitarbeitern der \ac{NSD} besteht,
|
||||
für eine Umsetzung der Benutzeroberfläche als \ac{CLI}, zur Ausführung der in
|
||||
Abschnitt~\ref{sec:Anwendungsfaelle}: \nameref{sec:Anwendungsfaelle} beschriebenen Anwendungsfälle, entschieden.
|
||||
|
||||
Die Einbindung der Konsolenbefehle soll über die standardisierte \ac{M2} Implementierungsmöglichkeit für \ac{CLI} Befehle erfolgen.
|
||||
|
||||
\subsection{Datenmodell}
|
||||
\label{sec:Datenmodell}
|
||||
|
||||
Um eine Zwischenspeicherung der Daten, die von der \ac{IX}-\ac{API} bereitgestellt werden, zu realisieren, wird eine Tabelle zur
|
||||
Datenstruktur vom betroffenen \ac{M2} Webshop hinzugefügt. Diese Tabelle soll lediglich Informationen über die importierten Daten und den
|
||||
jeweiligen Zeitstempel zur Nachvollziehbarkeit enthalten.
|
||||
|
||||
Da keine komplexen Entitäten hierfür benötigt werden, wurde vom Autor darauf verzichtet ein \ac{ERM} sowie eine Datenbankstruktur zu
|
||||
erstellen.
|
||||
|
||||
|
||||
\subsection{Geschäftslogik}
|
||||
\label{sec:Geschaeftslogik}
|
||||
|
||||
Wie in Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschrieben, wird die Anwendung in mehrere Komponenten aufgeteilt.
|
||||
Die Aufteilung der Komponenten erfolgt per Registrierung als Composer Package. Composer als \ac{PHP} Package Manager bietet die Möglichkeit,
|
||||
Abhängigkeiten der genutzten Software zu versionieren und in einem kontrollierten Umfeld zu nutzen. Durch die Aufteilung der Anwendung in solche
|
||||
Packages, erlangt der Autor eine entkoppelte Anwendung, die ohne großen Aufwand ebenfalls erweitert werden kann.
|
||||
|
||||
Es wird eine Basis-Komponente geben von der jede Subkompenente ableitet. Diese Basis-Komponente beinhaltet die Grundabhängigkeiten,
|
||||
damit die Anwendung im jeweiligen \ac{M2} Umfeld lauffähig ist. Diese Grundabhängigkeiten beinhalten die Version der Programmiersprache
|
||||
\ac{PHP}, die Version des genutzten \ac{M2} sowie die genauen Abhängigkeiten der genutzten \ac{M2} Kern-Komponenten. Zusätzlich wird eine Version
|
||||
der Anwendung selbst definiert, sodass in der weiteren Entwicklung eigene Versionen für verschiedene \ac{M2} Versionen (\zB ältere) zur Verfügung gestellt
|
||||
werden könnten. Die Basis Komponente wird den Namen neusta-m2-intex-base tragen.
|
||||
|
||||
neusta-m2-intex-base wird erweitert um folgende Subkomponenten:
|
||||
\begin{itemize}
|
||||
\item neusta-m2-intex-client: Subkomponente zur Verbindung zur \ac{IX} \ac{API}
|
||||
\item neusta-m2-intex-client-config: Subkomponente zur Konfiguration des Key-Value Mappings für Daten von \ac{IX}
|
||||
\item neusta-m2-intex-cli: Subkomponente zur Implementierung der Benutzeroberfläche
|
||||
\item neusta-m2-intex-customer: Subkomponente zur Implementierung der Import Logik für Nutzerdaten
|
||||
\item neusta-m2-intex-catalog: Subkomponente zur Implementierung der Import Logik für Produktdaten
|
||||
\end{itemize}
|
||||
|
||||
Durch die Namenskonvention, die vom Autor gewählt wurde, ist für aussenstehende Entwickler schneller ersichtig, in welcher Komponente
|
||||
welche Logik eingebaut wurde. So wird weiterhin die Wartungsfähigkeit der Anwendung in den Vordergrund gestellt.
|
|
@ -1,38 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Fazit}
|
||||
\label{sec:Fazit}
|
||||
|
||||
\subsection{Soll-/Ist-Vergleich}
|
||||
\label{sec:SollIstVergleich}
|
||||
|
||||
Bei der rückblickenden Betrachtung des Projektes, wird vom Autor festgehalten, dass die zuvor festgelegten Anforderungen erfüllt wurden.
|
||||
Die Entwicklung des Projektes hat einen Grundstein für ein modulares Import/Export System von \ac{M2} zu \ac{IX} gelegt, welches allerdings zur vollständigen
|
||||
Ersetzung der alten Module noch erweitert werden muss. Der Autor hat dies allerdings berücksichtigt und gemäß Abschnitt~\ref{sec:Projektabgrenzung}: \nameref{sec:Projektabgrenzung}
|
||||
aufgrund des begrenzten Projektumfangs eingeplant.
|
||||
|
||||
Wie der Tabelle~\ref{tab:Vergleich} zu entnehmen ist, konnte ebenfalls die Zeitplanung bis auf wenige Ausnahmen eingehalten werden.
|
||||
|
||||
\tabelle{Soll-/Ist-Vergleich}{tab:Vergleich}{Zeitnachher.tex}
|
||||
|
||||
|
||||
\subsection{Lessons Learned}
|
||||
\label{sec:LessonsLearned}
|
||||
|
||||
Der Autor konnte während des Projektes wertvolle Erfahrungen \bzgl der Planung und Durchführung von Software-Projekten
|
||||
sammeln. Hierbei wurde besonders deutlich, welch große Bedeutung stetige Rücksprache und Kommunikation mit den Projektbeteiligten
|
||||
für den Projekterfolg hat. Zusätzlich konnte der Autor neue Kompetenzen und Sicherheiten im Umgang mit \ac{M2} erlangen, welche
|
||||
für die zukünftige, angestrebte Tätigkeit im \ac{eCommerce} hilfreich sind.
|
||||
|
||||
Abschließend lässt sich sagen, dass die Realisierung des Projektes eine Erleichterung zur alltäglichen Arbeit mit \ac{M2}
|
||||
Webshops, die eine \ac{IX} Schnittstelle nutzen, darstellt und auch für den Autor während der Entwicklung eine Bereicherung war.
|
||||
|
||||
\subsection{Ausblick}
|
||||
\label{sec:Ausblick}
|
||||
|
||||
Die im Lastenheft definierten Anforderungen wurden zwar realisiert, dennoch können in Zukunft noch weitere Anforderungen \bzw
|
||||
Erweiterungsmöglichkeiten entwickelt werden. Es kann \zB die Erweiterung der Benutzeroberfläche in das bestehende \ac{M2} Administrator
|
||||
Backend als \ac{GUI} vorgenommen werden. Gleichzeitig können die Funktionen um weitere Datentypen erweitert werden, wie \zB
|
||||
Mediadaten und Bestellungen. Eine Möglichkeit zum Export von allen importierten Daten zu \ac{IX} selbst, sind ebenfalls Aussichten für die Zukunft.
|
||||
|
||||
Aufgrund des im Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschriebenen modularen Aufbaus, können die Anpassungen
|
||||
\bzw Erweiterungen einfach vorgenommen werden. Die Modularität der Anwendung ermöglicht somit eine gute Wart- und Erweiterbarkeit.
|
|
@ -1,82 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Implementierungsphase}
|
||||
\label{sec:Implementierungsphase}
|
||||
|
||||
\subsection{Implementierung der Datenstrukturen}
|
||||
\label{sec:ImplementierungDatenstrukturen}
|
||||
Wie in Abschnitt~\ref{sec:Datenmodell}: \nameref{sec:Datenmodell} beschrieben, ermöglicht \ac{M2} eine Einbindung von individuell benötigten \acs{SQL}
|
||||
Tabellen in die vorhandene Datenstruktur.
|
||||
|
||||
Dem \Anhang{app:InstallData} kann ein \acs{XML} entnommen werden, welches der Komponente neusta-m2-intex-base hinzugefügt wurde.
|
||||
Dieses deklarative Initialisieren von Datenstrukturen wird ebenfalls vom Framework Symfony genutzt. Es ermöglicht dem Entwickler anzugeben,
|
||||
wie die Datenstruktur einer Tabelle aussehen soll. \ac{M2} bestimmt dann den Unterschied der derzeitigen Tabellenstruktur und der Struktur, die durch
|
||||
vorhandene \acs{XML} Definitionen angegeben wurde. Diese Unterschiede werden dann durch atomare \acs{SQL} Operationen wiedergespiegelt.
|
||||
Zusätzlich priorisiert \ac{M2} deklarative Schemen und führt diese generell vor allen älteren Schema \ac{PHP} Scripten aus.
|
||||
|
||||
Die bestehende Datenbank wurde durch o.g. vorgehen um eine Basis-Tabelle erweitert, welche zur Nachvollziehbarkeit der Import-Vorgänge beitragen soll.
|
||||
|
||||
\subsection{Implementierung der Benutzeroberfläche}
|
||||
\label{sec:ImplementierungBenutzeroberflaeche}
|
||||
|
||||
Die Implementierung der Benutzeroberfläche erfolgte, wie bereits im Abschnitt~\ref{sec:Benutzeroberflaeche}: \nameref{sec:Benutzeroberflaeche} geplant,
|
||||
mit Hilfe der \ac{M2} eigenen Möglichkeiten zur Einbindung von \ac{CLI}-Befehlen.
|
||||
|
||||
Durch die Entscheidung des Autors, die Anwendung als \ac{M2} Modul umzusetzen, ergibt sich hier der Vorteil, dass die gewünschten und benötigten
|
||||
\ac{CLI} Befehle per Dependency Injection direkt in die \ac{M2} Befehlsliste aufgenommen werden können. Somit können Entwickler bei der Nutzung der Anwendung
|
||||
auf das Standard Interface von \ac{M2} zurückgreifen und separate Zugangsdaten oder Aufrufe werden vermieden.
|
||||
|
||||
Um der \ac{M2} Instanz die gewünschten Befehle zuzufügen, wurde die Klasse CliCommand der Komponente neusta-m2-intex-cli hinzugefügt. Diese Klasse
|
||||
leitet von der abstrakten \ac{M2} Klasse Command ab und bindet in \ac{M2} inkludierte Symfony-Komponenten zur Verarbeitung von Ein- und Ausgabe ein.
|
||||
|
||||
\subsection{Implementierung der Geschäftslogik}
|
||||
\label{sec:ImplementierungGeschaeftslogik}
|
||||
Da die Implementierung der Geschäftslogik den Kernbestandteil des gesamten Projektes darstellt, soll diese im folgenden Abschnitt
|
||||
genauer erläutert werden. Um die Implementierung möglichst komfortabel durchzuführen, wurde die Entwicklungsumgebung JetBrains PHPStorm 2019 hierfür
|
||||
vom Autor gewählt.
|
||||
|
||||
Zu Beginn der Implementierung wurde das Grundgerüst der Komponenten für die Anwendung erstellt. Hierzu wurde für jede in
|
||||
Abschnitt~\ref{sec:Geschaeftslogik}: \nameref{sec:Geschaeftslogik} erwähnte Komponente und Subkomponente die Grundlage zur Einbindung als
|
||||
Composer Package gelegt. Jede Komponente beinhaltet eine \acs{JSON} Datei, die Angaben zum Namen des Packages, der Version, einer Package-Typ Definition
|
||||
(hier: magento2-module), Abhängigkeiten zu anderen Packages sowie Informationen zum Autor beinhaltet (Beispiel: \Anhang{app:ComposerJson}). Somit konnten die Komponenten
|
||||
im einzelnen als separates Projekt angesehen werden.
|
||||
|
||||
Nachdem die Grundlagen zur Aufteilung der Anwendung in modulare Komponenten gelegt wurde, befasste sich der Autor damit, die lokale Entwicklungsumgebung aufzusetzen.
|
||||
Hierzu wurde ein für \ac{M2} bereits vorhandenes Docker \footnote{Docker - \url{https://www.docker.com}} Setup der \ac{NSD} genutzt. Docker ist ein \ac{VM} Container System, welches im genutzten Setup Container für
|
||||
jeweils den Quellcode der \ac{M2} Instanz, der Datenbank sowie dem benötigten NGINX \footnote{NGINX - \url{https://www.nginx.com/}} Server bereit stellt. Dem Autor wurde hiermit ein natives Aufsetzen einer \ac{M2} Instanz
|
||||
erspart, was zur Qualität der Entwicklung erheblich beitrug und gleichzeitig garantiert, dass die Anwendung auf der tatsächlichen Serverumgebung lauffähig ist.
|
||||
|
||||
Nach der Fertigstellung des Grundgerüstes und der lokalen Umgebung konnte mit der eigentlichen Implementierung fortgesetzt werden.
|
||||
|
||||
Wie in Abschnitt~\ref{sec:Entwicklungsprozess}: \nameref{sec:Entwicklungsprozess} beschrieben, entschied der Autor sich für eine agile Umsetzung in einer Mischung
|
||||
aus Kanban und Scrum. Jede einzelne Komponente ergab somit eine Story im Kanban Board, welche nach Scrum Prinzip zusammen mit den Mitarbeitern der \ac{NSD} priorisiert wurden.
|
||||
|
||||
Die Implementierung des Basis Moduls neusta-m2-intex-base wurde zügig Vollzogen, da die Komponente lediglich als Wrapper für alle Funktionen dienen soll.
|
||||
|
||||
Die o.g. Priorisierung gemäß Scrum sah nun vor, dass die Implementierung der Verbindungslogik zu \ac{IX} am wichtigsten ist, da alle weiteren Logik-Komponenten hierrauf aufbauen müssen.
|
||||
Deswegen soll an dieser Stelle die Implementierung der Komponente neusta-m2-intex-client als Beispiel herangezogen werden.
|
||||
|
||||
Zunächst wurde in der \acs{JSON} Datei für Composer definiert, dass neusta-m2-intex-base die Grundabhängigkeit für das Modul darstellt. So wurden duplizierte
|
||||
Einträge in der Konfiguration vermieden, da diese bereits in der Komponente neusta-m2-intex-base inkludiert sind. Zusätzlich besteht eine Abhängigkeit zur Komponente
|
||||
neusta-m2-intex-client-config, da in der Komponente die Konfigurationen für die \ac{IX}-\acs{API} Zugriffe vorgenommen werden sollen. Die Konfigurationen beinhalten neben
|
||||
den Key-Value Paaren zum Mapping der Produkt- und Nutzerattribute auf den \ac{M2} Standard auch die grundlegenden Informationen wie Passwort und Nutzername zur Verbindung
|
||||
mit \ac{IX}.
|
||||
|
||||
Die Aufgabe des neusta-m2-intex-client in der Anwendung soll sein, jegliche Datenverbindung von der entwickelnden Anwendung mit der \ac{IX}-\acs{API}
|
||||
herzustellen und gleichzeitig ein nachvollziehbares Logging dieser Verbindungen und eventuell auftretender Fehler zur Verfügung zu stellen.
|
||||
|
||||
Wie in Abschnitt~\ref{sec:Architekturdesign}: \nameref{sec:Architekturdesign} beschrieben, sah der Entwurf vor, das Factory Design Pattern zu nutzen und so
|
||||
mehrere Instanzen der Verbindungen zu vermeiden. Hierzu wurde in der Komponente neusta-m2-intex-client die Klasse Factory implementiert, welche die Instanziierung
|
||||
der Klassen abbildete, die neusta-m2-intex-client der Anwendung zur Verfügung stellen soll. Der Grundgedanke ist hierbei, dass die Komponente zum Import der Nutzerdaten
|
||||
(hier: neusta-m2-intex-customer) die Factory des neusta-m2-intex-client nutzen und so seine Verbindung zu \ac{IX} herstellen lassen kann. Der Quellcode der Factory kann
|
||||
dem \Anhang{app:Factory} entnommen werden.
|
||||
|
||||
Um Requests zur \ac{IX}-\acs{API} zu verarbeiten, entschied der Autor, den Open Source \ac{HTTP} Client GuzzlePhp \footnote{GuzzlePhp - \url{https://github.com/guzzle/guzzle}} zu nutzen. Hierdurch erlangte der Autor die Möglichkeit,
|
||||
asynchrone Requests an die \acs{API} von \ac{IX} zu stellen, ohne einen eigenen \ac{PHP} \acs{HTTP} Client entwickeln zu müssen.
|
||||
|
||||
Die Factory instanziiert nun die beim Aufruf angeforderte Klasse. Hier als Beispiel CustomerConnection (siehe \Anhang{app:CustomerConnection} und \Anhang{app:Connection}), welche im
|
||||
CustomerDataController in der Komponente neusta-m2-intex-customer instanziiert wird (siehe \Anhang{app:CustomerDataController}).
|
||||
|
||||
Durch den Fokus auf das Fertigstellen der neusta-m2-intex-client Komponente, waren alle folgenden Subkomponenten trivialer zu implementieren, da bei einem Datenimport
|
||||
die Abfrage der Daten der Hauptbestandteil einer solchen Anwendung darstellt. Dem folgend wurde vom Autor in Reihenfolge die Logik zur Verarbeitung der erhaltenen Daten
|
||||
implementiert (neusta-m2-intex-customer \& neusta-m2-intex-catalog) sowie die Möglichkeit die Funktionalität über einen \acs{CRON}-Job anstoßen zu können, welche
|
||||
im \ac{M2} Standard per \acs{XML} Datei inkludiert werden kann.
|
|
@ -1,48 +0,0 @@
|
|||
% !TEX root = ../Projektdokumentation.tex
|
||||
\section{Projektplanung}
|
||||
\label{sec:Projektplanung}
|
||||
|
||||
|
||||
\subsection{Projektphasen}
|
||||
\label{sec:Projektphasen}
|
||||
|
||||
Für die Umsetzung des Projektes standen dem Autor 70 Stunden zur Verfügung. Zu Projektbeginn wurden diese auf, wie in der
|
||||
Softwareentwicklung üblich, verschiedene Phasen verteilt, die während der Entwicklung durchlaufen werden.
|
||||
|
||||
Eine grobe Zeitplanung sowie die Hauptphasen lassen sich der Tabelle~\ref{tab:Zeitplanung} entnehmen.
|
||||
Eine Pufferzeit wurde bereits in der Planung der Implementierung inkludiert.
|
||||
Die Hauptphasen werden außerdem noch in kleinere Unterpunkte zerlegt. Eine detaillierte Übersicht der Phasen befindet sich im \Anhang{app:Zeitplanung}.
|
||||
|
||||
\tabelle{Zeitplanung}{tab:Zeitplanung}{ZeitplanungKurz}\\
|
||||
|
||||
\subsection{Ressourcenplanung}
|
||||
\label{sec:Ressourcenplanung}
|
||||
|
||||
Eine genaue Auflistung der verwendeten Ressourcen, welche für das Projekt eingesetzt wurden, kann der Übersicht im
|
||||
\Anhang{app:Ressourcen} entnommen werden. Hiermit sind sowohl Hard- und Softwareressourcen als auch Personal vom Autor berücksichtigt worden.
|
||||
Bei der Auswahl der verwendeten Software wurde darauf geachtet, dass diese kostenfrei (\zB als Open Source) zur Verfügung
|
||||
steht oder die \ac{NSD} bereits Lizenzen für diese besitzt. Hierdurch sollen anfallende Projektkosten so gering wie möglich
|
||||
gehalten werden.
|
||||
|
||||
|
||||
|
||||
\subsection{Entwicklungsprozess}
|
||||
\label{sec:Entwicklungsprozess}
|
||||
|
||||
Bevor mit der Realisierung des Projektes begonnen werden konnte, musste sich der Autor für eine geeignete Vorgehensweise zur Umsetzung entscheiden.
|
||||
Der Autor hat sich auf einen agilen Entwicklungsprozess festgelegt. Hierbei wird in Anlehnung
|
||||
an das Vorgehensmodell Kanban \footnote{Wikipedia Kanban Definition - \url{https://en.wikipedia.org/wiki/Kanban}} gearbeitet, welches durch Elemente des Vorgehensmodells Scrum \footnote{Scrum.org - \url{https://www.scrum.org}} erweitert werden soll.
|
||||
Die für Scrum typischen Iterationen der Projektphasen sowie die damit verbundene, stetige Rücksprache
|
||||
mit den Stakeholdern sind einige Merkmale, die diesen agilen Entwicklungsprozess auszeichnen und in diesem Abschlussprojekt Anwendung finden.
|
||||
|
||||
Eine flexible Umsetzung der Anforderung wird durch die relativ kurzen Entwicklungszyklen ermöglicht. Hierdurch können den Mitarbeitern der \ac{NSD}
|
||||
zeitnah Resultate präsentiert werden. Aufgrund dieser Tatsache wurde bei der Projektplanung in Abschnitt~\ref{sec:Projektphasen}: \nameref{sec:Projektphasen} für die Entwurfsphase
|
||||
weniger Zeit eingeplant, da sich Teile dieser Phase erst im Laufe der Entwicklung der Anwendung ergeben.
|
||||
|
||||
Das stetige Feedback zur Anwendung, resultierend aus der engen Kommunikation mit den Mitarbeitern, gewährleistet eine bessere und flexiblere Reaktionsfähigkeit
|
||||
auf Änderungswünsche. So können die Kollegen des Autors während der Entwicklung mit dem System vertraut gemacht werden, welches zur Folge den Vorteil bringt,
|
||||
dass bei Projektabnahme und -einführung Zeit eingespart werden kann. Dies wurde vom Autor in der Zeitkalkulation bereits berücksichtigt.
|
||||
|
||||
Außerdem soll der agile Entwicklungsprozess durch die Praktik der testabgedeckten Entwicklung erweitert werden. Hierbei werden Softwaretests nach der Implementierung
|
||||
des Quellcodes erstellt. Dies hat zum Vorteil, dass nachträgliche Änderungen immer das gleiche Endresultat in der Datenausgabe erwarten und erhöht somit die Wartbarkeit
|
||||
der gesamten Anwendung.
|
|
@ -1,139 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Neusta\IntexClient\Connection\Model;
|
||||
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Neusta\IntexClientConfig\Model\Config\Config;
|
||||
use Neusta\IntexClientConfig\Provider\JsonConfigProvider;
|
||||
use \GuzzleHttp\Client as GuzzleHttpClient;
|
||||
use \GuzzleHttp\Event\BeforeEvent;
|
||||
use \GuzzleHttp\Event\CompleteEvent;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
abstract class Connection
|
||||
{
|
||||
protected const HTTP_STATUS_CODE_OK = 200;
|
||||
|
||||
/**
|
||||
* @var GuzzleHttpClient
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
protected $serverConfig;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct(JsonConfigProvider $configProvider, LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->serverConfig = $configProvider->getConfig('server');
|
||||
$this->httpClient = new GuzzleHttpClient(
|
||||
$this->getHttpClientOptions()
|
||||
);
|
||||
|
||||
$this->initHttpEventEmitter();
|
||||
}
|
||||
|
||||
protected function authenticate(): bool
|
||||
{
|
||||
$result = false;
|
||||
|
||||
$response = $this->createPost(
|
||||
$this->serverConfig->getAuthUri()
|
||||
);
|
||||
|
||||
$statusCode = $response->getStatusCode();
|
||||
|
||||
if ($statusCode === self::HTTP_STATUS_CODE_OK) {
|
||||
$this->logger->info('authentication successful');
|
||||
$result = true;
|
||||
} else {
|
||||
$this->logger->info(
|
||||
sprintf('authentication failed with Code: %s', $statusCode)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function createPost(string $uri, array $options = []): ?ResponseInterface
|
||||
{
|
||||
$result = null;
|
||||
$request = $this->httpClient->postAsync($uri, $options);
|
||||
|
||||
$request->then(
|
||||
static function (ResponseInterface $response) {
|
||||
$result = $response;
|
||||
},
|
||||
function (RequestException $exception) {
|
||||
$this->logger->info(
|
||||
sprintf('Crucial Error: %s \n Trace: %u', $exception->getMessage(), $exception->getTraceAsString())
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function createGet(string $uri, array $options = []): ?ResponseInterface
|
||||
{
|
||||
$result = null;
|
||||
$request = $this->httpClient->getAsync($uri, $options);
|
||||
|
||||
$request->then(
|
||||
static function (ResponseInterface $response) {
|
||||
$result = $response;
|
||||
},
|
||||
function (RequestException $exception) {
|
||||
$this->logger->info(
|
||||
sprintf('Crucial Error: %s \n Trace: %u', $exception->getMessage(), $exception->getTraceAsString())
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function initHttpEventEmitter(): void
|
||||
{
|
||||
// initialize the EventEmitters to get a good Logging whether the Request was send
|
||||
// or failed
|
||||
$this->httpClient->getEmitter()->on('before', static function (BeforeEvent $event) {
|
||||
$this->logger->info(
|
||||
sprintf('About to send Request: %s', $event->getRequest())
|
||||
);
|
||||
});
|
||||
|
||||
$this->httpClient->getEmitter()->on('complete', static function (CompleteEvent $event) {
|
||||
$this->logger->info(
|
||||
sprintf('Request %s finished', $event->getRequest())
|
||||
);
|
||||
});
|
||||
|
||||
$this->httpClient->getEmitter()->on('error', static function (ErrorEvent $event) {
|
||||
$this->logger->info(
|
||||
sprintf('Request %s failed', $event->getRequest())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
protected function getHttpClientOptions(): array
|
||||
{
|
||||
// Configure Base URL for all ongoing Requests and set Cookies to true,
|
||||
// so we can handle the auth cookie over and over again without using authenticate() multiple times
|
||||
return [
|
||||
'base_url' => $this->serverConfig->getBaseUrl(),
|
||||
'cookies' => true
|
||||
];
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Neusta\IntexClient\Connection\Model;
|
||||
|
||||
|
||||
use Neusta\IntexClientConfig\Model\Config\Config;
|
||||
use Neusta\IntexClientConfig\Provider\JsonConfigProvider;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function json_decode;
|
||||
|
||||
class CustomerConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* @var Config
|
||||
*/
|
||||
private $customerConfig;
|
||||
|
||||
public function __construct(JsonConfigProvider $configProvider, LoggerInterface $logger)
|
||||
{
|
||||
parent::__construct($configProvider, $logger);
|
||||
$this->customerConfig = $configProvider->getConfig('customer');
|
||||
}
|
||||
|
||||
public function loadCustomerData(): array
|
||||
{
|
||||
$response = $this->createGet(
|
||||
$this->customerConfig->getCustomerUri()
|
||||
);
|
||||
|
||||
return json_decode($response->getBody(), true);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
|
||||
namespace Neusta\IntexCustomer\Controller;
|
||||
|
||||
|
||||
use Neusta\IntexClient\Connection\Model\CustomerConnection;
|
||||
|
||||
class CustomerDataController
|
||||
{
|
||||
/**
|
||||
* @var CustomerConnection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
public function __construct(\Neusta\IntexClient\Connection\Factory $connectionFactory, \Neusta\IntexCustomer\Handler\DataHandler $dataHandler)
|
||||
{
|
||||
$this->connection = $connectionFactory->create('customer');
|
||||
$this->customerDataHandler = $dataHandler;
|
||||
}
|
||||
|
||||
public function getCustomerData(): void
|
||||
{
|
||||
$customerData = $this->connection->loadCustomerData();
|
||||
|
||||
$this->customerDataHandler->saveCustomerData($customerData);
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Neusta\IntexClient\Connection;
|
||||
|
||||
use Neusta\IntexClient\Connection\Model\Connection;
|
||||
|
||||
use function class_exists;
|
||||
use function sprintf;
|
||||
use function ucwords;
|
||||
use function strtolower;
|
||||
|
||||
class Factory
|
||||
{
|
||||
public static function create(string $connectionType): Connection
|
||||
{
|
||||
$connectionPath = sprintf(
|
||||
'\Neusta\IntexClient\Model\Connection\%sConnection',
|
||||
ucwords(strtolower($connectionType))
|
||||
);
|
||||
|
||||
if (class_exists($connectionPath)) {
|
||||
return new $connectionPath();
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Invalid Connection Type given');
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" ?>
|
||||
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
|
||||
<table name="neusta_intex_import" resource="default" engine="innodb"
|
||||
comment="Neusta IntexImport Logging Table">
|
||||
<column xsi:type="int" name="value_id" padding="11" unsigned="false" nullable="false" identity="true" comment="Value ID"/>
|
||||
<column xsi:type="smallint" name="attribute_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Attribute ID"/>
|
||||
<column xsi:type="smallint" name="store_id" padding="5" unsigned="true" nullable="false" identity="false" default="0" comment="Store ID"/>
|
||||
<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="false" default="0" comment="Entity ID"/>
|
||||
<column xsi:type="datetime" name="value" on_update="false" nullable="true" comment="Value"/>
|
||||
<constraint xsi:type="primary" referenceId="PRIMARY">
|
||||
<column name="value_id"/>
|
||||
</constraint>
|
||||
<constraint xsi:type="foreign" referenceId="CAT_PRD_ENTT_DTIME_ATTR_ID_EAV_ATTR_ATTR_ID" table="catalog_product_entity_datetime" column="attribute_id" referenceTable="eav_attribute" referenceColumn="attribute_id" onDelete="CASCADE"/>
|
||||
<constraint xsi:type="foreign" referenceId="CAT_PRD_ENTT_DTIME_ENTT_ID_CAT_PRD_ENTT_ENTT_ID" table="catalog_product_entity_datetime" column="entity_id" referenceTable="catalog_product_entity" referenceColumn="entity_id" onDelete="CASCADE"/>
|
||||
<constraint xsi:type="foreign" referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_STORE_ID_STORE_STORE_ID" table="catalog_product_entity_datetime" column="store_id" referenceTable="store" referenceColumn="store_id" onDelete="CASCADE"/>
|
||||
<constraint xsi:type="unique" referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_ENTITY_ID_ATTRIBUTE_ID_STORE_ID">
|
||||
<column name="entity_id"/>
|
||||
<column name="attribute_id"/>
|
||||
<column name="store_id"/>
|
||||
</constraint>
|
||||
<index referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_ATTRIBUTE_ID" indexType="btree">
|
||||
<column name="attribute_id"/>
|
||||
</index>
|
||||
<index referenceId="CATALOG_PRODUCT_ENTITY_DATETIME_STORE_ID" indexType="btree">
|
||||
<column name="store_id"/>
|
||||
</index>
|
||||
</table>
|
||||
</schema>
|
|
@ -1,39 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Neusta\IntexClient\Connection\Factory;
|
||||
use Neusta\IntexClient\Connection\Model\CustomerConnection;
|
||||
|
||||
class FactoryTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Factory
|
||||
*/
|
||||
private $subject;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->subject = new Factory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function createMustReturnInstanceOfCustomerConnectionWithValidIdentifierGiven()
|
||||
{
|
||||
$expectedInstance = $this->subject->create('customer');
|
||||
|
||||
self::assertInstanceOf(CustomerConnection::class, $expectedInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function createMustThrowRuntimeExceptionIfInvalidIdentifierIsGiven()
|
||||
{
|
||||
$unexpectedInstance = $this->subject->create('fooBar');
|
||||
|
||||
self::expectException(RuntimeException::class);
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "neusta/m2-intex-client",
|
||||
"license": "proprietary",
|
||||
"description": "Client for Magento2 Intex Import/Export",
|
||||
"type": "magento2-module",
|
||||
"version": "0.0.1",
|
||||
"require": {
|
||||
"php": "7.4.33",
|
||||
"magento/framework": "~101.0",
|
||||
"neusta/m2-intex-base": "0.0.1",
|
||||
"guzzlehttp/guzzle": "6.5.*"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"registration.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Neusta\\IntexClient\\": "src"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
include(dirname(__FILE__).'/../bootstrap/Propel.php');
|
||||
|
||||
$t = new lime_test(13);
|
||||
|
||||
$t->comment('Empty Information');
|
||||
$emptyComparedInformation = new ComparedNaturalModuleInformation(array());
|
||||
$t->is($emptyComparedInformation->getCatalogSign(), ComparedNaturalModuleInformation::EMPTY_SIGN, 'Has no catalog sign');
|
||||
$t->is($emptyComparedInformation->getSourceSign(), ComparedNaturalModuleInformation::SIGN_CREATE, 'Source has to be created');
|
||||
|
||||
$t->comment('Perfect Module');
|
||||
$criteria = new Criteria();
|
||||
$criteria->add(NaturalmodulenamePeer::NAME, 'SMTAB');
|
||||
$moduleName = NaturalmodulenamePeer::doSelectOne($criteria);
|
||||
$t->is($moduleName->getName(), 'SMTAB', 'Right modulename selected');
|
||||
$comparedInformation = $moduleName->loadNaturalModuleInformation();
|
||||
$t->is($comparedInformation->getSourceSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Source sign shines global');
|
||||
$t->is($comparedInformation->getCatalogSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Catalog sign shines global');
|
||||
$infos = $comparedInformation->getNaturalModuleInformations();
|
||||
foreach($infos as $info)
|
||||
{
|
||||
$env = $info->getEnvironmentName();
|
||||
$t->is($info->getSourceSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Source sign shines at ' . $env);
|
||||
if($env != 'SVNENTW')
|
||||
{
|
||||
$t->is($info->getCatalogSign(), ComparedNaturalModuleInformation::SIGN_OK, 'Catalog sign shines at ' . $info->getEnvironmentName());
|
||||
}
|
||||
else
|
||||
{
|
||||
$t->is($info->getCatalogSign(), ComparedNaturalModuleInformation::EMPTY_SIGN, 'Catalog sign is empty at ' . $info->getEnvironmentName());
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -53,12 +53,6 @@
|
|||
\pagenumbering{arabic}
|
||||
\input{Inhalt.tex}
|
||||
|
||||
% Literatur ------------------------------------------------------------------
|
||||
\clearpage
|
||||
\renewcommand{\refname}{Literaturverzeichnis}
|
||||
\bibliography{Bibliographie}
|
||||
\bibliographystyle{Allgemein/natdin} % DIN-Stil des Literaturverzeichnisses
|
||||
|
||||
% Anhang ---------------------------------------------------------------------
|
||||
\clearpage
|
||||
\appendix
|
||||
|
|
21
texput.log
Normal file
|
@ -0,0 +1,21 @@
|
|||
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2025.6.5) 12 JUN 2025 19:40
|
||||
entering extended mode
|
||||
restricted \write18 enabled.
|
||||
%&-line parsing enabled.
|
||||
**Projektdokumentation.tex
|
||||
|
||||
! Emergency stop.
|
||||
<*> Projektdokumentation.tex
|
||||
|
||||
End of file on the terminal!
|
||||
|
||||
|
||||
Here is how much of TeX's memory you used:
|
||||
3 strings out of 478287
|
||||
131 string characters out of 5849290
|
||||
289007 words of memory out of 5000000
|
||||
18302 multiletter control sequences out of 15000+600000
|
||||
469259 words of font info for 28 fonts, out of 8000000 for 9000
|
||||
1141 hyphenation exceptions out of 8191
|
||||
0i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,80000s
|
||||
! ==> Fatal error occurred, no output PDF file produced!
|