Überblick
Send ist ein Startup für die Lieferung auf der letzten Meile, das lokale Unternehmen mit Fahrern verbindet. Ich war der alleinige Backend-Entwickler und habe eine Laravel-REST-API für eine Flutter-App (Fahrer und Verkäufer) sowie ein Vue.js-Admin-Dashboard gebaut, das ich ebenfalls komplett selbst umgesetzt habe.
Die Plattform unterstützt drei Nutzerrollen (Administratoren, Verkäufer und Fahrer), die jeweils über einen eigenen Laravel-Sanctum-Guard authentifiziert werden. Verkäufer reichen Lieferaufträge für eine oder mehrere Abladestellen ein. Das Backend plant eine Route, berechnet den Preis, ordnet einen Fahrer zu und verfolgt die Lieferung bis zum Abschluss.
Dies war mein erstes berufliches Projekt: von der Datenbankplanung bis zu einem vollständigen Backend und Dashboard, mit rund 85 API-Endpunkten und 15 Kernmodellen. Send ist noch nicht öffentlich gestartet, der Gründer peilt den Start in Kürze an.
Routenoptimierung mit mehreren Stopps
Ein Verkäufer kann mehrere Abladestellen zu einem Lieferauftrag bündeln. Den nachweislich kürzesten Weg durch alle zu finden, ist das Problem des Handlungsreisenden (NP-schwer) und für die Stoppzahlen, die ein einzelner Fahrer tatsächlich ansteuert, überdimensioniert. Das Backend nutzt stattdessen eine Nearest-Neighbor-Heuristik:
Ausgehend vom Standort des Verkäufers springt sie wiederholt zum nächstgelegenen verbleibenden Stopp und summiert dabei die Großkreisdistanz. Diese Gesamtdistanz wird einer Preisstufe nach Distanzzonen zugeordnet (jede Zone mit eigenem Grundpreis, Kilometerpreis und Gebühr pro Stopp), woraus sich der Fahrpreis ergibt.
Es ist eine gierige Näherung auf Basis der Luftlinie statt der tatsächlichen Straßenentfernung. Das war ein bewusster Kostenkompromiss: In der Größenordnung, in der das Startup arbeitete, war die Einbindung eines kostenpflichtigen Routing-Dienstes nicht gerechtfertigt.
Zentrale Ingenieurbeiträge
- Multi-Rollen-API-Architektur: Entwurf und Aufbau von drei unabhängig abgesicherten API-Bereichen (Admin, Verkäufer, Fahrer) auf Laravel Sanctum, mit gemeinsamen Endpunkten für rollenübergreifende Ressourcen wie Bestellungen und Lieferaufträge.
- Routenplanung und Preisgestaltung: Umsetzung der oben beschriebenen Nearest-Neighbor-Routenoptimierung, gekoppelt an die Preis-Engine nach Distanzzonen.
- Fahrerzuordnung: Aufbau einer Zuordnung zum nächstverfügbaren Fahrer anhand der Live-Standorte der Fahrer, unter Berücksichtigung von Fahrzeugtyp und Verfügbarkeit.
- Admin-Dashboard: Aufbau des vollständigen Vue-3-/Vuetify-Betriebs-Dashboards (Onboarding- und Freigabewarteschlangen für Fahrer und Verkäufer, Preis- und Empfehlungskonfiguration, Zahlungs- und Abrechnungsverfolgung sowie KPI- und Analyseansichten), das die von mir entworfene API nutzt.
- Benachrichtigungen: Integration von Firebase Cloud Messaging für Push-Benachrichtigungen an Fahrer und Verkäufer sowie der WhatsApp Cloud API für Bestellbestätigungen, Lieferabschlüsse und Bewertungsanfragen an Verkäufer.
- Empfehlungssystem: Aufbau eines Empfehlungsprogramms für Verkäufer mit prozentualen Boni, die pro Lieferung erfasst werden.
- Authentifizierung und Onboarding: Umsetzung von Google-OAuth-Login für alle drei Nutzertypen neben der Standard-Anmeldung per Zugangsdaten.
Technischer Stack
| Komponente | Technologien |
|---|---|
| Backend | PHP, Laravel |
| Datenbank | MySQL |
| Authentifizierung | Laravel Sanctum (Multi-Guard), Google OAuth |
| API-Architektur | REST-API |
| Admin-Dashboard | Vue 3, Vuetify |
| Push-Benachrichtigungen | Firebase Cloud Messaging |
| Messaging | WhatsApp Cloud API |
Rückblick
Send war der Ort, an dem ich gelernt habe, ein Backend von Anfang bis Ende zu verantworten (Schema, API, Integrationen und das Dashboard, das alles nutzt), ohne einen erfahrenen Entwickler, an dem ich mich orientieren konnte.
Was ich rückblickend ändern würde
- Validierung in
FormRequest-Klassen statt inline im Controller - Geschäftslogik in Service-Klassen statt in aufgeblähten Controllern
- Antworten über API Resources
- Fahrerzuordnung als Queue-Job mit sauberem Locking rund um die Zuweisung, statt sie ungeschützt inline auszuführen
Diese Lektion prägt heute, wie ich jede Laravel-Codebasis strukturiere, mit der ich arbeite.