# Websale ↔ JTL-Wawi Sync — JTL-Teil

Artisan-getriebene Anbindung an die JTL-Wawi REST API (kein Web-UI). Verbindung/
Registrierung, Lese-Zugriffe, Stammdaten fürs Mapping und die Auftrags-/Kundenanlage
auf Basis der offiziellen V1-Contracts (developer.jtl-software.com, OpenAPI 2.1).
Die Websale-Seite und die Sync-Loops folgen, sobald die Websale-Doku da ist.

## Dateien

```
config/jtl.php                                  Konfiguration (URL, App-Identität, Scopes, Pflicht-UUIDs, Mapping)
app/Services/JtlApiService.php                  REST-Adapter (Auth-Kern gegen Wawi 1.11.8 bestätigt)
app/Models/Setting.php                          Key-Value-Store (nur falls noch nicht vorhanden)
app/Console/Commands/JtlRegisterCommand.php     App registrieren + Token holen
app/Console/Commands/JtlTestCommand.php         Verbindung testen (ping + /info)
app/Console/Commands/JtlWarehousesCommand.php   Lager auflisten
app/Console/Commands/JtlMetaCommand.php         Firma/Kundengruppe/Zahlungs-/Versandarten (UUIDs)
app/Console/Commands/JtlSalesOrderSampleCommand.php  Echten Auftrag als JSON ziehen (read-only)
database/migrations/..._create_settings_table.php
.env.jtl.example
```

## Einrichtung

1. Dateien ins Laravel-Projekt kopieren (Pfade beibehalten). Commands werden in
   Laravel 11/12 automatisch erkannt.
2. `.env.jtl.example` in die `.env` mergen, `JTL_BASE_URL` setzen.
3. `php artisan migrate`  (Setting-Model + Migration weglassen, falls vorhanden).
4. Registrieren und Token holen:
   ```
   php artisan jtl:register --base-url=https://wawi-host:5883/api/eazybusiness
   ```
   In JTL-Wawi → Admin → App-Registrierung freigeben; der Command pollt und
   speichert den Token sofort. `--resume` setzt fort, `--fresh` startet neu.
5. Verbindung + Stammdaten:
   ```
   php artisan jtl:test
   php artisan jtl:warehouses
   php artisan jtl:meta            # liefert die UUIDs für die Config
   php artisan jtl:salesorder:sample --count=1
   ```
6. Aus `jtl:meta` die UUIDs in `.env` / `config/jtl.php` eintragen:
   `JTL_COMPANY_ID`, `JTL_CUSTOMER_GROUP_ID`, sowie `payment_map`/`shipping_map`.

## Bestätigte API-Eigenheiten (Wawi 1.11.8, OnPrem)

- Auth-Header: `Authorization: Wawi {token}` — nicht Bearer.
- `x-challengecode` bei jedem Request.
- Pfade ohne `/v2`; Version per `api-version`-Header.
- API-Key wird beim Accept genau einmal unter `Token.ApiKey` geliefert.

## Auftrags-/Kundenanlage — Schema-Fakten (aus der offiziellen Doku)

- **SalesOrder**: `companyId` + `customerId` sind PFLICHT (beides UUIDs). Es gibt
  keine Anlage mit reinen Inline-Adressen — der Kunde wird zuerst aufgelöst
  (`findCustomerByEmail`) oder angelegt (`createCustomer`).
- **Customer**: Pflicht `customerGroupId`, `billingAddress`, `languageIso`,
  `internalCompanyId`.
- **Adresse** (`CreateAddress`): Pflicht nur `city` + `countryIso`.
- **LineItems**: `POST /salesOrders/{id}/lineitems` nimmt ein ARRAY. Feld heißt
  `sKU`; nur Brutto **oder** Netto angeben (Rest wird berechnet); `notice` für
  Hinweis; `itemId` leer ⇒ Freiposition.
- **Versand**: über `salesOrderShippingDetail.shippingMethodId` im Kopf — keine
  manuelle Versandposition nötig.
- **Zahlung als bezahlt markieren**: eigener Endpoint in neueren API-Versionen
  ("mark sales order as completely paid") — für den Zahlungsabgleich später.

## Hinweis zur Doku-Quelle

Die offizielle Referenz beschreibt das Cloud-Gateway (`api.jtl-cloud.com/erp`,
Pfad `/v2/`, `x-api-key`/OAuth, `x-tenant-id`). Die Datenmodelle (V1-Contracts)
sind mit OnPrem identisch; abweichend sind nur Auth + Pfad-Präfix. Felder, die
nicht aus dem Lese-Kern stammen, gegen die Swagger-Doku DER INSTANZ prüfen —
`jtl:salesorder:sample` liefert dafür ein reales Beispiel.
