517cbebf1b
Signed-off-by: Nico Schottelius <nico@ikn.schottelius.org>
1672 lines
59 KiB
TeX
1672 lines
59 KiB
TeX
% header
|
||
% Dies ist version-0.9.8 der IHK Doku [FINAL]
|
||
% let's go...
|
||
%\documentclass[10pt,a4paper,ngerman]{article}
|
||
\documentclass[11pt,a4paper]{article}
|
||
\usepackage[latin1]{inputenc} % Ascii-Format dieses Dokuments
|
||
%\usepackage{babel} % neue deutsche Rechtschreibung
|
||
% Teutsch
|
||
\usepackage{german}
|
||
% lange Tabellen
|
||
\usepackage{longtable}
|
||
% pagestyle..
|
||
\usepackage{fancyhdr}
|
||
\pagestyle{fancy}
|
||
%\fancyhf{} % bisherige Kopf- und Fusszeilen loeschen
|
||
\fancyhead[R]{Nico Schottelius} % rechter Kopfzeileneintrag
|
||
%\fancyhead[L]{Projekdokumentation} % linker Kopfzeileneintrag
|
||
%\fancyhead[L]{\thepage} % linker Kopfzeileneintrag
|
||
%\fancyfoot[C]{\thepage} % Fusszeileneintrag (Seitenzahl zentriert)
|
||
\renewcommand{\headrulewidth}{0.4pt} % Strichstaerke unter der Kopfzeile
|
||
% let's start
|
||
\begin{document}
|
||
\title{Projektdokumentation: Webzugriff auf eine Datenbank via PHP}
|
||
\date{01.03.2004 - 30.04.2004}
|
||
\author{
|
||
Nico Schottelius\\
|
||
Rodenstra\ss{}e 12\\
|
||
30826 Garbsen\\
|
||
nico-ihk@schottelius.org\\
|
||
\\
|
||
Ausbildungsbetrieb:\\
|
||
Wirtschaftsgenossenschaft deutscher Tier\"arzte eG\\
|
||
Siemensstra\ss{}e 14\\
|
||
30827 Garbsen\\
|
||
http://www.wdt.de\\
|
||
}
|
||
% Title
|
||
\maketitle
|
||
\newpage
|
||
% Inhaltsverzeichnis
|
||
\tableofcontents
|
||
\newpage
|
||
\section{Pers\"onliche Erkl\"arung}
|
||
Ich versichere durch meine Unterschrift, dass ich die betriebliche Projektarbeit
|
||
und die dazugeh\"orige Dokumentation selbst\"andig in der vorgegebenen Zeit
|
||
erarbeitet habe. Ich habe keine anderen als die von mir angegebenen Quellen und
|
||
Hilfsmittel verwendet.\\
|
||
\begin{verbatim}
|
||
|
||
|
||
\end{verbatim}
|
||
\begin{tabbing}
|
||
xxxxxxxxxxxxxxxxx\=xxxxxxxxx\kill
|
||
$\overline{\mbox{\large{Ort, Datum}}}$
|
||
\>$\overline{\mbox{\large{Unterschrift des Pr\"uflings}}}$\\
|
||
\end{tabbing}
|
||
\begin{verbatim}
|
||
|
||
\end{verbatim}
|
||
Zur Kenntnis genommen:
|
||
\begin{verbatim}
|
||
|
||
|
||
\end{verbatim}
|
||
$\overline{\mbox{\large{Ausbilder/-in}}}$
|
||
\newpage
|
||
\section{Einleitung}
|
||
\subsection{Projektumfeld}
|
||
Das Projekt fand in der Wirtschaftsgenossenschaft deutscher Tier\"arzte eG
|
||
("`\textit{WDT}"') am Standort in Garbsen statt. Die WDT liefert Arzneimittel und
|
||
medizinisches Zubeh\"or f\"ur tier\"arztliche Praxen in ganz Deutschland. Zur Zeit
|
||
arbeiten circa 170 Mitarbeiter an drei Firmenstandorten, davon sind 14
|
||
Aussendienstmitarbeiter ("`\textit{ADM}"') in der Kundenbetreuung t\"atig. Ein
|
||
Gro\ss{}teil der Arbeitsabl\"aufe wird durch das
|
||
\textit{ERP-System}\footnote{ERP-System: Enterprise Resource Planing System}
|
||
unterst\"utzt.
|
||
So erfolgt die gesamte Auftragsbearbeitung, die Kommissionierung, der Versand,
|
||
der Einkauf sowie die Buchhaltung mit Hilfe dieses Systems.
|
||
Die Aussendiensmitarbeiter erhalten monatlich einen f\"ur sie relevanten,
|
||
individuellen Auszug aus der Datenbank.
|
||
\subsection{Ist-Zustand}
|
||
Zur Zeit werden Informationen zur Planung der Kundenberatung an die
|
||
Aussendienstmitarbeiter als \textit{Excel-Tabelle}\footnote{Excel ist ein Produkt
|
||
von Microsoft. Excel-Tabellen stellen ein properit\"ares Format zur Speicherung
|
||
von Tabellen dar}
|
||
via E-Mail versandt. Aufgrund der Verbindungsart
|
||
(\textit{HSCSD/GSM}\footnote{GSM ist die Technik die zum Verbinden der
|
||
Mobiltelefone verwendet wird, HSCSD ist die Daten\"ubertragung \"uber GSM}, ISDN
|
||
oder Modem) und der Gr\"o\ss{}e (circa 16 \textit{MiB}\footnote{KiB, MiB, GiB
|
||
sind Alternativbezeichnungen zu KB, MB und GB. Bei der
|
||
Verwendung von den letztern ist nicht klar, ob der Faktor 1000 oder 1024 gemeint
|
||
ist, 1024Byte entsprechen \textbf{immer} 1KiB. So sind z.B. manche 80GB Platten
|
||
nur 80000000000 Byte gross, was 74,51GiB entspricht.})
|
||
der Datei kommt es zu Problemen bei der \"Ubertragung. Diese Probleme
|
||
\"au\ss{}ern sich wie folgt:
|
||
\begin{itemize}
|
||
\item der Transfer der Datei dauert sehr lange (\"uber 30 Minuten)
|
||
\item durch eine Zwangstrennung im Funknetz nach 30 Minuten kann die Datei nicht
|
||
vollst\"andig \"ubertragen werden
|
||
\end{itemize}
|
||
Da E-Mail ein
|
||
\textit{Push-System}\footnote{Als "`Push-Systeme"' werden Systeme bezeichnet,
|
||
die die Informationen ohne Aufforderung des Benutzers zu selbigen senden
|
||
(neben E-Mail auch z.B. Plakate). Bei "`Pull-Sytemen"' hingegen muss der
|
||
Benutzer interaktiv die Informationen anfordern (z.B. Webseite).} ist,
|
||
ergibt sich zus\"atzlich das Problem, dass grunds\"atzlich in dreifacher
|
||
Hinsicht unn\"otige Daten \"ubertragen werden k\"onnen:
|
||
\begin{enumerate}
|
||
\item der ADM ben\"otigt die Informationen z.Z. nicht:
|
||
komplett unn\"otiger Versand.\\
|
||
Eine Filterung nach Anforderung ist mit dem momentanen System schwer zu realisieren
|
||
und k\"onnte bestenfalls manuell mit R\"ucksprache geschehen.
|
||
\item selbst wenn sich die Daten nicht ge\"andert haben, wird ein Update versandt\\
|
||
Dies hat zwei Gr\"unde:
|
||
\begin{enumerate}
|
||
\item die regelm\"assig empfangene E-Mail ist ein
|
||
Indiz f\"ur den ADM, dass das System ordnungsgem\"ass{} funktioniert
|
||
\item zum Zweiten wird keine Versionsverwaltung betrieben, sondern die
|
||
Excel-Tabellen jedes Mal komplett neu generiert
|
||
\end{enumerate}
|
||
\item Der ADM ben\"otigt nur einen Teil der Daten, bekommt
|
||
jedoch immer eine vorgefertigte Version mit gro\ss{}em Umfang (Daten\"uberfluss)
|
||
\item Bei jeder Aktualisierung werden auch die unver\"anderten Stammdaten
|
||
transferiert
|
||
\end{enumerate}
|
||
\subsection{Soll-Zustand}
|
||
Auf den Transfer via E-Mail soll grunds\"atzlich verzichtet und der
|
||
Zugriff in ein Pull-System umgewandelt werden.
|
||
Der Zugriff soll \"uber das
|
||
Internet auf ein Webinterface geschehen. Die Implementation muss auf dem
|
||
\textit{LAMP-System}\footnote{LAMP ist die Abk\"urzung f\"ur ein \textbf{L}inux,
|
||
\textbf{A}pache, \textbf{M}ySQL, \textbf{P}HP Kombination, wobei Linux das
|
||
Betriebssystem, Apache der Webserver, MySQL die Datenbank und PHP die
|
||
Programmiersprache ist.}
|
||
des Providers lauff\"ahig sein. Dazu soll ein m\"oglichst identisches Testsystem
|
||
intern verf\"ugbar sein. Die Daten m\"ussen aus dem ERP-System in einem
|
||
f\"ur MySQL importf\"ahigen Format bereitgestellt werden. Die entsprechenden
|
||
Aufgaben sollen gem\"a\ss{} der Qualifizierung der Mitarbeiter delegiert werden:
|
||
\begin{itemize}
|
||
\item das LAMP-System soll durch die Systemintegration bereitgestellt werden
|
||
\item der Export der Daten aus dem ERP-System soll durch die hauseigenen
|
||
Programmierer bereitgestellt werden
|
||
\item die Erstellung des Webzugriffs und der Dokumentation (inklusive Handbuch
|
||
f\"ur Benutzer und Entwickler, Schnittstellendefinitionen und Pflichtenheft) soll
|
||
vom Pr\"ufling erledigt werden
|
||
\end{itemize}
|
||
Ziel ist es, ein verwendbares System zu entwickeln und die Machbarkeit zu beweisen.
|
||
\section{Planung}
|
||
\subsection{Ablauf des Projektes}
|
||
Zu Beginn des Projektes wurden die Projektgrundsteine "`gelegt"':
|
||
\begin{enumerate}
|
||
\item es wurde ein Zeitplan f\"ur die einzelnen Phasen festgelegt, inklusive der
|
||
Festlegung von Besprechungsterminen
|
||
\item es wurden f\"ur die einzelnen Teams Schnittstellen definiert, damit diese
|
||
unabh\"angig voneinander arbeiten konnten und um eine klare Trennung zwischen den
|
||
einzelnen Modulen zu schaffen
|
||
\end{enumerate}
|
||
\subsection{Schnittstellendefinition}
|
||
Durch den sauberen Einsatz von Schnittstellen kann zum Beispiel ein Mitarbeiter
|
||
die Daten aus dem ERP-System auslesen und sie in einem definierten Format
|
||
speichern, w\"ahrend ein anderer schon die Umwandlung in die neue Datenbank
|
||
mit Hilfe von Testdaten programmiert. \\
|
||
Es sollen folgende Schnittstellendefinitionen erzeugt werden:
|
||
\begin{enumerate}
|
||
\item Benutzer/Weboberfl\"ache: Layoutdefiniton
|
||
\item Weboberfl\"ache/Datenbank: Zugriffsdefiniton
|
||
\item Datenbank/Quelldaten: Importformatdefiniton
|
||
\end{enumerate}
|
||
\subsection{Kompatibilit\"at}
|
||
Die Skripte m\"ussen ein identisches Verhalten auf dem Testsystem und auf dem
|
||
Echtsystem vorweisen. Um dies zu gew\"ahrleisten sind Modifizierungen, die im
|
||
Rahmen der Installation von Programmen als normal zu betrachten sind
|
||
(z.B. Pfad-, Limitierungs- oder Namensmodifikationen), n\"otig.
|
||
Das Erscheinungsbild dem Benutzer gegen\"uber soll soweit wie m\"oglich
|
||
identisch bleiben.
|
||
Eine Absprache mit dem \textit{ISP}\footnote{Internet Service Provider
|
||
bieten Internetanbindungen und Service an}
|
||
soll vor Beginn der Entwicklung stattfinden, damit eventuelle
|
||
Inkompatibilit\"aten vermieden werden k\"onnen.\\
|
||
Ein System, das nur In-House funktioniert, w\"are f\"ur die bestehende Situation keine
|
||
ad\"aquate L\"osung. Da die Kompatibilit\"at ein wichtiger Punkt im Rahmen des
|
||
Projektes ist, wurde diese in einer eigenen Schnittstelle definiert
|
||
("`Test /Echtsystem"').
|
||
\subsection{Layout (Benutzerschnittstelle)}
|
||
Das Layout muss vor Beginn der Entwicklung der Weboberfl\"ache definiert sein
|
||
und den spezifischen Anforderungen entsprechen. An dieses Layout sollen
|
||
s\"amtliche Skripte angepasst sein.
|
||
\section{Durchf\"uhrung}
|
||
\subsection{Erzeugen des PHP Such-Skripts}
|
||
Das PHP Skript wurde nach der Vorlage des Excel Dokumentes erzeugt. Zuerst
|
||
wurde das Skript monolithisch erzeugt, d.h. es enthielt keinerlei Module und
|
||
s\"amtliche Einstellungen waren in dem Skript selbst zu finden. Da sich
|
||
schnell herausstellte, dass eine solche Struktur schlecht zu erweitern ist,
|
||
wurde das Skript in mehrere Teile aufgeteilt, welche wiederum modularisiert sind.
|
||
Die Module wurden in ein Unterverzeichnis "`modules"' verschoben.
|
||
Konfigurationen k\"onnen nun zentral in den dazu passenden Dateien im
|
||
"`includes"' Verzeichnis vorgenommen werden.
|
||
Es soll die M\"oglichkeit geben, dass die Skripte sp\"ater extern gepflegt oder
|
||
erweitert werden. Da dies auch durch Dienstleistungen ausl\"andischer Firmen
|
||
geschehen k\"onnte, sind die Kommentare in Englisch. Da ein Gro\ss{}teil der
|
||
technischen Literatur in
|
||
Englisch geschrieben ist, werden deutsche Informatiker mit den englischen
|
||
Kommentaren keine Probleme haben.
|
||
Mit einigen Problemen behaftet war der Wechsel von Apache 1.3 zu Apache 2.0.
|
||
Der Letztere setzt keine globalen Variablen, wenn selbige durch eine Form
|
||
an ein PHP Skript gesendet werden. Dadurch musste nach dem Wechsel der Inhalt der
|
||
Formvariablen aus einem speziellen Parameterarray namens "`\_REQUEST"' ausgelesen
|
||
werden.
|
||
\subsection{Erzeugen des Importfilters}
|
||
Der Importfilter ist dem Layout des Hauptskriptes, und damit der allgemeinen
|
||
Definition, nachempfunden. Er wurde ebenfalls in PHP geschrieben und importiert
|
||
die hochgeladenen ASCII Tabellen in die MySQL Datenbank. Das Format der
|
||
ASCII-Tabellen wurde in der entsprechenden Schnittstellendefinition hinterlegt. \\
|
||
Das Standardverhalten bei identischen Primary Key Feldern ist, den alten Wert mit
|
||
dem neuen zu \"uberschreiben. Die Alternative, Werte zu addieren ist nur in
|
||
wenigen F\"allen sinnvoll und w\"urde in der praktischen Anwendung zu komplizierten
|
||
Abh\"angigkeiten und einigen zus\"atzlichen Definitionen und Tests f\"uhren. So
|
||
m\"usste man z.B. Felder wie die Postleitzahl oder die Telefonnummer gesondert
|
||
behandeln. Ebenfalls problematisch w\"are das Ergebnis, wenn jemand aus Versehen
|
||
zweimal den Upload Knopf bet\"atigt und somit zum Beispiel den Umsatz f\"ur
|
||
einen bestimmten Zeitraum verdoppelt. \\
|
||
Problematisch ist auch das Standardverhalten von PHP, welches nur eine maximale
|
||
Dateigr\"o\ss{}e von 2MiB vorsieht und einem Skript nur 8MiB Arbeitsspeicher
|
||
erlaubt. Wenn die Dateien dieses Limit \"uberschreiten, erzeugt PHP keine
|
||
Fehlermeldung, sondern ignoriert die hochzuladende Datei
|
||
(verifiziert bei PHP 4.3.4 und 4.3.5RC3).
|
||
\subsection{Erzeugen des Initialdatenbankgenerators}
|
||
Zur Vereinfachung der Arbeit wurde zus\"atzlich ein Skript eingerichtet, welches
|
||
eine initiale Datenbank mit den entsprechenden Tabellen anlegt. Die entsprechenden
|
||
Tabellen wurden in den Quelltext integriert, da eine Auslagerung der
|
||
Tabellenspezifikation einen zus\"atzlichen Parser erfordert h\"atte.
|
||
\subsection{Transfer in das Echtsystem}
|
||
Der Transfer in das Echtsystem verlief problemlos.
|
||
Der Einsatz im Echtsystem wurde mit dem ISP der WDT abgesprochen und
|
||
getestet.
|
||
Zuerst wurden die Sicherheitseinstellungen transferiert.
|
||
Danach wurden die PHP-Skripte hochgeladen, welche dann gleich zur Initialisierung der
|
||
Datenbank und dem Transfer der Echtdaten benutzt wurden. Da die Verbindung
|
||
\"uber das \textit{HTTPS}\footnote{Sicheres, verschl\"usselt \"ubertragen von
|
||
Dateien; Alternative zu HTTP} Protokoll erfolgt, sind die Daten w\"ahrend des
|
||
Transfers verschl\"usselt und f\"alschungssicher.
|
||
Die maximale Dateigr\"o\ss{}e f\"ur einen Upload durch PHP ist beim ISP
|
||
auf 8MB beschr\"ankt.
|
||
Deswegen mussten die Umsatz Tabellen, die pro Jahr eine Gr\"o\ss{}e von 22MiB
|
||
haben, aufgeteilt werden.
|
||
\section{Dokumentationsphase}
|
||
\subsection{Erstellen der Programmdokumentation}
|
||
Die Programmdokumentation ist f\"ur die Verwendung durch Entwickler und
|
||
Administratoren konzipiert und enth\"alt technische Fachbegriffe.
|
||
Sie wurde in Stichw\"ortern w\"ahrend der Durchf\"uhrungsphase niedergeschrieben
|
||
und danach zusammengefasst in ein Latex-Dokument. \textit{Latex}\footnote{
|
||
Siehe auch die deutsche TeX Webseite http://www.dante.de} ist ein Textsatzsystem,
|
||
welches insbesondere f\"ur wissenschaftliche und technische Dokumentation verwendet
|
||
wird. Die Programmdokumentation ist entsprechend der Bed\"urfnisse von
|
||
Administratoren und Entwicklern gegliedert und aufgebaut. Dies bedeutet z.B.,
|
||
dass der Administrator schnell die entsprechenden Sektionen zur Installation
|
||
und der Entwickler ebenso einfach den Aufbau der Programme finden kann.
|
||
Als Ausgabeformat wurde PDF gew\"ahlt, da dieses Format auf jeder Plattform
|
||
lesbar ist.
|
||
\subsection{Erstellen des Benutzerhandbuches}
|
||
Das Benutzerhandbuch wurde nach der Durchf\"uhrung erstellt. Dadurch
|
||
wurde garantiert, dass die Screenshots der Oberfl\"ache sich nicht mehr
|
||
ver\"andern k\"onnen. Vom Aufraggeber wurde eine Dokumentation gefordert, die den
|
||
Ablauf m\"oglichst pr\"azise und zugleich simpel beschreibt. Dies wurde durch den
|
||
Einsatz von Screenshots bewerkstelligt. Als Ausgabeformat wurde eine
|
||
Pr\"asentation (entweder im \textit{PowerPoint oder OpenOffice}\footnote{
|
||
PowerPoint ist ein Programm aus der Programmgruppe "`Microsoft Office"' von
|
||
Microsoft, OpenOffice ist ein OpenSource Konkurrenzprodukt zu Microsoft Office}
|
||
Format) gew\"ahlt, da in einer Pr\"asentation wie in einem Buch am Bildschirm
|
||
gebl\"attert werden kann.
|
||
\subsection{Erstellen der IHK-Projektdokumentation}
|
||
Bei der Erstellung dieser Dokumentation wurde \"ahnlich verfahren wie
|
||
bei der Erstellung der Programmdokumentation. Jedoch wurde diese Dokumentation
|
||
zuerst in OpenOffice geschrieben und nachher in Latex konvertiert, da Latex
|
||
wesentlich effektiver f\"ur die Erstellung von gro\ss{}en Dokumenten ist.
|
||
\section{Testphase}
|
||
\subsection{Testabschnitte w\"ahrend der Erstellung}
|
||
W\"ahrend der Entwicklungsphase wurde die Funktionalit\"at der Skripte mit Hilfe
|
||
einer Datenbank mit Pseudodaten getestet. Da die Anzahl der S\"atze in der
|
||
Datenbank sehr gering war, waren die Ergebnisse schnell verf\"ugbar und es
|
||
musste in Betracht gezogen werden, dass die Arbeit mit Echtdaten wesentlich
|
||
langsamer laufen k\"onnte. Dies best\"atigte sich jedoch nicht, die Auslieferung
|
||
der Daten durch die MySQL Datenbank verlief weiterhin gewohnt schnell. Die Ausgabe
|
||
erfolgte teilweise mit Debug Informationen. Diese beinhalteten z.B.
|
||
Variableninhalte oder R\"uckgabewerte von Funktionen.
|
||
\subsection{Eigentest aller Programme}
|
||
Nach der Entwicklungsphase wurden die Programme auf Funktionalit\"at und saubere
|
||
Ausgaben \"uberpr\"uft. So durften keine Debug-Nachrichten mehr erscheinen und es
|
||
sollten keine Fehler beim "`normalen Benutzen"' auftreten. Es wurde kritisch darauf
|
||
geachtet, dass keine Situation auftritt, die ein normaler Benutzer nicht verstehen
|
||
kann (z.B. Bildschirm ohne Inhalt). Des weiteren wurden generelle Sicherheitsl\"ucken
|
||
\"uberpr\"uft, wie
|
||
\textit{Buffer Overflows, SQL-Injektion und Cross-Site-Scripting}\footnote{Buffer
|
||
Overflows, SQL-Injektion und Cross-Site-Scripting sind
|
||
bekannte Fehler die bei der Programmierung auftreten. Die letzteren beiden
|
||
besonders bei der Programmierung von Skripten mit Webzugriff}.
|
||
\subsection{Fremdtest aller Programme}
|
||
Zum Abschlu\ss{} wurden die Programme von Mitarbeitern aus der EDV Abteilung
|
||
getestet und zus\"atzlich auf Sicherheitsl\"ucken gepr\"uft. Durch diese Hilfe
|
||
konnten Fehler entdeckt werden, die ein Entwickler selbst nicht bemerkt. So
|
||
wurde z.B. bemerkt, dass auf einer Seite ein Teil des Firmenlogos anders angezeigt
|
||
wurde ("`stehende Karawane"', sollte "`bewegte Karawane"' sein).
|
||
\section{Fazit}
|
||
\subsection{R\"uckblick}
|
||
Die Programmierung des Skriptes und die Einrichtung des Apache 2.0 mit PHP 4.3.4
|
||
aus dem Quelltext verliefen ohne Probleme. Dies wurde durch den Einsatz des
|
||
LAMP-Systems gef\"ordert, denn die einzelnen Komponenten,
|
||
Linux, Apache, MySQL und PHP, sind sehr gut aufeinander abgestimmt.
|
||
Einen Gro\ss{}teil der Zeit musste in die Entwicklung der Schnittstellen und
|
||
das Testen investiert werden. \\
|
||
Das Teamwork erleichterte die Entwicklungsarbeit, da durch vorhergehende Schulungen
|
||
und Tipps w\"ahrend der Entwicklung Probleme im Design fr\"uhzeitig vermieden
|
||
werden konnten.
|
||
So empfahlen Kollegen das Datenbankdesign in die dritte Form
|
||
der Normalisierung zu \"ubertragen um eine Umsetzung in eine relationale Datenbank
|
||
zu erleichtern und zeigten an Beispielen, wie dies zu geschehen hat.
|
||
Die strikte Trennung der einzelnen Aufgaben erleichterte die Arbeit. Dadurch konnte
|
||
problemlos an einem anderen Teil weitergearbeitet werden, w\"ahrend noch die
|
||
Echtdaten f\"ur die Datenbank fehlten.
|
||
\newpage
|
||
\subsection{Zeitplan mit Abweichungen}
|
||
\setlongtables
|
||
\begin{longtable}{||l|c|c||}
|
||
\caption{Zeitplan}
|
||
\endfirsthead
|
||
\hline \hline
|
||
\textbf{Aufgabe} & \textbf{ben\"otigte Zeit} & \textbf{geplante Zeit} \\
|
||
& (in h) & (in h) \\
|
||
\hline \hline
|
||
\textbf{1 Vorarbeiten [Differenz: -1h]} & \textbf{10} & \textbf{11} \\
|
||
\hline \hline
|
||
1.1 Vorbesprechung mit unserem Au\ss{}endienst & 1 & 3 \\
|
||
\hline
|
||
1.2 Eruieren und dokumentieren des genauen Problems & 4 & 3 \\
|
||
und Definition des IST-Status & & \\
|
||
\hline
|
||
1.3 R\"ucksprache mit dem Au\ss{}endienst und Abgleich & 1 & 1 \\
|
||
des dokumentierten IST-Status mit dem Au\ss{}endienst & & \\
|
||
\hline
|
||
1.4 Definieren des SOLL-Status & 3 & 3 \\
|
||
\hline
|
||
1.5 R\"ucksprache mit dem Au\ss{}endienst und Abgleich & 1 & 1 \\
|
||
des dokumentierten SOLL-Status mit dem Au\ss{}endienst & & \\
|
||
\hline \hline
|
||
\textbf{2 Planungsphase [-2h (gesamt: -3h)]} & \textbf{10} & \textbf{12}\\
|
||
\hline \hline
|
||
2.1 Grob-Modell entwickeln, das die Anforderungen des & 2 & 2 \\
|
||
Soll-Status widerspiegelt & & \\
|
||
\hline
|
||
2.2 Schnittstellen definieren & & \\
|
||
\hline
|
||
2.2.1 Benutzer/Webinterface ("`Layoutdefinition"') & 1 & 2 \\
|
||
\hline
|
||
2.2.2 Webinterface/Datenbank & 2 & 2 \\
|
||
\hline
|
||
2.2.3 Datenbank/Quelldaten & 1 & 2 \\
|
||
\hline
|
||
2.2.4 Echtsystem/Testsystem & 2 & 2 \\
|
||
\hline
|
||
2.3 Pflichtenheft erstellen & 2 & 2 \\
|
||
\hline \hline
|
||
\textbf{3 Realisierungs- und Testphase [+2h (gesamt: -1h)]} & \textbf{28} & \textbf{25} \\
|
||
\hline \hline
|
||
\multicolumn{3}{||l||}{3.1 Erstellen des Webinterfaces} \\
|
||
\hline \hline
|
||
3.1.1 Erstellen der Zugriffseinstellungen & 1 & 1 \\
|
||
\hline
|
||
3.1.2 Erstellen des Hauptprogrammes inklusive & 3 & 2 \\
|
||
Datenbankverbindung & & \\
|
||
\hline
|
||
3.1.3 Erstellen der Loginprozedur & 2 & 2 \\
|
||
\hline
|
||
3.1.4 Erstellen der Suchprozedur & 3 & 4 \\
|
||
\hline
|
||
3.1.5 Erstellen der Anzeigeprozedur & 5 & 2 \\
|
||
\hline
|
||
3.2 Testen des Webinterface in der Testumgebung & 5 & 5 \\
|
||
\hline
|
||
3.3 Erstellen des Konverters & 3 & 4 \\
|
||
(CSV Datenbank in MySQL-Format) & & \\
|
||
\hline
|
||
3.4 Testen des Konverters in der Testumgebung & 2 & 2 \\
|
||
\hline
|
||
3.5 Fremdtest des Webinterface in der Testumgebung & 1 & 1 \\
|
||
\hline
|
||
3.6 Fremdtest des Konverters in der Testumgebung & 1 & 1 \\
|
||
\hline
|
||
3.7 Transfer des Testsystems in das Echtsystem des Providers & 2 & 2 \\
|
||
\hline \hline
|
||
\textbf{4 Dokumentationsphase [-5h (gesamt: -6h)]} & \textbf{12} & \textbf{17} \\
|
||
\hline \hline
|
||
4.1 Erstellen der Programmdokumentation & 7 & 7 \\
|
||
\hline
|
||
4.2 Erstellen des Benutzerhandbuches & 5 & 10 \\
|
||
\hline \hline
|
||
\textbf{5 Abschlussphase [(gesamt: -6h)]} & \textbf{1} & \textbf{1} \\
|
||
\hline \hline
|
||
5.1 Vorstellung des Systems in der Au\ss{}endienstleitung & 1 & 1 \\
|
||
\hline \hline
|
||
\textbf{6. Pufferzeit f\"ur nicht vorhersehbare Ereignisse} & \textbf{9} & \textbf{3} \\
|
||
\hline \hline \hline
|
||
\textbf{Gesamtzeit} & \textbf{70} & \textbf{70} \\
|
||
\hline \hline
|
||
\end{longtable}
|
||
Einige Differenzen erl\"autere ich detaillierter, da sie wichtige Aspekte
|
||
der Projektentwicklung widerspiegeln.\\
|
||
Vorarbeiten:
|
||
\begin{itemize}
|
||
\item Die Besprechung mit dem Au\ss{}endienst verk\"urzte sich,
|
||
da diesem die Problematik des alten Systems schon bekannt war
|
||
\end{itemize}
|
||
Realisierungs- und Testphase:
|
||
\begin{itemize}
|
||
\item Die Anbindung an die Datenbank verlief nicht so problemlos wie erwartet, da
|
||
w\"ahrend der Entwicklung der Datenbankserver zwei kurze Ausf\"alle hatte. Dies
|
||
f\"uhrte zu unvermuteten Ergebnissen im Hauptprogramm.
|
||
\item Die Gestaltung der Anzeigeprozedur erwies sich als wesentlich komplexer als
|
||
anfangs angenommen, da das Aussehen so wenig wie m\"oglich vom alten System
|
||
abweichen sollte.
|
||
\end{itemize}
|
||
Dokumentationsphase:
|
||
\begin{itemize}
|
||
\item Die Benutzerhandb\"ucher wurden als einfache Pr\"asentation realisiert und
|
||
bedurften kein spezielles Layout oder des Drucks.
|
||
\end{itemize}
|
||
Pufferzeit f\"ur nicht vorhersehbare Ereignisse:
|
||
\begin{itemize}
|
||
\item Im Zeitplan wurde der Punkt "`Erstellung der Projektdokumentation"' vergessen
|
||
und musste deswegen hier einsortiert werden.
|
||
\end{itemize}
|
||
\subsection{Ausblick}
|
||
\subsubsection{Erweiterung der bestehenden Programme}
|
||
Zus\"atzlich zu den bestehenden Anzeigen k\"onnten noch Auswertungen programmiert
|
||
werden, die sowohl schriftlich als auch graphisch pr\"asentiert werden.
|
||
Des weiteren k\"onnte die Tabellenspezifikation aus init-database.php ausgelagert
|
||
und selbiges Skript um einen Parser erweitert werden.
|
||
\subsubsection{Hinzuf\"ugen weiterer Programme}
|
||
Die Verwaltung der Benutzer k\"onnte durch ein Skript vereinfacht werden, welches
|
||
das Hinzuf\"ugen, L\"oschen oder Modifizieren der MySQL Datenbank und der htpasswd
|
||
Datei \"ubernimmt. Die Aktualisierung k\"onnte automatisiert werden, wenn von
|
||
ProAlpha aus regelm\"assig (z.B. tagesweise) die aktuellen Ums\"atze an ein
|
||
Programm \"ubermittelt werden, welches die Daten via HTTPS an das Upload Skript
|
||
\"ubertr\"agt.
|
||
\subsection{Kostenrechnung}
|
||
\subsubsection{altes System}
|
||
Die Kosten vorher setzten sich wie folgt zusammen:
|
||
14 Au\ss{}endienstler holen 15 MiB gro\ss{}e Dateien zweimal im Monat ab.
|
||
Die Internetverbindung erlaubt eine Transferrate von ca. 4 KiB pro Sekunde.\\
|
||
\textbf{Rechnung:}
|
||
$$\mbox{Transferrate} = \frac{4\mbox{KiB}}{\mbox{s}}$$\\
|
||
$$15 \mbox{MiB} * 14 \mbox{ADM} = 210 \mbox{MiB} = 210 * \mbox{1024 KiB} =
|
||
215040 \mbox{KiB}$$\\
|
||
$$\frac{215040 \mbox{ KiB}}{\frac{4\mbox{ KiB}}{\mbox{s}}} = 53760\mbox{ Sekunden}
|
||
= 896\mbox{ Minuten}$$\\
|
||
$$1 \mbox{ Minute } \hat{=} 0,39 \mbox{Euro}$$\\
|
||
$$896\mbox{ Minuten } * \frac{0,39 \mbox{ Euro}}{\mbox{Minute}} = 349,44
|
||
\mbox{ Euro pro Update}$$\\
|
||
2 $*$ Monatlich wird das Update gesendet.\\
|
||
$$349,44\mbox{ Euro } * 2 = 698,88\mbox{ Euro pro Monat}$$
|
||
Dies ergibt eine Online-Nutzdauer von 53.760 Sekunden, was 896 Minuten entspricht.
|
||
Bei einem Minutenpreis von 39 Cent pro Minute enstehen \textbf{698,88 Euro}
|
||
monatliche Kosten.
|
||
\subsubsection{neues System}
|
||
Die momentane Kosten setzen sich zusammen aus den Kosten f\"ur das Hosting
|
||
des Webinterfaces und den Onlinekosten.
|
||
Der Provider bietet einen Webauftritt, der \"uber eine
|
||
HTTPS Verbindung abgesichert ist und eine Unterst\"utzung f\"ur PHP und MySQL
|
||
enth\"alt, f\"ur 50 Euro pro Monat an. \\
|
||
\textbf{Rechnung:}\\
|
||
$$\mbox{MySQL Datenbank + PHP + Webspace } =
|
||
\mbox{"`Webauftritt"' }= 50\mbox{ Euro pro Monat}$$
|
||
$$\mbox{Nutzh\"aufigkeit} = \frac{\mbox{2mal}}{\mbox{Tag}}\mbox{ (benutzt der
|
||
ADM das Webinterface)}$$\\
|
||
Dies macht er an 20 Tagen (Arbeitstage) im Monat.
|
||
$$\frac{\mbox{zweimal}}{\mbox{Tag}} * \frac{\mbox{Arbeitstage}}{\mbox{Monat}} = 40
|
||
\mbox{mal Nachsehen pro Monat (pro ADM)}$$\\
|
||
$$14 \mbox{ ADM} * 40\mbox{mal} \mbox{ Nachsehen} = 560\mbox{mal}
|
||
\frac{\mbox{Nachsehen}}{\mbox{Monat}}$$\\
|
||
Einmal Nachsehen entspricht statistisch nach einer Umfrage einer Minute
|
||
(da nicht jeder das Angebot nutzen w\"urde und manche l\"anger brauchen).\\
|
||
$$560 \mbox{Minuten} * \frac{0,39\mbox{ Euro}}{\mbox{Minute}} = 218.40
|
||
\mbox{Euro}$$\\
|
||
$$218,40 + 50,00 = 268,40 \frac{\mbox{Euro}}{\mbox{Monat}}$$
|
||
Damit ergeben sich kumuliert Kosten von \textbf{268,40 Euro} pro Monat.\\
|
||
In dieser Rechnung sind jedoch nicht die Entwicklungskosten f\"ur das neue
|
||
System enthalten. Diese setzen sich zusammen aus dem Stundenlohn und der Anzahl
|
||
der ben\"otigten Stunden.\\
|
||
\textbf{Rechnung:}
|
||
$$70\mbox{ Stunden} * 5\mbox{ Euro} = 350\mbox{ Euro}$$
|
||
Dieser Betrag ist nur einmal f\"allig und amortisiert sich im Normalfall \"uber
|
||
die Jahre. In unserem speziellen Fall sind die Entwicklungskosten sogar schon nach
|
||
einem Monat kompensiert.\\
|
||
\subsubsection{Kostenvergleich}
|
||
Das neue System erbringt eine Kostenvorteil von \textbf{430,48 Euro}
|
||
beziehungsweise verbraucht nur \textbf{38\%} der alten Kosten pro Monat.
|
||
\section{Anhang}
|
||
\subsection{Literatur}
|
||
\subsubsection{PHP}
|
||
\begin{itemize}
|
||
\item "`PHP kurz \& gut"', O'Reilly, ISBN 3-89721-225-0
|
||
\item "`Programmieren lernen in PHP4"', Hanser, ISBN 3-446-21754-1
|
||
\item http://www.php.net
|
||
\end{itemize}
|
||
\subsubsection{Apache}
|
||
\begin{itemize}
|
||
\item http://httpd.apache.org/
|
||
\end{itemize}
|
||
\subsubsection{HTTP}
|
||
\begin{itemize}
|
||
\item HTTP Pocket Reference, O'Reilly, ISBN 1-56592-862-8
|
||
\end{itemize}
|
||
\subsubsection{MySQL}
|
||
\begin{itemize}
|
||
\item Managing and Using MySQL, 2nd Edition, O'Reilly, ISBN 0-596-00211-4
|
||
\end{itemize}
|
||
\subsection{Schnittstellen}
|
||
\subsubsection{Benutzer/Weboberfl\"ache: Layoutdefiniton}
|
||
\begin{verbatim}
|
||
|
||
--------------------------------------------------------------------------------
|
||
Nico Schottelius, v0.6
|
||
Schnittstelle: Webinterface/Layout
|
||
--------------------------------------------------------------------------------
|
||
|
||
1. Generelle Layoutdefiniton
|
||
2. Benutzerinteraktion
|
||
3. Authentifizierung
|
||
4. Sicherheit
|
||
5. Einstiegsbildschirm
|
||
6. Suchergebnisse
|
||
7. Suchdetails
|
||
|
||
|
||
1. Generelle Layoutdefiniton
|
||
|
||
Die Weboberfl<66>che sollte von der Farbwahl der Firmenhomepage [WL1] <20>hneln.
|
||
Zudem sollte ein firmentypisches Objekt (Logo, Motto, etc.) pr<70>sent sein.
|
||
|
||
2. Benutzerinteraktion
|
||
|
||
Der Benutzer soll die Oberfl<66>che intuitiv bedienen k<>nnen.
|
||
Fachw<68>rter und technische Details sind zu verbergen, Fehlermeldungen wenn
|
||
m<>glich durch einfache Hinweise zu ersetzen.
|
||
|
||
3. Authentifizierung
|
||
|
||
Der Webserver (hier: Apache) sendet nach dem GET Aufruf des Clients
|
||
einen 401 (Unauthorized) Code und den WWW-Authenticate Header an den Browser. [WL2]
|
||
Dieser Header kann zus<75>tzlich noch einen Text enthalten, wie z.B.
|
||
"Nur f<>r Au<41>endienstler erlaubt".
|
||
|
||
Die Authentifizierung wird dann in einem vom Browser selbstdefinierten
|
||
Authentifizierungsfenster durchgef<65>hrt, das den zus<75>tzlichen Text
|
||
des Serverheaders beinhalten kann, jedoch nicht muss.
|
||
|
||
Das bedeutet das man Serverseitig nur definieren kann, das sich der Client
|
||
authentifizieren muss, jedoch nicht wie dieses Fenster aussieht (im Gegensatz
|
||
zu Javascript basierten Authentifizierungen, die jedoch keine echte Sicherheit bieten).
|
||
|
||
Die Authentifizierung wird Serverseitig durch die htaccess Methodik [WL3]
|
||
definiert. Diese ben<65>tigt die htaccess Einstellungen selbst [WL4] und
|
||
zur Benutzerverwaltung die htpasswd [WL5].
|
||
|
||
Des weiteren m<>ssen die in der htpasswd vorhandenen Benutzer noch in der
|
||
MySOL Benutzerverwaltung angelegt werden. Diese erhalten dort ein
|
||
leeres Passwort vergeben, da die htaccess Authentifizierung ausreichend ist.
|
||
|
||
4. Sicherheit
|
||
|
||
Folgende Sicherheitsanforderungen sind vorhanden:
|
||
|
||
- Datenintegrit<69>t: die Daten m<>ssen gew<65>hrleistet unver<65>nderbar sein
|
||
- Vertraulichkeit: niemand darf unauthorisiertes Daten lesen k<>nnen
|
||
- Verf<72>gbarkeit: die Datenverbindung muss st<73>ndig verf<72>gbar sein
|
||
|
||
Die ersten beiden Anforderungen werden durch das TLS Protokoll [WL5] erf<72>llt.
|
||
|
||
Die Verf<72>gbarkeit des Webinterface im Internet ist abh<62>ngig von der Verf<72>gbarkeit des Web- und MySQL Servers.
|
||
|
||
|
||
5. Einstiegsbildschirm
|
||
|
||
Die Einstiegsseite zeigt den Namen des aktuell angemeldeten Benutzers an.
|
||
Des weiteren befindet sich ein Auswahlfeld, das die Suchoptionen enth<74>lt,
|
||
und des Suchbegrifffeld auf dieser Seite.
|
||
|
||
Dem Benutzer muss eine angemessen Suchfunktion zur Verf<72>gung stehen, die
|
||
das Suchen nach den erforderlichen Parametern erlaubt.
|
||
|
||
Als Suchoptionen m<>ssen die folgenden vorhanden sein:
|
||
|
||
- Kundennummer
|
||
- Kundenname
|
||
- Praxennummer
|
||
- Telefon
|
||
- PLZ
|
||
- Ort
|
||
|
||
|
||
6. Suchergebnisse
|
||
|
||
Auf der Seite der Ergebnisse sollen der Suchbegriff und das Suchkriterium
|
||
als <20>berschrift dargestellt werden.
|
||
|
||
Die Suchergebnisse werden tabellarisch dargestellt, die Ergebnisse sind
|
||
geordnet nach Kundennummern, aufsteigend.
|
||
|
||
Des weiteren muss die M<>glichkeit bestehen die Ergebnisse nach
|
||
den anderen angezeigten Feldern zu sortieren.
|
||
|
||
|
||
7. Suchdetails
|
||
|
||
Diese Seite soll sich an dem Beispiel Excel Dokument [WL6] orientieren.
|
||
Sie muss Details <20>ber den Kunden enhalten, u.a. die Anschrift
|
||
und soweit vorhanden die Telefonnummer.
|
||
|
||
|
||
[WL1]: http://www.wdt.de
|
||
[WL2]: RFC 2616
|
||
[WL3]: http://httpd.apache.org/docs-2.0/howto/auth.html
|
||
[WL4]: Beispiel: siehe Anhang dot-htaccess
|
||
[WL5]: RFC 2246, RFC 3546, Beispiel: htpasswd
|
||
[WL6]: Internes Dokument: Beispiel_Excel.xls
|
||
\end{verbatim}
|
||
\subsubsection{Weboberfl\"ache/Datenbank: Zugriffsdefiniton}
|
||
\begin{verbatim}
|
||
|
||
--------------------------------------------------------------------------------
|
||
Nico Schottelius, v0.2
|
||
Schnittstelle: Webinterface/Datenbank
|
||
--------------------------------------------------------------------------------
|
||
|
||
Tabellen und Felder in der Datenbank
|
||
------------------------------------
|
||
|
||
Die Typen der Felder und Tabellen sind in [WED1] dokumentiert.
|
||
Die Namen der Felder und Tabellen sind in [WED2] definiert.
|
||
Der Datenbankname und Datenbankserver sind frei w<>hlbar, muessen
|
||
jedoch in der Konfigurationsdatei [WED3] angegeben werden.
|
||
|
||
|
||
Quellen:
|
||
[WED1]: Siehe Anhang: 2.2.3 Schnittstelle Datenbank/Quelldaten
|
||
[WED2]: Siehe Anhang: Quellcode zu modules/init-db-create.php,
|
||
Funktion create_db, array "$creat_query"
|
||
[WED3]: Siehe Anhang: Quellcode zu includes/db-settings.php
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Datenbank/Quelldaten: Importformatdefiniton}
|
||
\begin{verbatim}
|
||
|
||
--------------------------------------------------------------------------------
|
||
Nico Schottelius, v0.6
|
||
Schnittstelle: Quelldaten/Datenbank
|
||
--------------------------------------------------------------------------------
|
||
|
||
1. Quelldaten
|
||
2. Zielform
|
||
3. Ziellayout / Typdefinition
|
||
4. Verhalten beim Import
|
||
|
||
1. Quelldaten
|
||
|
||
Die Quelldaten liegen in der Progressdatenbank [QDD1]. Sie m<>ssen mithilfe von
|
||
Progress oder Alternativ ProAlpha [QDD2] ausgelesen werden.
|
||
|
||
2. Zielform
|
||
|
||
Es sollen CSV Tabellen entsprechend der Typdefinition erstellt werden, wobei pro Tabelle eine Datei erstellt wird.
|
||
Der Trenner soll jedoch kein Komma sein, sondern ein Semikolon.
|
||
|
||
Tabellenspalten sind getrennt durch Semikolen, Tabellenzeilen getrennt durch
|
||
Zeilenumbruch, kein Header (wie z.B. ADM Name; ADM Nr) ist vorhanden,
|
||
Reihenfolge wie unten in der Typdefinition.
|
||
|
||
3. Ziellayout / Typdefinition
|
||
|
||
Feldnamen(*) genutzte Feldergroessen
|
||
* = Bemerkung vorhanden
|
||
|
||
0. ADM-Tabelle
|
||
ADM-Nr.* [int]
|
||
ADM-Name. [text 255 stellig]
|
||
|
||
ADM-Nr. ist >=0 und <=999.
|
||
Nummern >=1000 und <=9999 werden fuer adminstrative Zwecke genutzt.
|
||
|
||
1. Kundentabelle
|
||
KundenNr.* [int]
|
||
Prax.Nr.* [int]
|
||
ADM-Nr. [int] [wie oben]
|
||
Name [text 255 stellig]
|
||
Strasse [text 255 stellig]
|
||
Strassennummer [text 255 stellig]
|
||
PLZ [text 255 stellig]
|
||
Ort [text 255 stellig]
|
||
Telefon [text 255 stellig]
|
||
|
||
KundenNr sind 6 stellig
|
||
PraxNr sind 6 stellig
|
||
|
||
2. Umsatztabelle
|
||
KundenNr. [int] [wie oben]
|
||
ArtNr. [int] [wie unten]
|
||
|
||
Umsatz [float]
|
||
Menge [int]
|
||
|
||
Tag [int]
|
||
Monat [int]
|
||
Jahr* [int]
|
||
|
||
Jahr ist vierstellig
|
||
|
||
3. Artikeltabelle
|
||
ArtNr. [int]
|
||
ArtName [text 255 stellig]
|
||
GruppenName [text 255 stellig]
|
||
|
||
|
||
4. Verhalten beim Import
|
||
|
||
Wenn ein Datensatz mit identischen Primary Key vorhanden ist,
|
||
so werden die alten Daten in der Zieldatenbank mit den neuen Werten
|
||
<EFBFBD>berschrieben.
|
||
|
||
|
||
Quellen:
|
||
[QDD1]: http://www.progress.de/, http://www.progress.com/
|
||
[QDD2]: http://www.proalpha.de/
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Test-/Echtsystem}
|
||
\begin{verbatim}
|
||
|
||
--------------------------------------------------------------------------------
|
||
Nico Schottelius, v0.2
|
||
Schnittstelle: Test-/Echtsystem
|
||
--------------------------------------------------------------------------------
|
||
|
||
1 generelle Anpassungen
|
||
2 Probleme mit anderen PHP oder Apache Versionen oder Konfigurationen
|
||
|
||
|
||
1 generelle Anpassungen
|
||
|
||
Der Datenbankname und Datenbankserver m<>ssen in der Konfiguration
|
||
"includes/db-settings.php" angepasst werden.
|
||
|
||
|
||
2 Probleme mit anderen PHP oder Apache Versionen oder Konfigurationen
|
||
|
||
Der Apache 2.0 bietet bei PHP keine globalen Variablen.
|
||
Der Aufruf von "/script.php?option=test" setzt nur im Apache 1.3.x die Variable
|
||
"option". Im Apache 1.3.x und im Apache 2.0 kann man jedoch <20>ber den Array
|
||
_REQUEST und dem index des Variablennamens (z.B. $_REQUEST['option']) den Inhalt
|
||
auslesen.
|
||
|
||
F<EFBFBD>r das Verzeichnis in dem die Skripte liegen muss in der Apache Config
|
||
"AllowOverride Auth" angeschaltet sein, damit die .htaccess Datei beachtet wird.
|
||
|
||
In der Standard Installation von PHP d<>rfen Dateien beim Upload nicht
|
||
gr<EFBFBD><EFBFBD>er sein als 2MiB.
|
||
Somit muss unter Umst<73>nden die Tabellengr<67><72>e auf 2MiB limitiert werden.
|
||
Dies ist jedoch unproblematisch, da die Aktualisierung der Datenbank
|
||
inkrementell geschehen kann. Somit ist die M<>glichkeit gegeben z.B.
|
||
monatlich, w<>chentlich, oder sogar t<>glich eine Aktualisierung vorzunehmen.
|
||
Je kleiner die Abst<73>nde sind, desto kleiner sind logischerweise auch die Dateien.
|
||
Sollte eine Tabelle gr<67><72>er werden als 2MiB, so kann man sie auch teilen und
|
||
in mehreren Schritten hochladen.
|
||
|
||
Das Limit muss mit dem Provider abgekl<6B>rt werden.
|
||
|
||
\end{verbatim}
|
||
\subsection{Quelltext}
|
||
\subsubsection{includes/search.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
|
||
/* definiere die suchbegriffe nach feldern in der DB */
|
||
|
||
/* suche in welcher tabelle, modular ergaenzbar */
|
||
$suchbegriff_tabelle = array(
|
||
"Kundennummer" => "kunden",
|
||
"Kundenname" => "kunden",
|
||
"Praxennummer" => "kunden",
|
||
"Telefon" => "kunden",
|
||
"PLZ" => "kunden",
|
||
"Ort" => "kunden"
|
||
);
|
||
|
||
/* felder in den tabellen */
|
||
$suchbegriff_felder = array(
|
||
"Kundennummer" => "nr",
|
||
"Praxennummer" => "praxisnr",
|
||
"Kundenname" => "name",
|
||
"Telefon" => "telefon",
|
||
"PLZ" => "plz",
|
||
"Ort" => "ort",
|
||
);
|
||
|
||
/* felder in den tabellen */
|
||
$suchbegriff_map_field_eqto_kdnr = array(
|
||
"Kundennummer" => "nr",
|
||
"Praxennummer" => "praxisnr",
|
||
"Kundenname" => "name",
|
||
"Telefon" => "telefon",
|
||
"PLZ" => "plz",
|
||
"Ort" => "ort",
|
||
);
|
||
|
||
|
||
/*
|
||
Ausgabe: wie in excel
|
||
|
||
PraxenNummer
|
||
Kundennummer
|
||
Kundenname
|
||
PLZ
|
||
Telefon
|
||
Ort
|
||
WDT-Laufendes Jahr
|
||
Differenz Vorjahr
|
||
PRX-Laufendes Jahr
|
||
Differenz Vorjahr
|
||
GRO-Laufendes Jahr
|
||
Differenz Vorjahr
|
||
|
||
*/
|
||
|
||
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
\subsubsection{includes/db-settings.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
$dbserver = "localhost";
|
||
// $dbserver = "fs1";
|
||
$database = "projekt06";
|
||
?>
|
||
|
||
\end{verbatim}
|
||
\subsubsection{init-database.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* create the initial database
|
||
*******************************************************************/
|
||
|
||
$HEADER='
|
||
<HTML>
|
||
<HEAD>
|
||
<TITLE>Initialisieren der Datenbank</title>
|
||
<META NAME="Author" CONTENT="Nico Schottelius <nico-wdt@schottelius.org>">
|
||
</head>
|
||
<body bgcolor="#ffffff" LINK="#133E70" VLINK="#B52243" TEXT="#000000">
|
||
<P><IMG SRC="images/logo-wdt.png" ALT="WDT" HEIGHT="30" WIDTH="150"></P>
|
||
';
|
||
|
||
$FOOTER='
|
||
<P ALIGN=RIGHT><IMG SRC="images/tiere-animiert.gif"></P>
|
||
</BODY>
|
||
</HTML>
|
||
';
|
||
|
||
/* output header */
|
||
echo $HEADER;
|
||
|
||
/* select what todo */
|
||
switch($_REQUEST["option"]) {
|
||
case 1: /* create it */
|
||
include "modules/init-db-create.php";
|
||
create_db($_REQUEST['dbserver'],
|
||
$_REQUEST['database'],
|
||
$_REQUEST['dbuser'],
|
||
$_REQUEST['dbpass']);
|
||
break;
|
||
|
||
default: /* login */
|
||
include "modules/init-db-login.php";
|
||
login($dbserver,$database,$_SERVER["PHP_SELF"]);
|
||
break;
|
||
}
|
||
|
||
echo $FOOTER;
|
||
|
||
?>
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/init-db-login.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* create the initial database - login
|
||
* v0.4
|
||
*******************************************************************/
|
||
|
||
/* default function */
|
||
function login($dbserver,$database,$self)
|
||
{
|
||
|
||
include "includes/db-settings.php";
|
||
|
||
echo "<h3>Erzeugen der initialen Datenbank</h3>\n";
|
||
|
||
/* the upload form */
|
||
echo "<FORM ACTION=\"$self\" METHOD=POST>\n";
|
||
|
||
$dbserver_name="Datenbankserver";
|
||
$dbuser_name="Benutzer";
|
||
$dbpass_name="Passwort";
|
||
$database_name="Name der Datenbank";
|
||
|
||
/* fields */
|
||
echo "<TABLE>\n";
|
||
echo "<TR><TD>$dbserver_name:</TD>"
|
||
. '<TD><INPUT TYPE="text" name="dbserver" value="' . "$dbserver" . '" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$dbuser_name:</TD>"
|
||
. '<TD><INPUT TYPE="text" name="dbuser" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$dbpass_name:</TD>"
|
||
. '<TD><INPUT TYPE="password" name="dbpass" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$database_name:</TD>"
|
||
. '<TD><INPUT TYPE="text" name="database" value="' . "$database" . '" size="30">' . "</TD></TR>\n";
|
||
echo "</TABLE>\n";
|
||
|
||
/* hidden */
|
||
echo '<input type="hidden" name="option" value="1">' . "\n";
|
||
echo '<INPUT TYPE="submit" value="Erstellen">' . "\n";
|
||
echo '</form>' . "\n";
|
||
|
||
}
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/init-db-create.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* create the initial database - do the create
|
||
* v0.3
|
||
*******************************************************************/
|
||
|
||
function create_db($server, $database, $user, $pass)
|
||
{
|
||
|
||
echo "<h3>Initialisere die Datenbank '$database' auf $server als $user</h3>";
|
||
|
||
/* open connection */
|
||
$conn = mysql_connect($server,$user,$pass) or
|
||
die("<H3>Verbindung zur Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* choose database */
|
||
|
||
/* initial query */
|
||
$query= "CREATE DATABASE IF NOT EXISTS $database;";
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
echo "<P><B>Datenbank ist angelegt.</B></P>";
|
||
|
||
/* select the new db */
|
||
$db_check = mysql_select_db($database,$conn) or
|
||
die("<H3>Selektion der Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* create tables */
|
||
$create_query = array(
|
||
"CREATE TABLE IF NOT EXISTS adm (
|
||
nr INT PRIMARY KEY,
|
||
name TINYTEXT NOT NULL
|
||
);",
|
||
"CREATE TABLE IF NOT EXISTS kunden (
|
||
nr INT PRIMARY KEY,
|
||
praxisnr INT NOT NULL,
|
||
admnr INT NOT NULL,
|
||
name TINYTEXT NOT NULL,
|
||
strasse TINYTEXT NOT NULL,
|
||
strnr TINYTEXT NOT NULL,
|
||
plz TINYTEXT NOT NULL,
|
||
ort TINYTEXT NOT NULL,
|
||
telefon TINYTEXT NOT NULL
|
||
);",
|
||
"CREATE TABLE IF NOT EXISTS umsatz (
|
||
kundennr INT NOT NULL,
|
||
artikelnr INT NOT NULL,
|
||
umsatz FLOAT,
|
||
menge INT,
|
||
tag INT,
|
||
monat INT,
|
||
jahr INT
|
||
);",
|
||
"CREATE TABLE IF NOT EXISTS artikel (
|
||
nr INT PRIMARY KEY,
|
||
name TINYTEXT NOT NULL,
|
||
gruppe TINYTEXT NOT NULL
|
||
);"
|
||
);
|
||
|
||
foreach($create_query as $query) {
|
||
echo "<P><B>SQL-Kommando:</B> $query ...\n";
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
echo "done</p>";
|
||
}
|
||
|
||
echo "<P><B>Datenbank und die Tabellen sind angelegt.</B></P>";
|
||
}
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{search.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/* Nico Schottelius (c) 2004 *
|
||
* Suchen in der Datenbank *
|
||
* v0.4 */
|
||
|
||
$HEADER='
|
||
<HTML>
|
||
<HEAD>
|
||
<TITLE>WDT Datenbankzugriff</title>
|
||
<META NAME="Author" CONTENT="Nico Schottelius <nico-wdt@schottelius.org>">
|
||
</head>
|
||
<body bgcolor="#ffffff" LINK="#133E70" VLINK="#B52243" TEXT="#000000">
|
||
<P><IMG SRC="images/logo-wdt.png" ALT="WDT" HEIGHT="30" WIDTH="150"></P>
|
||
';
|
||
|
||
$FOOTER='
|
||
<P ALIGN=RIGHt><IMG SRC="images/tiere-animiert.gif"></P>
|
||
</BODY>
|
||
</HTML>
|
||
';
|
||
|
||
|
||
/* database settings */
|
||
$dbuser = $_SERVER["REMOTE_USER"];
|
||
$dbpass = "";
|
||
include "includes/db-settings.php";
|
||
|
||
/* output header */
|
||
echo $HEADER;
|
||
|
||
/* select option */
|
||
switch($_REQUEST['option']) {
|
||
case 1: /* display list of results */
|
||
include "modules/search_results.php";
|
||
search_results($dbserver,$database,$dbuser,$dbpass,$_REQUEST['finde'],$_REQUEST['suchoption'],$_REQUEST['sortby']);
|
||
break;
|
||
|
||
case 2: /* display details */
|
||
include "modules/search_details.php";
|
||
search_details($dbserver,$database,$dbuser,$dbpass,$_REQUEST['kdnr']);
|
||
break;
|
||
|
||
default: /* login */
|
||
include "modules/search_login.php";
|
||
search_login($dbserver,$database,$dbuser,$dbpass,$PHP_SELF);
|
||
break;
|
||
}
|
||
|
||
echo $FOOTER;
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/search\_results.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/* (c) 2004 Nico Schottelius
|
||
* display search results
|
||
* code: missing sanity checks */
|
||
|
||
function search_results($server, $database, $user, $pass, $begriff, $kriterium, $sortby)
|
||
{
|
||
|
||
include "includes/search.php";
|
||
|
||
/* open connection */
|
||
$conn = mysql_connect($server,$user,$pass) or
|
||
die("<H3>Verbindung zur Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* choose database */
|
||
$db_check = mysql_select_db($database,$conn) or
|
||
die("<H3>Selektion der Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* display name of ADM */
|
||
echo "<h3>Suchergebnisse: (gesucht in \"$kriterium\", nach \"$begriff\")</h3>\n";
|
||
|
||
/* do the query */
|
||
$table = $suchbegriff_tabelle[$kriterium];
|
||
$field = $suchbegriff_felder[$kriterium];
|
||
|
||
/* really sort by */
|
||
$rsortby = $suchbegriff_felder[$sortby];
|
||
|
||
/*****************************************************/
|
||
/* table begin */
|
||
/*****************************************************/
|
||
echo "<TABLE BORDER=1>\n";
|
||
|
||
/* table headers */
|
||
$query="DESCRIBE $table;";
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query1 fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* display header */
|
||
echo "<TR>\n";
|
||
|
||
/* create links to sort */
|
||
while ($row = mysql_fetch_array($resultcode) ) {
|
||
echo "<TH><A HREF=\"$self?option=1&suchoption=$kriterium&finde=$begriff&sortby=$row[0]\">$row[0]</A></TH>\n";
|
||
}
|
||
echo "</TR>\n";
|
||
|
||
/* construct the query */
|
||
$query_begin="SELECT * FROM `$table` ";
|
||
$query_end=" admnr = '$user' ORDER BY ";
|
||
|
||
$query = $query_begin;
|
||
|
||
/* sort */
|
||
if($sortby != "") $query_end .= " '$sortby'; ";
|
||
else $query_end .= " 'nr'; ";
|
||
|
||
/* search string */
|
||
if($begriff == "") $query .= " WHERE ";
|
||
else $query .= " WHERE $field LIKE " . "'$begriff" . "%'" .
|
||
" AND ";
|
||
|
||
/* complete the search */
|
||
$query .= $query_end;
|
||
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* count if we got results */
|
||
$count=0;
|
||
|
||
/* get number of fields */
|
||
$size=mysql_num_fields ($resultcode);
|
||
|
||
/* print all entries */
|
||
while ($row = mysql_fetch_array($resultcode) ) {
|
||
$count++;
|
||
|
||
echo "<TR>\n";
|
||
|
||
for($i=0;$i<$size;$i++) {
|
||
if($i == 0) {
|
||
$TD="<TD><A HREF=\"$PHP_SELF?option=2&kdnr=$row[$i]\">$row[$i]</A></TD>\n";
|
||
} else {
|
||
$TD="<TD>$row[$i]</TD>\n";
|
||
}
|
||
echo "$TD";
|
||
}
|
||
echo "</TR>\n";
|
||
}
|
||
echo "</TABLE>\n";
|
||
|
||
/* sanity check */
|
||
if(!$count) {
|
||
echo "<p><B>Keine Ergebnisse gefunden.</B></p>\n";
|
||
}
|
||
|
||
}
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/seach\_details.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* (c) 2004 Nico Schottelius
|
||
* display customer details
|
||
*******************************************************************/
|
||
|
||
function search_details($server, $database, $user, $pass, $nr)
|
||
{
|
||
|
||
/****************************************************************/
|
||
/* includes */
|
||
/****************************************************************/
|
||
include "includes/search.php";
|
||
|
||
/****************************************************************/
|
||
/* get times */
|
||
/****************************************************************/
|
||
$date_info = getdate();
|
||
$this_year = $date_info['year'];
|
||
$last_year = $this_year -1;
|
||
$oldest_year = $last_year -1;
|
||
$this_month = $date_info['mon'];
|
||
$this_day = $date_info['mday'];
|
||
$all_years = array("$oldest_year",
|
||
"$last_year",
|
||
"$this_year");
|
||
|
||
|
||
/****************************************************************/
|
||
/* sanity checks for variables FIXME! */
|
||
/****************************************************************/
|
||
|
||
|
||
/****************************************************************/
|
||
/* start database connection */
|
||
/****************************************************************/
|
||
|
||
/* open connection */
|
||
$conn = mysql_connect($server,$user,$pass) or
|
||
die("<H3>Verbindung zur Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* choose database */
|
||
$db_check = mysql_select_db($database,$conn) or
|
||
die("<H3>Selektion der Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
echo "<h3>Details für Kunde $nr</h3>\n";
|
||
|
||
/******************************************************/
|
||
/* table begin / headers */
|
||
/******************************************************/
|
||
$TABLE_BEGIN="<TABLE BORDER=0>\n";
|
||
$TABLE_END="</TABLE>\n";
|
||
|
||
echo $TABLE_BEGIN;
|
||
|
||
$query= "SELECT praxisnr , name , strasse , strnr ," .
|
||
"plz , ort , telefon FROM kunden WHERE nr = $nr " .
|
||
"AND admnr = $user;";
|
||
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
$row = mysql_fetch_array($resultcode);
|
||
$size = mysql_num_fields ($resultcode);
|
||
|
||
echo "<TR><TH ALIGN=LEFT>".$row['name']."</TH></TR>";
|
||
echo "<TR><TH ALIGN=LEFT>".$row['strasse']. " " . $row['strnr'] . "</TR>";
|
||
echo "<TR><TH ALIGN=LEFT>".$row['plz']. " " . $row['ort'] . "</TR>";
|
||
echo "<TR><TH ALIGN=LEFT>".$row['telefon']."</TH></TR>";
|
||
echo "<TR><TH ALIGN=LEFT>".$nr ."</TH></TR>";
|
||
|
||
echo $TABLE_END;
|
||
|
||
/****************************************************************/
|
||
/* last 3 months FIXME */
|
||
/****************************************************************/
|
||
echo $TABLE_BEGIN;
|
||
|
||
$last_month = $this_month-1;
|
||
$before_last_month = $last_month-1;
|
||
|
||
/* get data like in .xls */
|
||
$query= "SELECT umsatz FROM umsatz WHERE " .
|
||
"kundennr = $nr " . /* Kunde */
|
||
"AND jahr = $this_year " . /* Jahr */
|
||
"AND monat = ($this_month OR $last_month OR $before_last_month);" ; /* Monat */
|
||
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
$row = mysql_fetch_array($resultcode);
|
||
$size = mysql_num_fields ($resultcode);
|
||
|
||
echo "<TR><TD>A: $row[0]</td></tr>";
|
||
echo "<TR><TD>B: $query</td></tr>";
|
||
echo "<TR><TD>C: $row[1] :: $row[2]</td></tr>";
|
||
|
||
echo $TABLE_END;
|
||
|
||
/****************************************************************/
|
||
/* kummultative results */
|
||
/****************************************************************/
|
||
echo $TABLE_BEGIN;
|
||
|
||
/* get data like in .xls */
|
||
$query= "SELECT praxisnr , name , strasse , strnr ," .
|
||
"plz , ort , telefon FROM kunden WHERE nr = $nr " .
|
||
"AND admnr = $user;";
|
||
|
||
echo $TABLE_END;
|
||
|
||
/****************************************************************/
|
||
/* display all articles (details) */
|
||
/****************************************************************/
|
||
|
||
echo $TABLE_BEGIN;
|
||
|
||
/* get all articles from this customer */
|
||
/*
|
||
$query= "SELECT artikelnr FROM umsatz WHERE kundennr = $nr " .
|
||
"GROUP BY artikelnr;";
|
||
*/
|
||
$query= "SELECT umsatz.artikelnr FROM umsatz,kunden WHERE " .
|
||
"umsatz.kundennr = $nr AND umsatz.kundennr = kunden.nr " .
|
||
"AND kunden.admnr = $user " .
|
||
"GROUP BY artikelnr;";
|
||
|
||
$rs_all_artikel = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* display table header */
|
||
echo "<TR><TD> </td></tr>\n";
|
||
echo "<TR>\n";
|
||
echo "\t<TH ALIGN=LEFT>Artikelnummer</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Umsatz $oldest_year</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Menge $oldest_year</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Umsatz $last_year</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Menge $last_year</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Umsatz $this_year</TH>\n";
|
||
echo "\t<TH ALIGN=LEFT>Menge $this_year</TH>\n";
|
||
echo "</TR>\n";
|
||
|
||
/* count columns */
|
||
$count=0;
|
||
|
||
/* go through all articles */
|
||
while ($row = mysql_fetch_array($rs_all_artikel) ) {
|
||
$count++;
|
||
$artikelnr="$row[0]";
|
||
echo "<TR>\n";
|
||
echo "<TD>$artikelnr</TD>\n";
|
||
|
||
/* go through all years */
|
||
foreach($all_years as $work_year) {
|
||
$query =
|
||
"SELECT SUM(umsatz.umsatz) , SUM(umsatz.menge) " .
|
||
"FROM umsatz WHERE umsatz.kundennr = $nr AND " .
|
||
"umsatz.artikelnr = $artikelnr AND umsatz.jahr = $work_year;";
|
||
|
||
$rs_cur_artikel = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
$cur_umsatz_menge = mysql_fetch_array($rs_cur_artikel);
|
||
$cur_umsatz=$cur_umsatz_menge[0];
|
||
$cur_menge=$cur_umsatz_menge[1];
|
||
|
||
/* select 0 if nothing was found */
|
||
if($cur_umsatz == "") {
|
||
echo "\t<TD>0</TD>\n";
|
||
} else {
|
||
echo "\t<TD>" . $cur_umsatz . "</TD>\n";
|
||
}
|
||
|
||
/* same here */
|
||
if($cur_menge == "") {
|
||
echo "\t<TD>0</TD>\n";
|
||
} else {
|
||
echo "\t<TD>" . $cur_menge . "</TD>\n";
|
||
}
|
||
|
||
}
|
||
echo "</TR>\n";
|
||
}
|
||
|
||
echo $TABLE_END;
|
||
|
||
/* sanity check if there were no articles bought*/
|
||
if(!$count) {
|
||
echo "<p><B>Keine Ergebnisse gefunden.</B></p>\n";
|
||
}
|
||
}
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{upload.php}
|
||
\label{upload.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* Update der Datenbank
|
||
*******************************************************************/
|
||
|
||
$HEADER='
|
||
<HTML>
|
||
<HEAD>
|
||
<TITLE>Update der Datenbank</title>
|
||
<META NAME="Author" CONTENT="Nico Schottelius <nico-wdt@schottelius.org>">
|
||
</head>
|
||
<body bgcolor="#ffffff" LINK="#133E70" VLINK="#B52243" TEXT="#000000">
|
||
<P><IMG SRC="images/logo-wdt.png" ALT="WDT" HEIGHT="30" WIDTH="150"></P>
|
||
';
|
||
|
||
$FOOTER='
|
||
<P ALIGN=RIGHt><IMG SRC="images/tiere-animiert.gif"></P>
|
||
</BODY>
|
||
</HTML>
|
||
';
|
||
|
||
|
||
/* DB settings */
|
||
include "includes/db-settings.php";
|
||
|
||
/* database settings */
|
||
$dbuser = $_SERVER["REMOTE_USER"];
|
||
$dbpass = "";
|
||
|
||
/* output header */
|
||
echo $HEADER;
|
||
|
||
/* select option */
|
||
switch($_REQUEST["option"]) {
|
||
case 1: /* do the update */
|
||
$filenames=array( 'adm' => $_FILES['tabelle_adm'],
|
||
'kunden' => $_FILES['tabelle_kunden'],
|
||
'umsatz' => $_FILES['tabelle_umsatz'],
|
||
'artikel' => $_FILES['tabelle_artikel']
|
||
);
|
||
include "modules/upload-it.php";
|
||
update_it($dbserver,$database,$dbuser,$dbpass,$filenames);
|
||
break;
|
||
|
||
default: /* login */
|
||
include "modules/upload-login.php";
|
||
login($dbserver,$database,$dbuser,$dbpass,$PHP_SELF);
|
||
break;
|
||
}
|
||
|
||
echo $FOOTER;
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/upload-login.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* create the initial database - do the create
|
||
* v0.5
|
||
*******************************************************************/
|
||
|
||
/* default function */
|
||
function login($dbserver, $database, $dbuser, $pass, $self)
|
||
{
|
||
|
||
$adm_tab = "ADM Tabelle";
|
||
$kunden_tab = "Kunden Tabelle";
|
||
$umsatz_tab = "Umsatz Tabelle";
|
||
$artikel_tab = "Artikel Tabelle";
|
||
|
||
/* 120 MB */
|
||
$max_tab_size = 120 * 1024 * 1024;
|
||
|
||
echo "<H3>Update der Datenbank...</h3>\n";
|
||
|
||
/* the upload form */
|
||
echo "<FORM enctype=\"multipart/form-data\" ACTION=\"$self\" METHOD=POST>\n";
|
||
|
||
/* fields */
|
||
echo "<TABLE>\n";
|
||
echo "<TR><TD>$adm_tab:</TD>"
|
||
. '<TD><INPUT TYPE="file" name="tabelle_adm" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$kunden_tab:</TD>"
|
||
. '<TD><INPUT TYPE="file" name="tabelle_kunden" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$umsatz_tab:</TD>"
|
||
. '<TD><INPUT TYPE="file" name="tabelle_umsatz" size="30">' . "</TD></TR>\n";
|
||
echo "<TR><TD>$artikel_tab:</TD>"
|
||
. '<TD><INPUT TYPE="file" name="tabelle_artikel" size="30">' . "</TD></TR>\n";
|
||
echo "</TABLE>\n";
|
||
|
||
/* hidden */
|
||
echo '<input type="hidden" name="MAX_FILE_SIZE" value="' . "$max_tab_size\">\n";
|
||
echo '<input type="hidden" name="option" value="1">' . "\n";
|
||
echo '<INPUT TYPE="submit" value="Update!">' . "\n";
|
||
echo '<INPUT TYPE="reset" value="Zurücksetzen">' . "\n";
|
||
echo '</form>' . "\n";
|
||
|
||
}
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsubsection{modules/upload-it.php}
|
||
\begin{verbatim}
|
||
|
||
<?php
|
||
/*******************************************************************
|
||
* Nico Schottelius (c) 2004
|
||
* Update der Datenbank
|
||
* v0.3
|
||
*******************************************************************/
|
||
|
||
function update_it($dbserver, $database, $dbuser, $pass, $filenames)
|
||
{
|
||
|
||
/* open connection */
|
||
$conn = mysql_connect($dbserver,$dbuser,$pass) or
|
||
die("<H3>Verbindung zur Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
/* choose database */
|
||
$db_check = mysql_select_db($database,$conn) or
|
||
die("<H3>Selektion der Datenbank fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
|
||
$i=0;
|
||
foreach($filenames as $tablename => $tableinfo) {
|
||
|
||
/* debug */
|
||
// echo "<P>table: $tablename\n";
|
||
// echo "<BR>tableinfo: $tableinfo</P>\n";
|
||
|
||
|
||
$wert = $tableinfo["tmp_name"];
|
||
$filename = $tableinfo["name"];
|
||
|
||
/* check if this table should get updated */
|
||
if($wert != "none" and $wert != "") {
|
||
|
||
echo "<P><B>Update die Tabelle '$tablename' " .
|
||
"aus Datei $filename ...</B>\n";
|
||
|
||
/* reset query */
|
||
$query = "";
|
||
|
||
/* basic query array */
|
||
$sql = array ('LOAD DATA LOCAL INFILE', " '$wert'", ' REPLACE INTO TABLE ',
|
||
" `$tablename` ", 'FIELDS TERMINATED BY \';\' ENCLOSED BY \'"\' ESCAPED BY \'\\\\\' LINES TERMINATED BY \'\\n\';');
|
||
|
||
/* construct query */
|
||
foreach($sql as $partofquery) {
|
||
$query .= $partofquery;
|
||
}
|
||
|
||
/* query() */
|
||
echo "<P>$query </P>";
|
||
$resultcode = mysql_query($query,$conn) or
|
||
die("<H3>Query fehlgeschlagen: ". mysql_error() ."</h3>");
|
||
echo "<B>done</B><br>\n";
|
||
$i++;
|
||
}
|
||
}
|
||
|
||
/* result display */
|
||
echo "<p>$i Tabelle(n) verarbeitet.</p>\n";
|
||
}
|
||
|
||
?>
|
||
|
||
\end{verbatim}
|
||
|
||
\subsection{Testtabellen}
|
||
Diese Tabellen wurden zum Testen benutzt, w\"ahrend noch keine Echtdaten
|
||
verf\"ugbar waren. Sie werden von upload.php verarbeitet (siehe Seite
|
||
\pageref{upload.php}).
|
||
\subsubsection{Aussendienstmitarbeiter ("`adm.test"')}
|
||
\begin{verbatim}
|
||
|
||
120; Heinz Martin
|
||
140; Mutter Albert
|
||
150; Kruenling
|
||
1000; Der Admin
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Artikel ("`artikel.test"')}
|
||
\begin{verbatim}
|
||
|
||
12345; Elefantenpritze; wdt
|
||
12346; Elefantenbesteck; wdt
|
||
12347; Kaenguruhnapf; prx
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Kunden ("`kunden.test"')}
|
||
\begin{verbatim}
|
||
|
||
019066; 201749; 120;prakt. Tier<65>rztin aus Test;Testwegrein;23;22527;Hamburg;01234/4555
|
||
010646; 201749; 120;prakt. Tieraerztin2 aus Test3;Testwegrein;23;22527;Hamburg;01234/4555
|
||
019067; 019066; 140; Tierliebhaber Burgberg; veilenweg; 42; 30456; Hannover; 00123/123
|
||
019068; 019069; 150; Tierer Bargberg;blumenstarre;235;33334; Testhause; 0042455/5533
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Umsatz ("`umsatz.test"')}
|
||
\begin{verbatim}
|
||
|
||
019066;12345;120,00;12; 01; 07; 2004
|
||
019066;12346;120,00;12; 02; 06; 2004
|
||
019066;12347;120,00;12; 03; 05; 2004
|
||
019066;12347;150,00;12; 19; 04; 2003
|
||
019066;12347;140,00;12; 19; 03; 2003
|
||
019066;12346;110,00;12; 19; 02; 2002
|
||
019066;12345;100,00;12; 10; 01; 2002
|
||
019066;12346;150,00;12; 12; 01; 2004
|
||
019067;12347;160,00;12; 12; 01; 2004
|
||
019068;12346;160,00;12; 22; 01; 2004
|
||
|
||
\end{verbatim}
|
||
|
||
\subsection{Konfigurationsdateien}
|
||
\subsubsection{Apache: .htaccess (oder "`dot-htaccess"')}
|
||
.htaccess ist die Standardmethode f\"ur Authentfizierung beim Apache Webserver.
|
||
In der gleichnamigen Datei wird definiert,
|
||
um was f\"ur eine Art Authentifizierung es sich handelt ("`AuthType"'),
|
||
welcher Text optional angezeigt wird beim Darstellen der Passwortbox
|
||
("`AuthName"'),
|
||
woraus die Authentifizierungsinformationen gelesen werden ("`AuthUserFile"') und
|
||
welche Bedingung erf\"ullt sein muss ("`Require"').
|
||
\begin{verbatim}
|
||
|
||
AuthType Basic
|
||
AuthName "Willkommen zum WDT Aussendienstler Programm"
|
||
AuthUserFile /home/user/nico/www/projekt/source/testpasswd
|
||
Require valid-user
|
||
|
||
\end{verbatim}
|
||
\subsubsection{Apache: htpasswd}
|
||
In der htpasswd werden die Passw\"orter f\"ur die Authentifizierung \"uber das
|
||
Webinterface definiert.
|
||
\begin{verbatim}
|
||
|
||
120:8ZnzPTAQ5IJkM
|
||
9999:$apr1$/9xFh...$/Qy28iJzLaPWfhFWwsy1C/
|
||
1000:$apr1$shOFt...$xoRiz8F4lClo2hv/MGi7n.
|
||
|
||
\end{verbatim}
|
||
\subsubsection{PHP: Auszug php.ini}
|
||
Im Gegensatz zur normalen Konfiguration ist hier die maximale Dateigr\"o\ss{}e 120MB
|
||
erh\"oht. Es ist der \textit{Manpage} nicht zu entnehmen, ob MB hier MiB
|
||
entspricht oder der Faktor 1000 als Basis genommen wurde.
|
||
\begin{verbatim}
|
||
|
||
;;;;;;;;;;;;;;;;;;;
|
||
; Resource Limits ;
|
||
;;;;;;;;;;;;;;;;;;;
|
||
|
||
max_execution_time = 30 ; Maximum execution time of each script, in seconds
|
||
max_input_time = 60 ; Maximum amount of time each script may spend parsing request data
|
||
memory_limit = 128M ; Maximum amount of memory a script may consume (8MB)
|
||
;;memory_limit = 8M ; Maximum amount of memory a script may consume (8MB)
|
||
|
||
; Maximum size of POST data that PHP will accept.
|
||
;;post_max_size = 8M
|
||
post_max_size = 120M
|
||
|
||
;;;;;;;;;;;;;;;;
|
||
; File Uploads ;
|
||
;;;;;;;;;;;;;;;;
|
||
|
||
; Whether to allow HTTP file uploads.
|
||
file_uploads = On
|
||
|
||
; Temporary directory for HTTP uploaded files (will use system default if not
|
||
; specified).
|
||
;upload_tmp_dir =
|
||
|
||
; Maximum allowed size for uploaded files.
|
||
;;upload_max_filesize = 2M
|
||
upload_max_filesize = 120M
|
||
\end{verbatim}
|
||
\end{document}
|