# Riccardo Filialbestand

Zeigt auf der Artikelseite, in welchen Filialen ein Artikel vorrätig ist.

## Datenquelle

**Die Offline-Wawi, nicht die Online-Wawi.**

| | |
|---|---|
| Offline-Wawi | `https://10.0.0.7:5884/api/eazybusiness` – 28 Lager, alle aktiv, echte Filialbestände (23.09.2026: 56.481 Bestandszeilen) |
| Online-Wawi | `10.0.0.4:5884` – die Lager dort heißen „RL-…" und sind Überbleibsel der Systemtrennung. **Keine Filialbestände.** |

Wer hier die falsche Adresse einträgt, bekommt eine Antwort ohne Fehlermeldung
und lauter leere Filialen.

## Eigenheiten der JTL-Wawi-API

Drei Dinge, die man nicht erwartet und die in keiner der Beispielimplementierungen stehen:

* Anmeldung heißt `Authorization: Wawi {Token}` – **nicht** Bearer.
* `x-challengecode` muss bei **jeder** Anfrage mit, nicht nur beim Anmelden.
* `X-AppId` ist Pflicht, sonst antwortet der Dienst mit `400 AppIdHeaderMissing`.

Zwei Abrufe je Artikel, weil die API keinen Bestand über die Artikelnummer kennt:

```
GET /v1/items?searchKeyWord={SKU}   -> Id des Artikels
GET /v1/stocks?itemId={Id}          -> eine Zeile je Lager und Lagerplatz
```

Die Artikelnummern des Shops stimmen exakt mit den Wawi-SKUs überein,
inklusive Variantensuffix. **Bestände hängen an der Variante** – der
Vaterartikel (`10000067`) hat keine, die Variante (`10000067-2770`) schon.

## Zertifikat

Der Wawi-Dienst läuft mit einem selbstsignierten Zertifikat
(`CN=JTL.Wawi.Rest.Server`). Die Prüfung wird **nicht** abgeschaltet, sondern
verschärft:

* `caFile` – das Zertifikat selbst als vertrauenswürdige Wurzel
* `certPin` – zusätzlich der öffentliche Schlüssel festgenagelt (pin-sha256)

```bash
mkdir -p /etc/ssl/riccardo
openssl s_client -connect 10.0.0.7:5884 </dev/null 2>/dev/null \
  | openssl x509 > /etc/ssl/riccardo/wawi-offline.pem

openssl x509 -in /etc/ssl/riccardo/wawi-offline.pem -pubkey -noout \
  | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
```

Die Datei muss auf **jedem** Frontend liegen. Ohne Pin und ohne Zertifikatsdatei
schlägt die Verbindung fehl – das ist Absicht: lieber eine klare Fehlermeldung
als stillschweigend jedem Zertifikat vertrauen.

Symfony unterstützt ausschließlich `pin-sha256` (Base64 über den
SubjectPublicKeyInfo), **nicht** den Zertifikats-Fingerabdruck. Der Pin hat
nebenbei den Vorteil, eine Zertifikatserneuerung zu überleben, solange der
Schlüssel derselbe bleibt.

## Anmeldung einrichten

`dev/daten/jtl-offline-registrieren.php` im Shopware-Projekt. Ablauf:

1. In der JTL-Wawi **Admin → App-Registrierung** öffnen und offen lassen.
   Ohne geöffneten Dialog antwortet der Dienst mit `403 NoActiveRegistration`.
2. `php dev/daten/jtl-offline-registrieren.php anmelden`
3. In der Wawi freigeben, Bestätigungscode vergleichen.
4. `php dev/daten/jtl-offline-registrieren.php status` – liefert den Schlüssel,
   genau einmal.

Angefordert werden nur Leserechte: `items.read`, `inventories.read`, `warehouse.read`.

## Zuordnung Filiale → Lager

In der Plugin-Konfiguration, eine Zeile je Filiale: `slug=Lagernummer`.
Stand 23.09.2026 sind alle 25 Filialen zugeordnet; die Zuordnung wurde über die
Filialadressen geprüft, nicht über Namensähnlichkeit. Zwei Fälle, die man
falsch machen kann:

* **Sulzbach = „Frankfurt MTZ" (7)** – das Main-Taunus-Zentrum liegt in Sulzbach.
* **Frankfurt am Main = „Frankfurt NWZ" (8)** – Tituscorso, Nordwestzentrum.

Ohne Zuordnung meldet die Filiale „unbekannt", nicht „nicht vorrätig" – eine
fehlende Angabe ist keine Aussage über den Bestand.

## Was angezeigt wird

`QuantityTotal` abzüglich der für Versand und Verfügbarkeit gesperrten Mengen.
Wer in die Filiale fährt, soll das Stück auch bekommen.

Prüfen:

```bash
bin/console riccardo:store-stock:check 10000067-2770
```
