Initialisiere VoTiAn NG mit Docker-Build, .env-Konfiguration und Cookie-Sitzungen
This commit is contained in:
commit
1a30233269
63 files changed
+12138
No files matched your search
@@ -0,0 +1,376 @@
|
||||
# Analyse des PHP-Altsystems votian
|
||||
|
||||
Stand: 01.10.2026. Auftraggeberkontext: Stadtbote GmbH. Grundlage ist eine statische, lesende Analyse des Quellbestands im Verzeichnis `votian/`. Es wurden keine produktiven Datenbanken, Fahrergeräte oder externen Dienste angesprochen. Dieser Bericht enthält keine produktiven Kundendatensätze oder Zugangsdaten.
|
||||
|
||||
**Verbindliche Datenbankvorgabe:** Die Neuentwicklung verwendet die bereits vorhandene MySQL-Datenbank und deren bestehendes Schema. Es wird keine eigene Datenbank angelegt und keine Schemaänderung vorgenommen. DDL, automatische Schemaerzeugung, Schemaaktualisierung und ungefragte Initialbefüllung sind ausgeschlossen.
|
||||
|
||||
Die Neuentwicklung soll die tägliche Auftragserfassung und Disposition in React und Spring Boot abbilden. Der Bestand umfasst jedoch zusätzlich eine umfangreiche Tarif-, Berechtigungs-, Abrechnungs- und Integrationslogik. Die nachfolgend als **Ziel erster Umsetzung** bezeichneten Funktionen sind ein geplanter Umfang und kein Nachweis ihres Implementierungsstands. Vollständige fachliche Parität oder Produktionsreife wird mit diesem Bericht nicht behauptet.
|
||||
|
||||
**Aktuelle Umsetzungsentscheidung:** Die erste Anbindung soll über lesende JDBC-Adapter auf das unveränderte Bestandsschema, vorhandene Benutzerkonten und Verweise auf bestehende PHP-Aktionen erfolgen. Das betrifft insbesondere Erfassung, Bearbeitung und weitere schreibende Geschäftsprozesse, deren Regeln nicht ungeprüft durch direkte SQL-Schreibzugriffe ersetzt werden. Ein PHP-Verweis ist keine React-/Spring-Portierung dieses Ablaufs. Wegen des derzeit nicht nachgewiesenen Datenbankzugriffs bleiben Live-Funktion, Spaltenverträglichkeit, Authentisierung und vollständige Portierung offen; dieser Bericht weist sie nicht als getestet aus.
|
||||
|
||||
## 1. Quellen und Aussagekraft
|
||||
|
||||
Quellenangaben haben die Form `votian/pfad/datei.php:Zeile` und beziehen sich auf den untersuchten Bestand. Zeilennummern markieren den Einstieg in die betreffende Funktion oder den relevanten Codeblock. Historische Kopien und nummerierte Dateivarianten kommen häufig vor; als Grundlage wurden überwiegend die unnummerierten, von den Hauptseiten referenzierten Dateien verwendet. Aus dem bloßen Vorhandensein einer Datei folgt nicht, dass die Funktion heute produktiv genutzt wird.
|
||||
|
||||
Die tatsächliche Ausprägung hängt von Datenbankparametern, Niederlassung, Kunde, Fahrzeugtyp, Zeitpunkt und Mitarbeiterrechten ab. Ohne diese Konfiguration und fachlich freigegebene Beispieldaten lassen sich die aktiven Regeln nicht vollständig bestimmen. Einzelne Codekommentare dienen als Hinweis; entscheidende Aussagen wurden soweit möglich mit ausführbarem Code abgeglichen.
|
||||
|
||||
Zentrale Quellen:
|
||||
|
||||
| Bereich | Quellen |
|
||||
|---|---|
|
||||
| Auftragsmaske und Benutzerkontext | `votian/jobs/job_edit.php:20`, `:38`, `:81` |
|
||||
| Auftrags- und Stationsspeicherung | `votian/jobs/job_options.php:208`, `:421`, `:2290` |
|
||||
| Disposition und Listen | `votian/admin/jb_list.php:505`, `:708`, `:957`, `:1376` |
|
||||
| Fachliche Feldlisten | `votian/include/mcglobal.inc.php:145`, `:169`, `:177`, `:198`, `:217` |
|
||||
| Tarifberechnung | `votian/include/services_func.inc.php:24`, `:89`, `:168`, `:371`, `:538` |
|
||||
| Storno | `votian/include/inc_job.inc.php:1242` |
|
||||
| Berechtigungen | `votian/include/auth.inc.php:208`, `:264`, `:285`, `:315` |
|
||||
| Abrechnung | `votian/invoice/inv.inc.php:28`, `votian/invoice/inv_aux.inc.php:264` |
|
||||
|
||||
## 2. Fachliches Datenmodell
|
||||
|
||||
### Kunden, Kostenstellen und Niederlassungen
|
||||
|
||||
Die Struktur ist `company → customer → costcenter`. Eine Firma enthält den Unternehmensstamm; der Kunde ergänzt die kaufmännischen Einstellungen. Kostenstellen bilden eine Hierarchie über `csc_pre_id` und `csc_path`. Sie haben eigene Sichtbarkeit, Sperren und Rechnungsparameter. Kostenstellenadressen unterscheiden unter anderem Abhol-, Rechnungs- und Serviceadressen.
|
||||
|
||||
Wichtige Felder:
|
||||
|
||||
- Kunde: `cs_id`, `cmp_id`, `hq_id`, externe/interne Kundennummer, Hauptkostenstelle, Standardzahler, übergeordneter/zugehöriger Kunde, Rabatt, Festpreisrabatt, Provision, Rechnungsmodus, Kommissionsnummer, Zuschlag, Zahlungsziel, Auftrags-/Tracking-Einstellungen.
|
||||
- Kostenstelle: `csc_id`, `cs_id`, Name, Elternreferenz, Pfad, extern/intern, gesperrt, sichtbar, Rechnungsintervall und Rechnungsart.
|
||||
- Adresse: Straße, Hausnummer, PLZ, Ort, Land, Firmenzusätze, Ansprechpartner, Telefon und Bemerkung.
|
||||
|
||||
Quellen: `votian/include/mcglobal.inc.php:130`, `:145`, `:147`, `:200`, `:217`.
|
||||
|
||||
**Konsequenz:** Ein einzelner Kundenname am Auftrag ersetzt die Kostenstellenstruktur nicht. Auftraggeber und Rechnungsempfänger müssen unterscheidbar bleiben. Niederlassungszugehörigkeit ist außerdem eine fachliche Zugriffsgrenze.
|
||||
|
||||
### Kuriere und Fahrzeuge
|
||||
|
||||
Kurier und Fahrzeug sind getrennte Entitäten. In der Disposition wird häufig die Fahrzeug-SID verwendet. Ein angebotener Kurier (`cr_id_order`) ist vom tatsächlich annehmenden Kurier (`cr_id`) zu unterscheiden.
|
||||
|
||||
- Kurier: Unternehmen und Benutzer, SID/Nummer, Fahrzeugtyp, Merkmale/Filter, Maximalgewicht, mögliche Auslage, Verfügbarkeit, Verfügbarkeitszeit und Standort-PLZ.
|
||||
- Fahrzeug: Kurierbezug, Fahrzeug-SID, Kennzeichen, Fahrzeugtyp, Nutzlast, Gesamtgewicht, Länge/Breite/Höhe, Stellplätze, Eigenschaften, Provision und Aktivierung.
|
||||
|
||||
Quellen: `votian/include/mcglobal.inc.php:198`, `:206`; Zuweisung über SID in `votian/admin/jb_list.php:515`.
|
||||
|
||||
### Auftrag, Stationen und Leistungen
|
||||
|
||||
| Entität | Fachlich relevante Felder |
|
||||
|---|---|
|
||||
| Auftrag `job` | Nummer, Version, Auftraggeber-Kostenstelle, Zahler-Kostenstelle, Niederlassungen für Disposition/Ausführung/Vertrieb, Besteller, Kommission, gewünschter/tatsächlicher Fahrzeugtyp, Gewicht/Maße, Auftrags-/Annahme-/Abschluss-/Warnzeit, Reservierung, Dauerauftrag, Tourname, Status, Storno, Angebot, unvollständig, Fernfahrt, Freitext, Dispositionshinweis, übergeordneter Auftrag, Preise, Buchungs-/Exportdaten |
|
||||
| Station `tour` | Auftragsbezug, Reihenfolge, Kostenstelle, Firma/Firmenzusatz, Adresse, Person, Telefon, Bemerkung, Kommission, Zusatzkilometer/-leistung, Abhol-/Lieferart, Status, Signatur, Empfängername, Abschlusszeit |
|
||||
| Stationsleistung `tourservice` | Station, Leistung/Leistungsart, Leistungsbezeichnung, Preis, Rabatt, zahlende Kostenstelle |
|
||||
| Artikelposition `tourarticle` | Artikel, Menge, Sortierung, Preis, Packstücke, Gewicht, Seriennummer, Zustand, Bemerkung |
|
||||
| Artikelbearbeitung `tourarticleprocess` | Positionsbezug, Vorgangsart, Status, Bemerkung, Zeitpunkt |
|
||||
| Preiskomponente `jobprice` | Auftragsbezug, Art der Komponente und Betrag; zusätzliche Informationen zu Kunden-/Kurierberechnung |
|
||||
|
||||
Quellen: `votian/include/mcglobal.inc.php:169`, `:177`, `:179`, `:181`, `:183`; weitere Maße und Bearbeitungsfelder in `votian/jobs/job_options.php:208`; Preiskomponenten in `votian/include/caglobal.inc.php:1663`.
|
||||
|
||||
## 3. Statusmodell und Arbeitsabläufe
|
||||
|
||||
### Auftragsstatus
|
||||
|
||||
| Legacywert | Bedeutung | Übertragung |
|
||||
|---|---|---|
|
||||
| `9` | Manuelle Disposition, noch zuzuteilen | Eigener fachlicher Status |
|
||||
| `8` | Autoranking | Eigener Zustand, dessen automatische Bearbeitung einen separaten Dienst benötigt |
|
||||
| `0` | Offen / anzunehmen | Kurierangebot und Annahme unterscheiden |
|
||||
| `1` | Angenommen / laufend | Laufende Ausführung |
|
||||
| `2` | Erledigt | Regulärer Abschluss oder Abschluss durch Storno; Stornoflag zusätzlich prüfen |
|
||||
| `99` | Interner Zustand im Zusammenhang mit Börsen-/Globalauftrag | Kein normaler Benutzerstatus ohne weitere Prüfung des Börsenablaufs |
|
||||
| `10` bzw. `ALL` | Alle Aufträge | Ausschließlich Listenfilter |
|
||||
|
||||
Quellen: `votian/jobs/job_options.php:421`, `:439`, `:451`; `votian/admin/jb_list.php:79`, `:516`.
|
||||
|
||||
**Storno ist eine eigene Dimension:** `jb_storno=1` bedeutet kostenpflichtig, `2` kostenfrei. Stornierung setzt `jb_status=2`, den Abschlusszeitpunkt und den stornierenden Benutzer. Ein vereinfachtes neues Enum darf diese Information nicht verlieren. Quelle: `votian/include/inc_job.inc.php:1242`.
|
||||
|
||||
Die dazugehörigen Gegenbuchungsaufträge verwenden `jb_storno=3` für die Gutschrift zu einem kostenpflichtigen Storno bzw. `4` für die Gutschrift zu einem kostenfreien Storno. Der Code kopiert und negiert dabei Preise/Leistungen und verknüpft den Originalauftrag über `jb_id_copy`. Solche Datensätze sind nicht einfach weitere reguläre Touren. Quelle: `votian/jobs/job_options.php:662`.
|
||||
|
||||
### Stationsstatus und Stationsart
|
||||
|
||||
Stationen sind einzeln offen (`tr_status=0`) oder erledigt (`1`). Bei vollständig erledigten Stationen kann der Gesamtauftrag abgeschlossen werden. Das Entfernen einer noch offenen Station kann ebenfalls einen Abschluss auslösen. Bei nachträglichen Stationsänderungen sind vorhandene Abschlussdaten zu erhalten.
|
||||
|
||||
`tr_ware_from_to` unterscheidet `1=Abholung`, `2=Anlieferung`, `3=Anlieferung und Abholung`. `0` leitet die Standardart aus der Stationsposition ab. Die neue Oberfläche sollte eindeutige, explizite Arten verwenden.
|
||||
|
||||
Quellen: `votian/jobs/job_options.php:2290`, `:2335`, `:2356`; `votian/include/caglobal.inc.php:1355`.
|
||||
|
||||
### Kernablauf
|
||||
|
||||
1. **Erfassen:** Die Zentrale wählt eine Kostenstelle. Beim Kundenbenutzer wird die auftraggebende Kostenstelle aus dem Mitarbeiterkonto abgeleitet. Die Auftragsmaske erlaubt Kurieren und Systemadministratoren in diesem Kontext keine normale Erfassung. Quelle: `votian/jobs/job_edit.php:38`.
|
||||
2. **Route anlegen:** Mehrere Stationen mit Abhol-/Lieferkennzeichen, Adressen, Ansprechpartnern, Hinweisen und optionalen Artikeln/Leistungen erfassen. Quellen: `votian/include/mcglobal.inc.php:177`, `votian/jobs/job_options.php:236`.
|
||||
3. **Zeit und Leistung festlegen:** Sofortfahrt, Reservierung oder Dauerauftrag; Fahrzeuganforderung, Gewicht, Maße und besondere Leistungen festlegen.
|
||||
4. **Preis bestimmen:** Tarifberechnung oder manueller Festpreis; Kundenpreis und Kuriervergütung separat behandeln. Quellen: `votian/jobs/job_options.php:942`, `:1811`.
|
||||
5. **Disponieren:** Ohne Kurier abhängig vom Niederlassungsmodus Status `9` oder `8`; mit Kurier üblicherweise `0`. Offline-Disposition kann direkt `1` setzen. Quellen: `votian/jobs/job_options.php:421`, `votian/admin/jb_list.php:516`.
|
||||
6. **Ausführen:** Annahme, Stationsabschlüsse und Zustellnachweis; anschließend Gesamtabschluss. Quellen: `votian/include/mcglobal.inc.php:169`, `:177`, `votian/jobs/job_options.php:2335`.
|
||||
7. **Nachbearbeiten:** Kopieren/Nacherfassen, Versionsänderung, Änderungsprotokoll und gegebenenfalls Information an das Fahrergerät. Quellen: `votian/jobs/job_options.php:185`, `:2366`.
|
||||
8. **Stornieren und abrechnen:** Kostenpflicht prüfen, bestehende Buchungen/Exporte beachten und erforderlichenfalls Gegenbuchungen erzeugen. Quelle: `votian/include/inc_job.inc.php:1242`.
|
||||
|
||||
### Reservierungen, Daueraufträge und Vorlagen
|
||||
|
||||
Die Wiederholungslogik unterstützt Werktage, Werktage mit Samstag, täglich, wöchentlich, vierzehntäglich, monatlich, Monatsende, 15./Monatsende, 1./16., vierwöchentlich und Feiertage. Eine siebenstellige Maske enthält die ausgewählten Wochentage Montag bis Sonntag. Feiertagsverschiebungen unterscheiden sich je nach Wiederholungsart. Ein Enddatum begrenzt Serien. Quelle: `votian/include/caglobal.inc.php:2304`.
|
||||
|
||||
Ein gespeicherter Tourname dient auch dem Wiederverwenden einer Tour; die Preisermittlung kann beim Wiederverwenden auf aktuelle Tarife zugreifen. Quellen: `votian/jobs/job_options.php:231`, `:1799`.
|
||||
|
||||
## 4. Preislogik und Abrechnung
|
||||
|
||||
Der Bestand besitzt keine einzelne universelle Formel. Wesentliche Einflussgrößen sind Niederlassung, Kunde, Fahrzeugtyp, Auftragszeit, Leistung, PLZ-Paar, PLZ-Gebiet, Zusatzleistungen und Zahlungsart.
|
||||
|
||||
| Regelbereich | Beleg | Für Parität benötigter Nachweis |
|
||||
|---|---|---|
|
||||
| Zeitlich gültige Leistungs-/Kundentarife | `votian/include/services_func.inc.php:24`, `:371` | Aktive Tarifstände und erwartete Auswahl bei Überschneidungen |
|
||||
| PLZ-Paar-/Gebietstarife | `votian/include/services_func.inc.php:89`, `:168` | Gebietsdefinitionen, Richtung, Prioritäten, Sonderadressen |
|
||||
| Treibstoffzuschlag Kunde/Kurier | `votian/include/services_func.inc.php:430`, `:494` | Gültigkeitsstände und zuschlagsfähige Komponenten |
|
||||
| Leistungspreise, Rabatt, Kostenaufteilung | `votian/include/services_func.inc.php:538` | Reihenfolge, Zahlerzuordnung, Rundung und Ausnahmen |
|
||||
| Manuelle Fest-/Servicepreise | `votian/jobs/job_options.php:1050`, `:1067`, `:1828` | Einbeziehung von Rabatt und Zuschlag; Eingabepreis netto/brutto |
|
||||
| Separate Kuriervergütung | `votian/include/services_func.inc.php:766`, `:794`, `:813` | Provision, Fernfahrt-, Fahrzeug- und Unternehmerregeln |
|
||||
| Summen-/Rundungsfolge | `votian/jobs/job_options.php:1811` | Referenzfälle mit identischen Einzel- und Endsummen |
|
||||
| Umsatzsteuer/Maut | `votian/jobs/job_options.php:2140` | Satz, Leistungsdatum und steuerliche Zuordnung je Fall |
|
||||
| Storno und bereits exportierte Buchungen | `votian/include/inc_job.inc.php:1286` | Gegenbuchungs- und Exportregeln, keine Doppelabrechnung |
|
||||
|
||||
Bei Festpreisen wirken im untersuchten Zweig ein Zuschlag, ein separat gerundeter Selbstbedienungsrabatt und anschließend ein Kundenrabatt. Servicepreise erhalten nicht automatisch denselben Zuschlag; ihre Rabattfähigkeit ist konfigurierbar. Die Kuriervergütung wird gesondert ermittelt. Deshalb reicht ein pauschales Feld „Gesamtpreis“ nicht zum Nachweis gleicher Abrechnung.
|
||||
|
||||
Für eine spätere native Schreibumsetzung ist manuelle Preisangabe mit nachvollziehbaren Werten ein sinnvoller begrenzter Umfang. Im aktuellen lesenden Ansatz sollen Preise aus vorhandenen Aufträgen angezeigt und Preisänderungen über die geprüfte PHP-Funktion vorgenommen werden. Es müssen jedoch Währung, Netto-/Bruttobedeutung, Steuersatz und Rundung klar sein. Beispielpreise sind als Beispieldaten zu behandeln. Die vollständige Altpreisberechnung ist damit nicht ersetzt.
|
||||
|
||||
Für Spring Boot sollten Geldbeträge als `BigDecimal` und passend zu den vorhandenen Datenbanktypen gelesen und geschrieben werden; Schemaänderungen sind ausgeschlossen. Der Auftrag benötigt einen unveränderlich nachvollziehbaren Preisstand mit Herkunft und Komponenten. Eine spätere Tarifänderung darf historische Beträge nicht stillschweigend verändern. Dies sind Empfehlungen für die Neuentwicklung, keine Behauptungen über deren aktuellen Code.
|
||||
|
||||
Die Rechnungsansicht unterscheidet Kunden- und Kurierabrechnung und berücksichtigt Kostenstellen, Barzahlungen und bereits exportierte Aufträge. Barzahlungen werden im betreffenden Zweig nicht als gewöhnliche Kundenrechnung behandelt. Quellen: `votian/invoice/inv.inc.php:28`, `:200`; `votian/invoice/inv_aux.inc.php:264`, `:319`, `:357`.
|
||||
|
||||
Eine neue Rechnungsübersicht oder ein CSV-Export ist daher zunächst eine Übersicht/Ausgabe. Gleichwertige Fakturierung, Korrekturbelege, Buchhaltungsexporte oder rechtliche Rechnungsanforderungen sind damit noch nicht nachgewiesen.
|
||||
|
||||
## 5. Benutzerrechte und fachliche Grenzen
|
||||
|
||||
Die Benutzertypen sind `1=Zentrale`, `2=Kunde`, `3=Kurier`, `4=Lager`. Darüber hinaus existiert gesonderte Systemadministratorbehandlung in verschiedenen Seiten. Quelle: `votian/include/dbglobal.inc.php:786`; Beispiel für Typ `0` in `votian/invoice/inv.inc.php:52`.
|
||||
|
||||
Mitarbeiterrechte werden zusätzlich über eine positionsbasierte Rechtemaske ausgewertet. Die Zugriffsprüfung unterscheidet Zentrale, Kunde und Kurier; Kundenrechte sind an Kostenstellen gebunden. Im Rechnungsmodul wird zusätzlich das Rechnungsrecht geprüft und die ausgewählte Kostenstelle auf den erlaubten Teilbaum beschränkt.
|
||||
|
||||
Quellen: `votian/include/auth.inc.php:208`, `:214`, `:264`, `:285`, `:315`; `votian/invoice/inv.inc.php:36`.
|
||||
|
||||
Erforderliche Nachweise vor produktiver Ablösung:
|
||||
|
||||
- Rollen- und Aktionsmatrix für Lesen, Erfassen, Ändern, Disponieren, Stornieren, Preise, Rechnungen und Export.
|
||||
- Mandanten-/Niederlassungsgrenzen und erlaubte Kostenstellen-Teilbäume.
|
||||
- Nachweis serverseitiger Prüfung bei direkten API-Aufrufen, nicht nur ausgeblendeter Navigation.
|
||||
- Trennung zwischen Stammdaten eines Kuriers, angemeldetem Fahrer und zugewiesenem Fahrzeug.
|
||||
- Historie mit Akteur, Zeitpunkt und relevanter Änderung; Schutz vor konkurrierenden Status-/Preisänderungen.
|
||||
|
||||
Eine Anmeldung mit wenigen Rollen kann die erste Umsetzung absichern, ersetzt aber die vorhandene Rechte- und Teilbaummatrix noch nicht.
|
||||
|
||||
## 6. Schnittstellen und Hintergrundverarbeitung
|
||||
|
||||
| Bereich | Im Quellbestand erkennbar | Quelle | Grenze der ersten Umsetzung |
|
||||
|---|---|---|---|
|
||||
| Fahrer-/Mobile-Kommunikation | XML-Verarbeitung mit Modulen für Aufträge, Kuriere, Artikel, Fahrzeuge und weitere Funktionen | `votian/mobile/serviceXML.php:15`, `:1668` | Eine neue REST-API ist nicht automatisch kompatibel zu vorhandenen Fahrergeräten |
|
||||
| Änderungen laufender Aufträge | Erzeugung zeitgesteuerter Gerätekommandos | `votian/jobs/job_options.php:2366` | Bestätigung, Wiederholung, Offlinebetrieb und Konfliktbehandlung benötigen eigene Tests |
|
||||
| Routing/Geokodierung | Adresssuche und Tour-/Zeitfensterplanung; PTV-Bezug im XML | `votian/import/xServer.inc.php:35`, `:101`, `:195` | Lizenz, Endpunkt, Koordinatensystem, Distanz-/Zeitgrundlage und Fehlerfälle sind offen |
|
||||
| Kilometer-/Routenpreis | Geokodierung, gespeicherte Routen, Optimierungsinformationen | `votian/include/ajaxReqKmPrice.php:5`, `:161`, `:259`, `:376` | Keine belastbare automatische Distanz- oder Preisberechnung ohne Dienst und Tarifabnahme |
|
||||
| Dateiimporte | Allgemeine und kundenspezifische Importstrecken | `votian/import/import_STANDARD_01.php:12`, `votian/import/import_TIMS.php:18` | Feldmapping, Dublettenschutz und Fehlerrückmeldung je aktivem Format prüfen |
|
||||
| Dateitransfer | FTP-bezogene Funktionen für Import-/Exportdateien | `votian/import/data_transfer.php:94`, `:767`, `:772` | Transporteinstellungen werden nicht aus dem Altsystem übernommen |
|
||||
| Datenexport | Eigenständiges Exportmodul mit Rechteprüfung über Menüeinträge | `votian/admin/menu.php:265`, `:331` | CSV-Ausgabe ist kein Ersatz aller bestehenden Vertragsschnittstellen |
|
||||
| Wiederholungsaufträge | Datums-/Feiertagslogik für nächste Ausführung | `votian/include/caglobal.inc.php:2304` | Ausführung, Eindeutigkeit und Neustartverhalten eines neuen Schedulers belegen |
|
||||
|
||||
Für jede tatsächlich genutzte Integration sind Verantwortlicher, Format-/Protokollversion, Testzugang, Beispieldaten, Authentisierung, Fehlerrückmeldung, Wiederholungsstrategie und Abnahmekriterium zu erfassen. Alte Zugangsdaten werden nicht migriert oder in die neue Anwendung kopiert. Der Bericht dokumentiert keine geheimen Konfigurationswerte.
|
||||
|
||||
## 7. Optik und Bedienung
|
||||
|
||||
Das Altsystem nutzt überwiegend kompakte, tabellarische Masken. Die Auftragserfassung ist in Kopf, Stationsmaske, Optionen und Stationsliste gegliedert; im Bestand erfolgt dies über Frames. Quelle: `votian/jobs/job_edit.php:81`.
|
||||
|
||||
Die erkennbaren Standardfarben sind Hellblau `#CDD9FD`, dunkles Blau `#1b12b9` und Akzentblau `#4e45ec`. Die Standardschrift ist Verdana mit Arial/Helvetica als Ersatz, häufig in 8 pt. Quellen: `votian/css/navigation.css.php:28`, `:33`, `:35`, `:52`; `votian/css/phoenix.css.php:22`.
|
||||
|
||||
Ziel der React-Oberfläche ist eine wiedererkennbare blaue Gestaltung mit klarer Navigation, dichten Auftragstabellen, sichtbaren Statusangaben und kurzer Erfassung. Lesbarkeit, Tastaturbedienung und responsive Darstellung können modernisiert werden. Die Übernahme der Frames, der kleinen historischen Schriftgröße oder jedes pixelgenauen Abstands ist kein fachliches Erfordernis. Visuelle Gleichheit ist ohne Screenshots der aktiven Installation nicht nachgewiesen.
|
||||
|
||||
## 8. Modul-Abdeckungsmatrix
|
||||
|
||||
Diese Matrix trennt vorhandene Fachlichkeit von dem vorgesehenen Einstieg. **Sie ersetzt keine Prüfung des tatsächlich implementierten Codes und der Tests.**
|
||||
|
||||
| Modul/Funktion | Bestand | Ziel erster Umsetzung | Noch zu belegende Parität / Priorität |
|
||||
|---|---|---|---|
|
||||
| Aufträge | Umfangreiche Felder, Listen, Kopien, Nacherfassung | Lesen/Filtern über JDBC; Erstellen/Bearbeiten als PHP-Verweis | Pflichtfelder, abgeschlossene/exportierte Aufträge und Historie; P0 |
|
||||
| Mehrstopp-Tour | Beliebige Stationsfolge mit Einzelstatus und Nachweisen | Vorhandene Stationsfolge lesen; Bearbeitung im PHP-Ablauf | Gemischte Stationen, Stationsabschluss, Empfänger/Signatur; P0 |
|
||||
| Disposition | Manuell, Autoranking, Börse, Offline-Zuweisung | Dispositionsdaten lesen; Zuweisung/Status als PHP-Aktion | Angebot gegenüber Annahme, Rücknahme, Konkurrenz; P0 |
|
||||
| Storno | Kostenpflichtig/kostenfrei, Buchungsfolgen | Storno anzeigen; Aktion im bestehenden PHP-Prozess | Altflags, Beträge, Export-/Gegenbuchungsfälle; P0 |
|
||||
| Kunden | Firmen, Kostenstellenhierarchie, Zahler, Parameter | Kundenstammdaten lesen; Pflege über PHP-Verweis | Kostenstellen und abweichender Rechnungsempfänger; P0/P1 |
|
||||
| Kuriere/Fahrzeuge | Getrennte Modelle, SID, Verfügbarkeit und Merkmale | Kurierstammdaten lesen; Pflege über PHP-Verweis | Fahrzeugzuordnung, Eignung, Verfügbarkeit; P1 |
|
||||
| Preise | Historisierte Tarife, PLZ-/Gebiete, Leistungen, Rabatte, Zuschläge | Vorhandene Preiswerte lesen; Kalkulation/Änderung im PHP-Prozess | Tarifmatrix und getrennte Kurierabrechnung; vor automatischer Preisnutzung P0 |
|
||||
| Rechnungen | Kunden-/Kurieransicht, Kostenstellen, Bar-/Exportregeln | Vorhandene Abrechnungswerte lesen bzw. PHP-Rechnungsansicht öffnen | Fakturierung, Korrekturen, Nummernkreise, Steuern und Exportstatus; vor Abrechnung P0 |
|
||||
| Export | Rechtegebundene und kundenspezifische Ausgaben | Lesende Ausgabe bzw. vorhandener PHP-Export; Umsetzung separat belegen | Schnittstellenverträge, Kodierung, Dubletten und Wiederholung; P1 |
|
||||
| Reservierungen | Zukünftige Auftragszeit und Dispositionsregeln | Vorhandenen Termin anzeigen; Änderung im PHP-Prozess | Zeitzone, Warn-/Vorbereitungszeit; P1 |
|
||||
| Daueraufträge/Vorlagen | Wiederholungsmuster, Feiertage, Enddatum, gespeicherte Tour | Nicht als abgedeckt voraussetzen | Scheduler und Serien-/Vorlagenabnahme; P1 |
|
||||
| Zugriffsrechte | Rolle, Einzelaktion, Niederlassung und Kostenstelle | Bestehende Benutzerkonten, HQ-Mitarbeiterbezug und Leserechte; noch live nachzuweisen | Vollständige serverseitige Rechte-/Sichtbarkeitsmatrix; P0 |
|
||||
| Kunden-/Fahrerportal | Unterschiedliche Ansichten und mobile Kommunikation | Nicht als abgedeckt voraussetzen | Eigene Datenbegrenzung, Geräteprotokoll und Offlinefälle; P1 |
|
||||
| Artikel/Lager | Artikelpositionen, Packstücke, Bearbeitungsstatus | Nicht als abgedeckt voraussetzen | Lager-/Scanprozesse und Bestandsintegration; P2 nach Nutzungsnachweis |
|
||||
| Routing/GPS/Autoranking | Externe Routen- und Ortungsinformationen | Nicht als abgedeckt voraussetzen | Dienstintegration, Rankingregeln, Ausfallbetrieb; P2/P1 je Betrieb |
|
||||
| Bestandsanbindung | Bestehendes MySQL-Schema mit verknüpften Bestands-/Archivdaten | Direkte, kompatible Anbindung ohne eigene Datenbank | Feld-, Status-, Transaktions- und Berechtigungsabgleich; keine DDL/Schemaänderung; P0 |
|
||||
|
||||
Prioritäten: **P0** verhindert die fachlich sichere Ablösung des betroffenen Kernablaufs; **P1** ist als nächster operativer Ausbau einzuplanen; **P2** hängt von der nachgewiesenen produktiven Nutzung ab. Nicht jede Funktion muss vor einer begrenzten Pilotnutzung verfügbar sein; der Pilotumfang muss die vorhandenen Einschränkungen ausdrücklich berücksichtigen.
|
||||
|
||||
Die besonders dringenden Ergänzungen über ein einfaches CRUD hinaus sind: getrennte Kostenstellen/Zahler, einzelne Stationsabschlüsse, echte Stornobedeutung, Trennung Angebot/Annahme, serverseitige Zugriffsgrenzen und nachvollziehbare Änderungen. Diese Aspekte beeinflussen den täglichen Kernprozess unmittelbar.
|
||||
|
||||
## 9. Bestehende Datenbank anbinden, ohne Schemaänderung
|
||||
|
||||
Die ausdrückliche Vorgabe lautet, die vorhandene Datenbank zu verwenden. Es gibt deshalb keinen Plan zur Anlage einer neuen Datenbank, zur Erstellung neuer Tabellen oder zum Import der Bestandsdaten in ein neues Schema. „Mapping“ bezeichnet ausschließlich die Abbildung bestehender Spalten auf Java-/API-Modelle. Eine rein lesende Schemaanalyse ist von Datensatzänderungen zu unterscheiden.
|
||||
|
||||
1. **Verbindung und Bestand feststellen.** Autorisiert bereitgestellte Verbindungsparameter außerhalb des Quellcodes konfigurieren. Datenbankversion, Tabellen, Spaltentypen, Schlüssel, Archivtabellen, Kodierung und aktive Parameter lesend ermitteln. Zugangsdaten nicht in Ausgaben oder Repository schreiben.
|
||||
2. **Automatische Strukturänderungen abschalten.** Keine H2-Ersatzdatenbank, keine neue MySQL-Datenbank, keine DDL, keine Flyway-/Liquibase-Migrationen und keine automatische Seed-Befüllung. Bei JPA darf die DDL-Einstellung keine Erzeugung oder Änderung auslösen. Explizites JDBC mit kontrolliertem SQL ist ebenfalls möglich.
|
||||
3. **API-/Feldmapping erstellen.** Für jede verwendete API-Eigenschaft die vorhandene Tabelle, Spalte, Join-Bedingung, Bedeutung, Nullbehandlung und Schreibregel dokumentieren. Auftraggeber/Zahler, Kunde/Kostenstelle, Kurier/Fahrzeug und Auftrag/Station bleiben unterscheidbar.
|
||||
4. **Bestand lesend prüfen.** Fachliche Stichproben, Objektanzahlen, Fremdschlüsselbeziehungen, Statuswerte und Summen abgleichen. Verwaiste Referenzen, doppelte Nummern und widersprüchliche Daten melden, ohne sie automatisch zu korrigieren. Die alte Oberfläche deklariert ISO-8859-1 (`votian/jobs/job_edit.php:67`); der tatsächliche Datenbankzeichensatz und JDBC-Transport sind separat zu prüfen.
|
||||
5. **Kompatibles Schreiben entwickeln.** Bestehende Schlüsselerzeugung, erforderliche Spalten, Status-/Stornofelder, Zeitstempel, Historie und Nebentabellen berücksichtigen. Ein fachlicher Speichervorgang benötigt eine Transaktion. Unbekannte Altspalten nicht durch vollständiges Ersetzen eines Datensatzes verlieren. Die Existenz aller SQL-Spalten vor Schreibfreigabe nachweisen.
|
||||
6. **Schreiben gezielt verifizieren.** Autorisierte Testdatensätze oder eine ausdrücklich bereitgestellte Testinstanz des unveränderten Bestandsschemas verwenden. Keine eigenmächtige Testdatenbankanlage. Produktive Datensätze nicht als Testmaterial ändern. Auftragserfassung ist mehr als ein `INSERT INTO job`: Stations-, Preis-, Zuweisungs- und eventuell Historieneinträge müssen fachlich zusammenpassen.
|
||||
7. **Parallelbetrieb prüfen.** PHP und Spring Boot können dieselben Datensätze sehen. Konkurrierende Bearbeitung, Nummernvergabe, Statuswechsel und Hintergrundprozesse dürfen sich nicht überschreiben. Bereits vorhandene Versions-/Sperrkonzepte sind auf Kompatibilität zu untersuchen. Serienaufträge, Benachrichtigungen und Exporte dürfen nicht doppelt ausgelöst werden.
|
||||
8. **Abgleich und Freigabe.** Lesen über PHP und neue API anhand identischer IDs vergleichen. Nach erlaubten Testschreibvorgängen Sichtbarkeit und Bedeutung im Altsystem prüfen. Disposition und Abrechnung bestätigen die relevanten Fälle; verbleibende Grenzen bleiben dokumentiert.
|
||||
|
||||
Falls ein bestehender Datentyp oder eine fehlende Spalte die gewünschte Funktion nicht abbildet, darf daraus keine automatische Schemaänderung folgen. Zunächst vorhandene fachliche Speicherorte untersuchen, dann die Einschränkung konkret benennen. Ein neuer API-Begriff ist kein Auftrag, eine gleichnamige Spalte anzulegen.
|
||||
|
||||
Authentisierung muss zum vorhandenen Benutzermodell passen. Alte Passwortwerte dürfen weder in API-Antworten noch in Logs gelangen. Eine Änderung von Passwortformaten, Kontoaktivierungen oder Benutzerrechten ist eine eigene fachliche Änderung und nicht Teil der bloßen Anbindung. Signaturen, Fotos und Dokumente bleiben an ihren vorhandenen Daten-/Dateibeziehungen; sie werden nicht ungefragt kopiert oder verschoben.
|
||||
|
||||
## 10. Fachliche Abnahme und technische Nachweise
|
||||
|
||||
| Abnahmeszenario | Erwartung |
|
||||
|---|---|
|
||||
| Sofortauftrag mit zwei Stationen | Pflichtfelder, Preisbedeutung und initialer Status stimmen; Auftrag nach Neustart vorhanden |
|
||||
| Mehrstopp mit Abholung, Lieferung und gemischter Station | Reihenfolge bleibt erhalten; Teilabschluss beendet nicht vorzeitig den Gesamtauftrag |
|
||||
| Zuweisen, annehmen, zurücknehmen | Kurierangebot und Annahme sind nachvollziehbar; ungültige Übergänge werden serverseitig abgewiesen |
|
||||
| Zwei Disponenten bearbeiten denselben Auftrag | Keine unbemerkte Überschreibung; Versionskonflikt ist verständlich lösbar |
|
||||
| Reservierung und Warnzeit | Lokale Zeitdarstellung und Speicherung stimmen, auch bei Zeitumstellung |
|
||||
| Kostenpflichtiges/kostenfreies Storno | Zustand, Preisfolgen und Historie bleiben eindeutig; abgeschlossene/exportierte Fälle geprüft |
|
||||
| Abweichender Zahler und Unterkostenstelle | Rechnungszuordnung korrekt; unberechtigter Benutzer kann fremde Daten auch per API nicht erreichen |
|
||||
| Festpreis mit Rabatt, Zuschlag, Service und Steuer | Beträge und Rundungsfolge anhand freigegebener Referenzfälle exakt geprüft |
|
||||
| Historischer Auftrag nach Tarifänderung | Historischer Preis bleibt nachvollziehbar und unverändert, sofern keine ausdrückliche Neukalkulation erfolgt |
|
||||
| Abrechnung und Wiederholung des Exports | Keine Doppelabrechnung; Exportinhalt und Status sind reproduzierbar |
|
||||
| Fehlende externe Dienste | Verständliche Fehler, keine stillen Fantasiepreise oder falschen Statusbestätigungen |
|
||||
| Bestandsanbindung und Parallelbetrieb | Identische fachliche Daten in PHP und neuer API; keine DDL, keine verlorenen Felder und keine doppelten Hintergrundaktionen |
|
||||
|
||||
Die erste Lieferung ist anhand ihrer tatsächlich vorhandenen Endpunkte, Bedienwege und Tests gegen diese Matrix zu prüfen. Bestehende Backend-Tests, ein erfolgreicher Frontend-Build und ein erfolgreicher Start sind technische Nachweise; sie ersetzen weder Tarifvergleich noch Benutzerrechteprüfung, Schnittstellenabnahme und Datenabgleich.
|
||||
|
||||
Ein zunächst auf `job.hq_id = user.hq_id` begrenzter Lesezugriff zeigt nur Aufträge der eigenen **Erfassungsniederlassung**. Die Legacy-Liste berücksichtigt zusätzlich Ausführungs-, Dispositions- und Vertriebsniederlassung über eine Vereinigung erlaubter HQ-Mengen (`votian/admin/jb_list.php:1101`, `:1363`). Die engere neue Sicht ist als Einschränkung auszuweisen: Ein in einer anderen Niederlassung erfasster, der eigenen Disposition zugehöriger Auftrag kann fehlen. Zugriffsbereiche dürfen ohne passende Rechteabbildung nicht pauschal erweitert werden.
|
||||
|
||||
Eine vollständige Ablösung kann erst bestätigt werden, wenn Stadtbote die aktiv genutzten Module bestimmt hat, die zugehörigen Regeln in der neuen Anwendung kompatibel umgesetzt oder ausdrücklich stillgelegt sind und die relevanten Referenzfälle bestanden wurden.
|
||||
|
||||
## Anhang A. Konkrete Zuordnung bestehender Tabellen zu API-Modellen
|
||||
|
||||
Die API-Feldnamen in der linken Spalte sind Vorschläge für die Java-/JSON-Abbildung. Die rechten Spalten sind im PHP-Code belegte bestehende Datenbanknamen. Die tatsächlichen Typen, Nullmöglichkeiten und Indizes müssen über die vorhandene Datenbank lesend geprüft werden. Die folgenden SQL-Formen dienen nur der Implementierungsanalyse und wurden nicht gegen eine Datenbank ausgeführt.
|
||||
|
||||
### Kunde und Firmenstamm
|
||||
|
||||
| API-Feld | Bestehende Spalte / Ausdruck | Beziehung |
|
||||
|---|---|---|
|
||||
| `customer.id` | `customer.cs_id` | Fachlicher Kundenschlüssel, nicht `cmp_id` |
|
||||
| `customer.number` | `customer.cs_eid` | Im Bearbeitungsablauf auf Eindeutigkeit geprüft |
|
||||
| `customer.internalNumber` | `customer.cs_sid` | Weitere interne Nummer |
|
||||
| `customer.companyId` | `customer.cmp_id` | `customer.cmp_id = company.cmp_id` |
|
||||
| `customer.name` | `company.cmp_comp` | Firmenzusätze `cmp_comp2` bis `cmp_comp4` separat |
|
||||
| `customer.headquarterId` | `customer.hq_id` | Sichtbarkeit nach erlaubtem Niederlassungs-/Mandantenbereich |
|
||||
| `customer.defaultCostCenterId` | `customer.csc_id` | Hauptkostenstelle |
|
||||
| `customer.payerCostCenterId` | `customer.csc_id_payer` | Abweichender Standardzahler |
|
||||
| `customer.contact.firstName/lastName` | `user.usr_firstname`, `user.usr_name` | `customer.cs_admin = employee.emp_id`, dann `employee.usr_id = user.usr_id` |
|
||||
| `customer.phone/email` | `user.usr_phone`, `user.usr_email` | Wie Kontakt; Telefon nicht aus `company` erfinden |
|
||||
| `customer.address.street` | `address.ad_street` | `company.ad_id = address.ad_id` |
|
||||
| `customer.address.houseNumber` | `company.cmp_hsno` | Hausnummer liegt hier außerhalb der Adresstabelle |
|
||||
| `customer.address.postalCode/city/country` | `address.ad_zipcode`, `ad_city`, `ad_country` | Wie Straße |
|
||||
| `customer.visible/archived/authorized` | `company.cmp_visible`, `cmp_archived`, `cmp_authenticated` | Drei unterschiedliche Zustände |
|
||||
| `customer.discount/fixedPriceDiscount` | `customer.cs_discount`, `cs_fixprice_discount` | Prozentwerte; historische Tarif-/Änderungslogik zusätzlich prüfen |
|
||||
| `customer.paymentTerm` | `customer.cs_payment_term` | Vorhandene Bedeutung/Einheit am Bestand verifizieren |
|
||||
|
||||
Lese-Joins: `votian/include/inc_customer.inc.php:31`, `:70`; vollständige Feldliste `votian/include/mcglobal.inc.php:217`. Eindeutigkeitsprüfung `votian/admin/customer_special.php:797`.
|
||||
|
||||
Bestehende Anlagefolge in `votian/include/inc_customer.inc.php:678`: `costcenter` anlegen, `user` vom Typ `2`, `employee` mit Kostenstellen-/Rechtebezug, `company`, `customer`, anschließend `costcenter.cs_id` zurückverknüpfen, Adresse verknüpfen und mehrere `costcenteraddress`-Arten anlegen (`:746`, `:757`, `:762`). Eine alleinige Anlage in `customer` wäre zu dieser Fachlichkeit nicht kompatibel. Die Feldlisten für Änderungen stehen in `votian/admin/customer_special.php:823`, `:840`, `:844`; sie aktualisieren Firma, Kunde und Kontaktbenutzer separat. Das ist eine Analyse der Altlogik, keine Aufforderung zu Teständerungen am Bestand.
|
||||
|
||||
### Kostenstelle und Kostenstellenadresse
|
||||
|
||||
| API-Feld | Bestehende Spalte |
|
||||
|---|---|
|
||||
| `costCenter.id/customerId/name` | `costcenter.csc_id`, `cs_id`, `csc_name` |
|
||||
| `costCenter.parentId/path` | `costcenter.csc_pre_id`, `csc_path` |
|
||||
| `costCenter.visible/blocked/external` | `costcenter.csc_visible`, `csc_blocked`, `csc_is_extern` |
|
||||
| `costCenter.invoiceInterval/invoiceType` | `costcenter.csc_inv_interval`, `csc_inv_type` |
|
||||
| `costCenterAddress.typeId/addressId` | `costcenteraddress.adt_id`, `ad_id` |
|
||||
| `costCenterAddress.company/houseNumber/contact/phone/email` | `cscad_comp`, `cscad_hsno`, `cscad_person`, `cscad_phone`, `cscad_email` |
|
||||
| `costCenterAddress.street/postalCode/city` | `address.ad_street`, `ad_zipcode`, `ad_city` über `costcenteraddress.ad_id = address.ad_id` |
|
||||
|
||||
Leseabfragen: `votian/include/inc_customer.inc.php:973`, `:998`. Anlage in `votian/customer/costcenter.php:77` prüft kundenspezifisch eindeutige Namen, setzt `cs_id`, `csc_pre_id`, `csc_name`, `csc_path`, `csc_visible` und übernimmt Adressen/Rechnungsintervall der Hauptkostenstelle. Umbenennen/Anzeige/Rechnungsdaten werden separat aktualisiert (`:172`, `:193`, `:375`). `csc_path` enthält im untersuchten Aufbau Namen und Trenner; nicht ohne Nachweis als reine ID-Liste interpretieren.
|
||||
|
||||
### Kurier, Kontakt und Fahrzeug
|
||||
|
||||
| API-Feld | Bestehende Spalte / Beziehung |
|
||||
|---|---|
|
||||
| `courier.id/number/dispatchSid` | `courier.cr_id`, `cr_eid`, `cr_sid` |
|
||||
| `courier.companyId/userId/headquarterId` | `courier.cmp_id`, `usr_id`, `hq_id` |
|
||||
| `courier.companyName` | `company.cmp_comp` über `courier.cmp_id = company.cmp_id` |
|
||||
| `courier.firstName/lastName/phone/email` | `user.usr_firstname`, `usr_name`, `usr_phone`, `usr_email` über `courier.usr_id = user.usr_id` |
|
||||
| `courier.vehicleTypeId` | `courier.vht_id`; nicht mit `vht_id_inv` für Abrechnung verwechseln |
|
||||
| `courier.available/availableAt/locationPostalCode` | `courier.cr_available`, `cr_availabletime`, `cr_locationzipcode` |
|
||||
| `courier.maxWeight/outlayLimit` | `courier.cr_maxweight`, `cr_outlay` |
|
||||
| `courier.disposition/appBlocked` | `courier.cr_disposition`, `cr_app_blocked` |
|
||||
| `vehicle.id/courierId/dispatchSid/typeId` | `couriervehicle.crvh_id`, `cr_id`, `crvh_sid`, `vht_id` |
|
||||
| `vehicle.licensePlate/payload` | `couriervehicle.crvh_vh_sign`, `crvh_payload` |
|
||||
|
||||
Lese-Joins: `votian/include/inc_courier.inc.php:32`, `:68`; Fahrzeugfelder: `votian/include/mcglobal.inc.php:206`.
|
||||
|
||||
Anlage erzeugt zuerst `user` vom Typ `3`, dann `company`, `courier` und Adresse (`votian/include/inc_courier.inc.php:645`, `:653`, `:682`, `:694`). Die Änderungsmaske schreibt Firma, Kurier und Benutzer getrennt (`votian/admin/courier_special.php:486`, `:525`, `:549`). Der aktuelle Kommentar vor dem Kurier-Update weist ausdrücklich darauf hin, dass `cr_sid` aus diesem allgemeinen Update entfernt wurde (`:524`); SID deshalb nicht ungeprüft als frei editierbares Stammdatenfeld behandeln. Änderungen an der Gerätenummer können weitere Zuordnungen beeinflussen; für einen einfachen Kontakt-Edit ist `usr_phone` maßgeblich, nicht automatisch `cr_mobile_pda`.
|
||||
|
||||
### Authentisierung und Autorisierung
|
||||
|
||||
| Zweck | Bestehende Felder / Beziehungen |
|
||||
|---|---|
|
||||
| Kontosuche | `user.usr_account`; Ergebnis `usr_id`, `hq_id`, `usr_type` |
|
||||
| Passwortprüfung | `user.usr_password`, gegebenenfalls `usr_password_old`; nur intern verwenden, nie API-Ausgabe |
|
||||
| Mitarbeiterbezug | `employee.usr_id = user.usr_id`; `emp_id`, `csc_id`, `emp_rights`, `emp_heritable_rights` |
|
||||
| Rollen | `usr_type`: `1` Zentrale, `2` Kunde, `3` Kurier, `4` Lager; Typ `0` separat prüfen |
|
||||
| Niederlassungszugriff | `user.hq_id`, Mitarbeiterkontext und besondere Freigaben; nicht nur Rolle |
|
||||
| Erweiterte Niederlassungsrechte | `employeerights.emp_id`, `hq_id`, `rgt_id` |
|
||||
| Kundenzulassung | `employee.csc_id → costcenter.cs_id → customer.cmp_id → company.cmp_authenticated` |
|
||||
| Kurierzuordnung | `courier.usr_id = user.usr_id` |
|
||||
|
||||
Der untersuchte Login prüft gegen die Datenbankfunktionen `PASSWORD()` und `OLD_PASSWORD()` (`votian/admin/login.php:484`, `:494`), und `cryptDbPassword` ruft ebenfalls `PASSWORD()` auf (`votian/include/dbglobal.inc.php:458`). Ein pauschaler BCrypt-Vergleich wäre deshalb nicht mit diesem Legacyzweig kompatibel. Passwortwerte oder Formate wurden hier nicht aus der Datenbank gelesen. Die konkret eingesetzte Datenbankversion und die vorhandenen Hashformate müssen vor Implementierung der Prüfung sicher geklärt werden. Die im Altlogin enthaltene automatische Passwortänderung wird bei einer rein lesenden Anbindungsprüfung nicht übernommen.
|
||||
|
||||
Die Benutzer-/Mitarbeiterbeziehung wird beim Login aufgelöst (`votian/admin/login.php:531`). Kunden müssen zusätzlich freigeschaltet sein (`:545`). Aktionsrechte werden über `employee.emp_rights` geprüft, können beim Niederlassungswechsel eingeschränkt werden und werden durch eine separate Niederlassungsrechtematrix ergänzt (`votian/include/dbglobal.inc.php:815`, `:841`; `votian/include/auth.inc.php:315`). Ein erfolgreiches Passwort allein berechtigt daher nicht zum Zugriff auf sämtliche Aufträge.
|
||||
|
||||
|
||||
### Präzisierungen für einen lesenden HQ-Zugang
|
||||
|
||||
Für einen Zugang als Zentralenmitarbeiter (`usr_type=1`) benötigt der Legacy-Prüfpfad eine existierende, positive `emp_id` mit `employee.usr_id = user.usr_id`. Der Niederlassungsschlüssel stammt aus `user.hq_id`, nicht aus einem unbelegten Feld `employee.hq_id`. Zunächst ist der eigene HQ-Bereich zu verwenden; Mehrfachzugriff setzt besondere Freigaben und Rechtebeschränkungen voraus (`votian/include/auth.inc.php:214`; `votian/include/dbglobal.inc.php:815`).
|
||||
|
||||
Der Login-Join fordert eine existierende `headquarters`-Zeile (`votian/admin/login.php:494`). Die allgemeine Authentisierungsinitialisierung verlangt außerdem einen gültigen Mandantenbezug über `mandatorheadquarters.hq_id → md_id` (`votian/include/auth.inc.php:115`). In den untersuchten Dateien `admin/login.php`, `include/auth.inc.php`, `admin/employee.php`, `admin/user_list.php` und `include/dbglobal.inc.php` wurde keine Loginprüfung anhand von `usr_active`, `usr_disabled`, `usr_deleted`, `emp_active` oder `emp_disabled` gefunden; diese Felder dürfen nicht in SQL erfunden werden. Das belegt nicht ihre Abwesenheit in jedem Datenbankstand. `hq_disabled` existiert als Auswahlfilter (`votian/jobs/job_header.php:79`), wird aber im untersuchten Passwort-Login nicht geprüft. Ob die neue Anmeldung eine deaktivierte HQ ausdrücklich ablehnt, ist als eigene Regel festzulegen und gegen den Bestand zu prüfen.
|
||||
|
||||
Die folgende HQ-Rechtematrix verwendet **nullbasierte** Indizes in `employee.emp_rights`. Sie gilt nicht automatisch für Kundenbenutzer:
|
||||
|
||||
| Zugriff | Bitindex | Quelle |
|
||||
|---|---|---|
|
||||
| Kunden | `0` | `votian/admin/menu.php:214` |
|
||||
| Kuriere/Transporteure | `1` | `votian/admin/menu.php:215` |
|
||||
| Auftragslisten | `4` | `votian/admin/menu.php:206` |
|
||||
| Rechnungsübersicht, PDF-/CSV-Ausgabe | `5` | `votian/admin/menu.php:254`, `:258`, `:259` |
|
||||
| Allgemeiner Datenexport | `6` | `votian/admin/menu.php:265` |
|
||||
| Auftragserfassung | `7` | `votian/admin/menu.php:246` |
|
||||
| Statistik | `8` | `votian/admin/menu.php:211` |
|
||||
|
||||
Diese Zugriffe müssen auch bei einer lesenden API serverseitig geprüft werden. Dashboard-Zahlen und Preiszusammenfassungen unterliegen ebenfalls den passenden Lese-/Abrechnungsrechten. Vorhandene PHP-Links besitzen ihre eigene Sitzung und Authentisierung; aus einem erfolgreichen Login der neuen Oberfläche folgt noch keine automatisch angemeldete PHP-Sitzung.
|
||||
|
||||
## Anhang B. Geprüfte PHP-Modulziele
|
||||
|
||||
Die folgenden Pfade sind relativ zur konfigurierten Basis-URL der vorhandenen `votian`-Installation. Sie öffnen Module und übermitteln keine Speicher-, Lösch-, Storno- oder Importausführungsaktion. Die Funktionsprüfung erfolgte am Quelltext; eine aktive PHP-Sitzung, Berechtigungen und eine laufende Installation bleiben Voraussetzung.
|
||||
|
||||
| Ziel | Relativer Pfad | Quellbeleg |
|
||||
|---|---|---|
|
||||
| Neuer Auftrag | `jobs/job_edit.php` | `votian/admin/menu.php:248` |
|
||||
| Auftrag auswählen/bearbeiten | `admin/jb_list.php` | `votian/admin/jb_list.php:33` |
|
||||
| Kundenverwaltung | `admin/customer_list.php` | `votian/admin/menu.php:214` |
|
||||
| Kurierverwaltung | `admin/courier_list.php` | `votian/admin/menu.php:215` |
|
||||
| Rechnungsübersicht | `invoice/invoice.php` | `votian/admin/menu.php:254` |
|
||||
| Servicepreise | `admin/services.php?mode=price` | `votian/admin/menu.php:268` |
|
||||
| PLZ-Preise | `admin/services_plz.php?mode=price` | `votian/admin/menu.php:269` |
|
||||
| Datenimport/-transfer | `import/data_transfer.php` | `votian/admin/menu.php:266` |
|
||||
| Datenexport | `export/export.php` | `votian/admin/menu.php:265` |
|
||||
| Statistik | `statistic/statistic.php` | `votian/admin/menu.php:211` |
|
||||
|
||||
Objektbezogene Links werden im Bestand normalerweise als `jobs/job_edit.php?jb_id=ec(jb_id)`, `admin/customer_special.php?companyId=ec(cmp_id)` und `admin/courier_special.php?companyId=ec(cmp_id)` erzeugt. `companyId` ist der Firmenschlüssel `cmp_id`, nicht die Kunden-ID `cs_id` und nicht die Kurier-ID `cr_id`. Quellen: `votian/include/jb_list_defineoutput.inc.php:665`, `votian/admin/customer_list.php:854`, `votian/admin/courier_list.php:712`.
|
||||
|
||||
`ec()` hängt von `HTTP_VARS_SEC_STATE`, einer Markierungssequenz und dem PHP-Sitzungskontext ab. `getSecHttpVars("1", …)` ruft `dc()` auf. Die untersuchte Implementierung von `dc()` lässt unmarkierte Werte unverändert; Klartext-IDs sind daher auf Quelltextebene nicht grundsätzlich ungültig. Eine eigene Nachbildung der Codierung oder ein beliebig erzeugter codierter Wert ist trotzdem kein nachgewiesen funktionsfähiger Link. Quellen: `votian/include/global.inc.php:57`, `:846`, `:868`.
|
||||
|
||||
Für die erste Anbindung sind Module ohne Objektparameter die belastbarere Option. Direkte Objektlinks benötigen eine Prüfung mit der tatsächlichen PHP-Konfiguration und einem erlaubten Testkonto. Es werden keine schreibenden `f_act`-Parameter konstruiert.
|
||||
|
||||
## Anhang C. Bei der Adapterprüfung besonders zu beachtende Bedeutungen
|
||||
|
||||
- `job.jb_totalprice` enthält den Kundenpreis einschließlich der dort angewendeten Zuschläge, während `jb_subtotalprice` im untersuchten Festpreiszweig den Zuschlag nicht enthält. Die Steuer wird gesondert berechnet. Eine Anzeige des vollständigen Nettopreises darf deshalb nicht ungeprüft auf `jb_subtotalprice` zugreifen (`votian/jobs/job_options.php:1828`, `:1886`, `:2140`).
|
||||
- `job.jb_service` wird als Bitmaske verwendet. Im Filter wird `2^mt_sort` getestet; ein einfacher Gleichheitsjoin `metatype.mt_sort = job.jb_service` ist für Kombinationen falsch (`votian/admin/jb_list.php:1158`). Fahrzeugtypen verwenden hingegen tatsächlich `metatype.mt_sort = job.vht_id` (`:1177`).
|
||||
- Kilometer werden im untersuchten Speicherpfad als `jobprice.jbprc_price` mit `mt_sort=11` gespeichert. Ein Feld `job.jb_km` darf daraus nicht abgeleitet werden (`votian/jobs/job_options.php:224`, `:2097`).
|
||||
- Packstücke werden über `SUM(tourarticle.trat_packingpieces)` ermittelt, Artikelgewichte über `SUM(tourarticle.trat_weight)`; `job.jb_weight` ist daneben ein vorhandenes Auftragsfeld (`votian/include/inc_job.inc.php:91`, `:112`).
|
||||
- Die Historie liegt im untersuchten Zugriff unter `phoenix_log.log`. Eine nicht verfügbare Historienanbindung darf nicht als nachgewiesen leere Historie erscheinen; sie benötigt eine ausdrückliche Kennzeichnung (`votian/include/caglobal.inc.php:2254`).
|
||||
@@ -0,0 +1,70 @@
|
||||
# Prüfstatus der ersten Bestandsanbindung
|
||||
|
||||
Stand: 1. Oktober 2026.
|
||||
|
||||
## Aktuelle Umstellung auf den zentralen Datenbankservice
|
||||
|
||||
Die neue Anwendung verwendet für jeden Datenbankzugriff `database.DatabaseService`, einschließlich Anmeldung, Listen, CSV-Leseabfragen, Verbindungstest und Schemadiagnose. Python ist bei der Diagnose nur noch der Launcher des Java-JARs. Der zentrale Schreibzugang bleibt gesperrt. Architekturtests erzwingen die Grenze auch für die Integrationstests; die PHP-Altanwendung bleibt unverändert.
|
||||
|
||||
Nach wiederhergestellter Datenbankverbindung wurden am 1. Oktober 2026 um 17:00 Uhr **49 Backend-Tests einschließlich des Integrationstests gegen die Bestandsdatenbank** erfolgreich ausgeführt: keine Fehler, keine übersprungenen Tests. Außerdem bestanden alle **10 Python-Tests**. Der Integrationstest lädt Aufträge, Kunden und Kuriere über die API und den zentralen Service mit simuliertem Anwendungskonto und echten SELECT-Abfragen.
|
||||
|
||||
Die erneute Java-CLI-Diagnose war ebenfalls erfolgreich: MariaDB `11.7.2-MariaDB-ubu2404-log`, 13 geprüfte Tabellen, keine fehlenden erforderlichen Spalten. Es wurden keine Daten oder Tabellen geändert. Die Anwendung bleibt gestoppt; nach den Tests waren die Ports 8080 und 5173 frei.
|
||||
|
||||
Im ersten erreichbaren Testlauf fiel eine ungeeignete Prüfung von `@@session.tx_read_only` auf: Dieser Wert beschreibt den Sessionstandard, nicht den Modus der einzelnen Transaktion. Die Prüfung wurde ersetzt und der Service aktiviert nun ausdrücklich `DataSourceTransactionManager.setEnforceReadOnly(true)`. Ein zusätzlicher Test mit echtem Transaktionsmanager und gemockter Verbindung prüft die Reihenfolge `SET TRANSACTION READ ONLY → SELECT → COMMIT`; es gibt keine Schreibversuche gegen den Bestand. Grundlagen: [MariaDB SET TRANSACTION](https://mariadb.com/docs/server/reference/sql-statements/administrative-sql-statements/set-commands/set-transaction), [Spring DataSourceTransactionManager](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/datasource/DataSourceTransactionManager.html#setEnforceReadOnly(boolean)).
|
||||
|
||||
Der zuvor bei unterbrochener Verbindung geprüfte Fehlerfall bleibt gültig: Der CLI-Modus liefert bereinigtes JSON mit `reason: UNAVAILABLE`, Exitcode 1 und startet keinen Webserver.
|
||||
|
||||
## Durchgeführt
|
||||
|
||||
| Prüfung | Ergebnis |
|
||||
|---|---|
|
||||
| React-/TypeScript-Produktionsbuild | Erfolgreich |
|
||||
| Spring-Boot `clean verify`, inklusive gebündeltem React | Erfolgreich |
|
||||
| 20 Backend-Tests ohne Bestandszugriff | Erfolgreich: Legacy-Mapping einschließlich Boolean-Flags und mehrwertiger Statuscodes, Rechte, Niederlassung, CSV, gesperrte Schreibmethoden |
|
||||
| 1 optionaler Integrationstest mit vorhandener Datenbank | Erfolgreich: Auftrags-, Kunden- und Kurier-API über MockMvc mit echten JDBC-Abfragen; Test-Authentifizierung, keine Datenänderungen |
|
||||
| 7 Python-Konfigurationstests | Erfolgreich: Kommentare, Escaping, Umgebungspriorität, keine PHP-Ausführung |
|
||||
| 1 HTTP-Integrationstest gegen das gebaute JAR | Erfolgreich: Health, Offline-Systemzustand, geschützte API, öffentliche Logo-Datei |
|
||||
| Manuelle Browserprüfung im integrierten Browser | Anmeldung mit Testantworten, Auftragsliste, Mehrstoppdetails, Disposition, Touren, Kunden, Kuriere, Abrechnungshinweis, Auswertung, serverseitige Suche, Logout und eingeschränktes Folgekonto geprüft |
|
||||
| Browserprüfung mit fehlenden Preisen und Terminen | Keine Browserfehler; unbekannte Werte bleiben „–“, Summen als unvollständig gekennzeichnet |
|
||||
| Abhängigkeiten des Frontends | `npm install` meldet keine bekannten Sicherheitslücken |
|
||||
| Verbindung und Schemametadaten der Bestandsdatenbank | Erfolgreich mit `scripts/check-database.py`: 13 Tabellen geprüft, keine erforderlichen Spalten fehlen; keine Anwendungsdatensätze gelesen und keine Schreibzugriffe |
|
||||
| Backend nach Neustart mit dem konfigurierten Datenbankkonto | Erfolgreich: `GET /api/health` liefert `status: UP`; `GET /api/system` liefert `connected: true`, `reason: CONNECTED`, `readOnly: true`, `schemaChanges: false` |
|
||||
|
||||
Für die Browserprüfung diente ausschließlich ein separater lokaler HTTP-Testserver mit ausdrücklich markierten Testantworten. Er ist kein Bestandteil der Anwendung und hat keine Datenbank. Es wurden keine Testdatensätze in MySQL angelegt. Die vollständige automatisierte Playwright-Browsersuite ist vorbereitet, konnte hier wegen eines abgewiesenen Chrome-Prozessstarts nicht ausgeführt werden; sie wird nicht als bestanden gewertet. Die entsprechende Bedienung wurde im integrierten Browser geprüft.
|
||||
|
||||
## Verbindung zur Bestandsdatenbank
|
||||
|
||||
Die lokale Verbindungskonfiguration steht in der `.env` im Projektstamm: `DB_URL` enthält Host, Port und Datenbanknamen; `DB_USER` und `DB_PASSWORD` enthalten das Datenbankkonto. Die Prüfung am 1. Oktober 2026 mit `scripts/check-database.py` war erfolgreich:
|
||||
|
||||
- Verbindung: `connected: true`
|
||||
- Serverversion: `11.7.2-MariaDB-ubu2404-log`
|
||||
- Geprüfte Tabellen: `checkedTables: 13`
|
||||
- Fehlende erforderliche Spalten: `missingColumns: {}`
|
||||
- Gelesene Anwendungsdatensätze: `applicationRowsRead: 0`
|
||||
- Schreibzugriffe: `writes: 0`
|
||||
|
||||
Die mit dem zuvor verwendeten Datenbankkonto aufgetretene Anmeldungssperre (MySQL-Fehler **1045**, auch beim Versuch mit TLS) blockiert den Zugriff mit dem anschließend konfigurierten Datenbankkonto nicht mehr. Die Prüfung hat ausschließlich Server- und Schemametadaten gelesen; sie bestätigt die Existenz der vom Prüfskript benötigten Tabellen und Spalten.
|
||||
|
||||
## Noch nicht erfolgreich geprüft
|
||||
|
||||
Die SQL-Zuordnungen beruhen auf dem vorhandenen PHP-Quellcode. Die drei Listen wurden mit jeweils 500 Bestandsdatensätzen erfolgreich gelesen. Der Fehler beim Kunden-/Kurierlesen wurde zuvor als `NumberFormatException` bei `company.cmp_archived` reproduziert: JDBC lieferte einen Boolean, der Mapper erwartete eine Zahl. Der Mapper akzeptiert nun Boolean-Flags; `tinyInt1isBit=false` erhält außerdem mehrwertige numerische Legacy-Codes. Alle 21 Backend-Tests einschließlich der optionalen Bestandsprüfung bestanden nach der Korrektur.
|
||||
|
||||
Die Bestandsprüfung verwendet ausschließlich für den Test eine simulierte Authentifizierung innerhalb einer vorhandenen Niederlassung. Sie bestätigt weder die reale Benutzeranmeldung noch sämtliche Filter und Berechtigungsgrenzen. Diese sowie die fachlichen Ergebnisse sind weiterhin gegen die PHP-Anwendung zu vergleichen.
|
||||
|
||||
### Tagesansicht der offenen Aufträge
|
||||
|
||||
Am 1. Oktober 2026 wurde die Auswahl für das vorhandene Zentralenkonto `admin_b` zusätzlich mit dessen Niederlassung und Rechten über den echten Leseadapter geprüft: Status `DISPOSITION` und Abholdatum 1. Oktober 2026 liefern genau einen Auftrag, `21891299`. Die zuvor fehlende Datumseinschränkung hatte auch historische und weit in der Zukunft geplante Aufträge geladen. Die Oberfläche verwendet wie die Standardliste im PHP-Bestand den heutigen lokalen Kalendertag als vorbelegten Zeitraum; andere Zeiträume bleiben über die Filter auswählbar. Es gibt keine fest programmierte Konto- oder Auftragsausnahme und keine Statusänderung in der Datenbank.
|
||||
|
||||
Frontend- und Backend-Build nach dieser Änderung erfolgreich (20 reguläre Backend-Tests bestanden; die optionale Bestands-Testsuite in diesem Build deaktiviert). Im Browser mit isolierten Testantworten geprüft: Schon die erste Listenanfrage enthält beide Tagesgrenzen; ein bewusst erweiterter Zeitraum zeigt zusätzlich einen Zukunftsauftrag; „Heute“ reduziert die Liste wieder auf den Tagesbestand. Das laufende Backend wurde neu gestartet und liefert den aktualisierten Frontend-Build.
|
||||
|
||||
## Bewusst noch offene Fachlichkeit
|
||||
|
||||
Die neue Oberfläche und der JDBC-Leseadapter sind eine erste Ausbaustufe, keine vollständige fachliche Ablösung. Noch offen sind insbesondere:
|
||||
|
||||
- Native Auftragserfassung/-bearbeitung, Disposition mit Fahrerkommunikation, Stationsabschluss und Storno einschließlich Gegenbuchungen.
|
||||
- Originale Tarife, Preisgültigkeiten, Rabatte, Zuschläge, Kurierabrechnung, Rechnungserstellung und Buchhaltungsexporte.
|
||||
- Kostenstellenhierarchie, separate Fahrzeuge, Daueraufträge, Tourvorlagen, Lager/Artikel und kundenspezifische Schnittstellen.
|
||||
- Kunden-/Kurierportale, zusätzliche Niederlassungsrechte, Archiv- und Log-Datenbanken.
|
||||
- Konfiguration der tatsächlich vorhandenen PHP-Basisadresse `LEGACY_APP_URL`, um noch nicht portierte Fachabläufe gezielt aufzurufen.
|
||||
|
||||
Die Detailanalyse steht in `ALTSYSTEM-ANALYSE.md`. Es gibt keine neue Datenbank, keine automatische Schemaänderung und keinen Seed-Mechanismus. Die bisherige PHP-Anwendung wurde durch diese Umsetzung nicht verändert.
|
||||
Reference in new issue
Block a user