Wie Magento MSI geografische Entfernung und Priorität bei mehreren Lagern kombiniert
Wer mehrere Lager in unterschiedlichen Regionen betreibt, steht bei MSI vor der Frage, ob Distance oder Priority die passende Auswahl trifft. Beide Algorithmen sind Standard, funktionieren aber grundlegend unterschiedlich: Der eine rechnet, der andere zählt eine feste Liste ab. Dieser Artikel zeigt, wie das Geocoding der Sources tatsächlich funktioniert, wie die Prioritäts-Konfiguration pro Source wirkt und wie ein realistisches Setup mit mehreren regionalen Lagern aussieht.
Inhaltsverzeichnis
- 1. Zwei unterschiedliche Philosophien der Source-Auswahl
- 2. Wie das Geocoding der Sources funktioniert
- 3. Die eigentliche Distanzberechnung
- 4. Prioritäts-Konfiguration pro Source im Priority-Algorithmus
- 5. Praktisches Beispiel: Drei Lager in unterschiedlichen Regionen
- 6. Kombinierte Strategie für wachsende Lagernetze
- 7. Häufige Fehlerquellen bei Distance-Setups
- 8. Performance-Überlegungen bei vielen Sources
- 9. Konfigurierbarkeit der Algorithmus-Wahl
- 10. Zusammenfassung
- 11. FAQ
1. Zwei unterschiedliche Philosophien der Source-Auswahl
Priority arbeitet komplett ohne Berechnung: Jede Source erhält in der Stock-Source-Zuordnung eine ganzzahlige Priorität, und der Algorithmus geht diese Liste streng der Reihe nach durch, bis die angefragte Menge gedeckt ist. Es gibt keine Rücksicht auf die Lieferadresse, keine Distanzberechnung und keine Laufzeitkosten für Geo-Lookups, was Priority zum performantesten der beiden Standardalgorithmen macht.
Distance hingegen berechnet für jede Bestellung die tatsächliche Entfernung zwischen der Lieferadresse des Kunden und der Adresse jeder Source und sortiert danach. Das ist näher an dem, was Kunden intuitiv erwarten, nämlich dass aus dem nächstgelegenen Lager versendet wird, kostet aber bei jeder Anfrage zusätzliche Rechenzeit für das Geocoding und die Distanzberechnung.
2. Wie das Geocoding der Sources funktioniert
Damit Distance überhaupt rechnen kann, benötigt jede Source geografische Koordinaten. Diese werden nicht automatisch beim Speichern einer Source ermittelt, sondern müssen über den Geocoding-Provider aufgelöst werden, den Magento standardmäßig über einen Google-Maps-API-Key anbindet. Beim Speichern einer Source-Adresse im Backend wird im Hintergrund ein API-Aufruf ausgelöst, der Strasse, Postleitzahl, Stadt und Land in Latitude und Longitude übersetzt und diese Werte in der Tabelle inventory_source persistiert.
Schlägt dieser Aufruf fehl, etwa wegen einer ungültigen Adresse, eines fehlenden API-Keys oder eines Kontingent-Limits bei Google, bleibt die Source ohne Koordinaten. Der Distance-Algorithmus behandelt eine solche Source dann als nicht bewertbar und schließt sie faktisch von der Auswahl aus, auch wenn dort ausreichend Bestand vorhanden wäre. Dieser stille Ausschluss ist eine der häufigsten Fehlerquellen bei Distance-Setups und fällt oft erst auf, wenn eine neue Source angelegt, aber nie beliefert wird.
<?php
declare(strict_types=1);
namespace Mironsoft\InventoryGeocodingCheck\Console\Command;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Lists all active sources missing geocoded coordinates, which would
* silently exclude them from the Distance algorithm.
*/
class ListUngeocodedSourcesCommand extends Command
{
/**
* @param SourceRepositoryInterface $sourceRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
*/
public function __construct(
private readonly SourceRepositoryInterface $sourceRepository,
private readonly SearchCriteriaBuilder $searchCriteriaBuilder
) {
parent::__construct();
}
/**
* Configures the command name.
*
* @return void
*/
protected function configure(): void
{
$this->setName('mironsoft:source:list-ungeocoded');
}
/**
* Iterates all active sources and prints those without valid coordinates.
*
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$criteria = $this->searchCriteriaBuilder->addFilter('enabled', 1)->create();
$sources = $this->sourceRepository->getList($criteria)->getItems();
foreach ($sources as $source) {
if ($source->getLatitude() === null || $source->getLongitude() === null) {
$output->writeln(sprintf(
'%s (%s) has no geocoded coordinates and is excluded from Distance selection.',
$source->getSourceCode(),
$source->getName()
));
}
}
return Command::SUCCESS;
}
}
3. Die eigentliche Distanzberechnung
Für die Distanzberechnung selbst nutzt Magento standardmäßig die Haversine-Formel, die die kürzeste Entfernung zwischen zwei Punkten auf einer Kugeloberfläche berechnet, also die Luftlinie und nicht die tatsächliche Fahrstrecke. Das ist ein bewusster Kompromiss: Eine echte Routenberechnung über eine Kartendienst-API wäre für jede Bestellung deutlich teurer und langsamer, während die Luftlinie für die meisten Fälle eine ausreichend gute Näherung liefert, besonders bei Lagern, die mehrere hundert Kilometer auseinanderliegen.
In Regionen mit stark unterschiedlicher Verkehrsinfrastruktur kann die Luftlinien-Näherung allerdings zu falschen Ergebnissen führen, etwa wenn zwei Lager durch ein Gebirge getrennt sind und die tatsächliche Fahrstrecke deutlich länger ist als die direkte Distanz. Für solche Fälle müsste ein eigener Algorithmus die Distance-Grundlogik um eine echte Routing-API erweitern, was für die meisten Betriebe jedoch unverhältnismäßig aufwendig ist.
4. Prioritäts-Konfiguration pro Source im Priority-Algorithmus
Die Priorität einer Source wird nicht global, sondern pro Stock-Source-Zuordnung gepflegt, im Backend unter Inventory Stocks bei der Bearbeitung eines Stocks. Jede zugeordnete Source erhält dort eine ganzzahlige Priorität, wobei ein niedrigerer Wert eine höhere Priorität bedeutet. Dieselbe Source kann in unterschiedlichen Stocks unterschiedliche Prioritäten haben, was für Betriebe mit mehreren, sich überschneidenden Absatzkanälen relevant ist, etwa wenn ein B2B-Stock ein anderes Hauptlager bevorzugt als der B2C-Stock desselben Unternehmens.
Wichtig ist, dass zwei Sources im selben Stock dieselbe Priorität erhalten können. In diesem Fall entscheidet die interne Sortierreihenfolge, in der die Source-Item-Datensätze aus der Datenbank geladen werden, was ohne explizite Sekundärsortierung faktisch undefiniert ist. Für produktive Setups sollte deshalb jede Source in einem Stock eine eindeutige Priorität erhalten, um dieses Verhalten vorhersehbar zu machen.
<!-- Ausschnitt: Stock-Source-Zuordnung über den ResourceModel, illustriert die
Datenstruktur hinter der Backend-Konfiguration von Inventory Stocks -->
<config>
<stock_source_links>
<link stock_id="10" source_code="warehouse-north" priority="1" />
<link stock_id="10" source_code="warehouse-central" priority="2" />
<link stock_id="10" source_code="warehouse-south" priority="3" />
</stock_source_links>
</config>
5. Praktisches Beispiel: Drei Lager in unterschiedlichen Regionen
Ein realistisches Setup für ein Unternehmen mit Kunden in Nord-, Mittel- und Süddeutschland besteht aus drei Sources: warehouse-north in Hamburg, warehouse-central in Frankfurt und warehouse-south in München, alle demselben Stock zugeordnet. Wird Priority gewählt, muss eine bewusste Reihenfolge festgelegt werden, etwa Frankfurt als zentrales Hauptlager mit höchster Priorität und die beiden Randlager als Ergänzung. Das funktioniert gut, solange die meisten Kunden geografisch verteilt sind, sorgt aber dafür, dass ein Kunde aus Hamburg trotzdem primär aus Frankfurt beliefert wird.
Wird stattdessen Distance gewählt, liefert derselbe Kunde aus Hamburg automatisch aus warehouse-north, ein Kunde aus München aus warehouse-south, ohne dass eine explizite Reihenfolge gepflegt werden muss. Der Vorteil zeigt sich vor allem in kürzeren Versandzeiten, der Nachteil liegt darin, dass Lagerauslastung und Bestandsverteilung nicht berücksichtigt werden. Ist warehouse-north knapp an Bestand, wählt Distance trotzdem konsequent das nächstgelegene Lager, auch wenn ein anderes Lager mit mehr Puffer geografisch weiter entfernt liegt.
6. Kombinierte Strategie für wachsende Lagernetze
In der Praxis wächst ein Multi-Source-Setup oft organisch: Zunächst gibt es ein Hauptlager mit Priority, später kommen regionale Außenlager hinzu, und die Frage nach Distance stellt sich erst dann. Ein sauberer Übergang gelingt, indem zunächst nur zwei oder drei geografisch klar getrennte Sources mit Distance getestet werden, bevor das gesamte Lagernetz umgestellt wird. So lassen sich Geocoding-Probleme und unerwartete Verteilungsmuster früh erkennen, ohne gleich das komplette Fulfillment umzustellen.
Für Betriebe, die sowohl geografische Nähe als auch Lagerauslastung berücksichtigen wollen, ist wie im vorherigen Artikel zum eigenen Source Selection Algorithmus beschrieben eine Kombination sinnvoll: Distance als grobe Vorauswahl der nächstgelegenen Sources, innerhalb dieser Vorauswahl dann eine Sortierung nach Auslastung. Das ist mit den Standardalgorithmen allein nicht abbildbar und erfordert eine eigene Implementierung des SourceSelectionInterface.
7. Häufige Fehlerquellen bei Distance-Setups
Der häufigste Fehler ist eine unvollständig gepflegte Source-Adresse, etwa ein fehlendes Land oder eine falsch formatierte Postleitzahl, die das Geocoding fehlschlagen lässt, ohne dass im Backend eine deutliche Fehlermeldung erscheint. Ein regelmäßiger Check aller aktiven Sources auf fehlende Koordinaten, wie im Beispiel oben gezeigt, verhindert, dass eine neue Source unbemerkt von der Auswahl ausgeschlossen bleibt.
Ein zweiter Fehler betrifft den API-Key selbst: Wird das Kontingent des Geocoding-Providers überschritten oder der Key ablaufen gelassen, schlagen neue Geocoding-Anfragen fehl, während bereits geocodete Sources weiterhin funktionieren. Das führt zu einem trügerischen Verhalten, bei dem bestehende Sources normal arbeiten, während jede neu angelegte Source stillschweigend nicht in der Distance-Berechnung berücksichtigt wird, bis das Kontingent-Problem behoben ist.
8. Performance-Überlegungen bei vielen Sources
Bei Stocks mit einer zweistelligen Anzahl an Sources berechnet Distance für jede Bestellung eine Haversine-Distanz zu jeder einzelnen Source, was bei sehr großen Lagernetzen spürbar wird. Die Berechnung selbst ist zwar mathematisch günstig, das eigentliche Kostenrisiko liegt eher darin, dass Distance häufiger als Priority im Checkout zur Live-Anzeige der voraussichtlichen Lieferzeit aufgerufen wird und dadurch pro Seitenaufruf mehrfach ausgeführt werden kann.
Für sehr große Lagernetze lohnt sich deshalb ein Caching der berechneten Distanzen pro Postleitzahlgebiet statt einer exakten Neuberechnung bei jeder Anfrage, da sich die Distanz zwischen einer Source und einem Postleitzahlgebiet praktisch nie ändert. Das reduziert die Rechenlast bei stark frequentierten Checkouts deutlich, ohne die Genauigkeit relevant zu verschlechtern.
9. Konfigurierbarkeit der Algorithmus-Wahl
Welcher Algorithmus verwendet wird, ist eine reine Stock-Konfiguration im Backend und erfordert keinen eigenen Code, solange die Standardalgorithmen genügen. Wichtig ist, dass diese Entscheidung dokumentiert und im Team bekannt ist, da sie direkten Einfluss auf Versandzeiten und Lagerauslastung hat und bei einem Wechsel spürbare Auswirkungen auf das operative Fulfillment haben kann.
Für eigene Erweiterungen, etwa eine konfigurierbare maximale Distanz, ab der eine Source gar nicht mehr in Frage kommt, gilt dasselbe Prinzip wie bei jedem anderen Mironsoft-Modul: eine eigene system.xml-Sektion mit acl.xml und Menüpunkt statt hartkodierter Schwellenwerte im Code, damit das Fulfillment-Team die Konfiguration selbstständig anpassen kann.
| Kriterium | Priority | Distance | Auswirkung |
|---|---|---|---|
| Berechnungsaufwand | Keiner, feste Liste | Haversine-Distanz je Source und Anfrage | Priority ist performanter bei vielen Sources |
| Voraussetzung | Prioritätswert je Stock-Source-Link | Geocoding-Koordinaten je Source | Fehlendes Geocoding schließt Sources still aus |
| Kundenerlebnis | Unabhängig vom Wohnort des Kunden | Nähestes Lager wird bevorzugt | Distance verkürzt tendenziell die Versanddauer |
| Lagerauslastung | Nicht berücksichtigt | Nicht berücksichtigt | Beide Algorithmen ignorieren aktuelle Kapazität |
| Geeignet für | Ein klar priorisiertes Hauptlager plus Backup | Mehrere regional verteilte, gleichwertige Lager | Wahl hängt von der Lagerstruktur ab |
Mironsoft
Magento-Entwicklung, Modul-Beratung und Systemarchitektur
Magento-Projekt, das eine zweite Meinung oder erfahrene Umsetzung braucht?
Wir entwickeln individuelle Magento-Module, beraten bei Architekturentscheidungen und übernehmen komplexe Umsetzungen, von der Service-Contract-Planung bis zum produktionsreifen Deployment.
Architektur-Beratung
Modul- und Systemarchitektur vor der Umsetzung fundiert durchdenken lassen.
Custom-Modul-Entwicklung
Individuelle Magento-Module nach Best Practices sauber umsetzen.
Code-Review & Audit
Bestehende Module auf Performance, Sicherheit und Wartbarkeit prüfen lassen.
10. Zusammenfassung
Distance und Priority: Das Wichtigste auf einen Blick
Priority ist statisch
Feste, konfigurierte Reihenfolge ohne Bezug zur Lieferadresse oder Bestandssituation.
Distance rechnet live
Haversine-Luftlinie zwischen Kundenadresse und geocodeten Source-Koordinaten je Bestellung.
Geocoding ist Voraussetzung
Ohne gültige Koordinaten wird eine Source von Distance still von der Auswahl ausgeschlossen.
Kombination möglich
Distance als Vorauswahl, eigene Kriterien wie Auslastung als Tiebreaker innerhalb der Vorauswahl.