- Neue Funktion idsconnect_notify() für GlobalNotify-Benachrichtigungen mit Fallback auf dol_syslog falls Modul nicht installiert - Neue Funktion idsconnect_validateSupplierConfig() prüft Supplier- Konfiguration vor dem Launch auf Vollständigkeit - launch.php: Validierung vor Formular-Submit - Fehler (leeres Passwort): blockiert Launch, Redirect zur Konfiguration - Warnung (leerer Username): erlaubt Launch aber warnt User + Admin - Löst Problem: Klux "Weiter"-Button fehlte weil ids_username leer war, Login schlug still fehl ohne jede Fehlermeldung Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
16 KiB
Executable file
16 KiB
Executable file
IDS Connect Modul - Changelog
Projektinfo
- Modul: IDS Connect für Dolibarr ERP
- Modul-ID: 500025
- Zweck: Punchout-Schnittstelle zu Elektrogroßhändlern (Sonepar, Kluxen)
- Protokoll: IDS Connect 2.0/2.5 (Browser-basiertes Punchout)
- Entwickler: Eduard Wisch / Claude AI
v3.4 - Klux-Support & Konfigurationsvalidierung (17.03.2026)
🐛 BUGFIX: Klux "Weiter"-Button fehlte
- Problem: Beim WKS (Warenkorb senden) an Klux fehlte im Klux-Shop der "Weiter"-Button zur Bestellbestätigung.
- Ursache:
ids_username(→name_kunde) war leer in der Klux-Supplier-Konfiguration. Ohne gültigen Login-Namen zeigt der Klux-Shop den Katalog, aber keinen IDS-Checkout-Button. - Fix:
ids_username = ids-1222925(Kundennummer) in der Produktiv-DB gesetzt. - Hintergrund: Bei deutschen Elektrogroßhändlern (Klux, Sonepar) wird die Kundennummer oft auch als Login-Username verwendet. Das
name_kunde-Feld darf nicht leer sein.
✨ Feature: Konfigurationsvalidierung vor IDS-Launch
Neue Validierung in launch.php bevor das Formular an den Großhändler-Shop gesendet wird:
- Fehler (blockiert Launch): Kein Passwort konfiguriert → Redirect zur Supplier-Konfiguration
- Warnung (erlaubt aber warnt): Kein Benutzername konfiguriert →
name_kundewäre leer → "Weiter"-Button fehlt im Shop - Verhindert das stille Fehlschlagen ("Shop lädt, aber kein Bestell-Button, niemand weiß warum")
✨ Feature: GlobalNotify-Integration
- Neue Funktion
idsconnect_notify()in lib/idsconnect.lib.php- Sendet Benachrichtigungen an Admins über GlobalNotify (falls Modul aktiv)
- Fallback auf
dol_syslog()wenn GlobalNotify nicht installiert - Typen:
error,warning,info,action
- Neue Funktion
idsconnect_validateSupplierConfig()in lib/idsconnect.lib.php- Prüft Supplier-Konfiguration vor dem Launch auf Vollständigkeit
- Gibt strukturierte
errorsundwarningszurück
- Bei unvollständiger Konfiguration: Admin erhält GlobalNotify-Meldung mit direktem Link zur Supplier-Konfigurationsseite
🔧 Technische Details
- Validierte Felder:
ids_password(Error),ids_username(Warning) - GlobalNotify-Typ:
actionfür Fehler (Link zur Konfiguration),warningfür Warnungen - Keine Code-Änderungen an der Formular-Generierung (
idsconnect.class.php) - nur Vorbedingung inlaunch.php
v2.9 - Preis-Vergleich & Kritische Bugfixes (12.03.2026)
🐛 KRITISCHER BUGFIX: SQL-Spaltenname korrigiert
- Problem:
matchProducts()hat SQL-Fehler produziert wegen falscher Spaltepfp.qty(existiert nicht!) - Fix: Alle
pfp.qty→pfp.quantityersetzt in:- class/idsconnect.class.php:578 - matchProducts() SELECT Query
- class/idsconnect.class.php:589 - $obj->qty → $obj->quantity
- tab_supplierorder.php:154,177 - Preis-Vergleich Queries
- Auswirkung: Vorher wurden ALLE Artikel als Freitext importiert (kein Produkt-Matching!)
- Test: Artikel 0486597 wird jetzt korrekt als COK-WAG-2273-202-2F erkannt ✅
🐛 BUGFIX: Produkt-Matching erweitert
- Fix:
p.status = 1→p.tosell = 1in matchProducts() und tab_supplierorder.php - Grund: Dolibarr verwendet
tosellfür verkaufbare Produkte, nichtstatus
✨ Preis-Vergleich in Warenkorb-Import (cart_review.php)
- Basis-Price-Vergleich: Shop-Preis (z.B. 12,88€/100 Stk) vs. DB-Preis (12,88€/100 Stk)
- Vorteil: Keine Rundungsfehler mehr durch Stückpreis-Umrechnung
- Berechnung:
shop_basis_price = raw_netprice(vom Shop empfangen)db_basis_price = debug_price(aus DB geladen)- Deviation = ((shop - db) / db) × 100
- DEBUG-Ausgabe für Admins: Zeigt Shop-Preis, DB-Preis, Einzelpreis zur Kontrolle
- Farbcodierung:
- Grün: ≤2% Abweichung
- Gelb: 2-10% Abweichung
- Rot: >10% Abweichung
✨ Preis-Vergleich in Lieferantenbestellungen (tab_supplierorder.php)
- Admin-Option:
IDSCONNECT_PRICE_UPDATE_ENABLED(Standard: AUS) - Schwellwert:
IDSCONNECT_PRICE_UPDATE_THRESHOLD(Standard: 5%) - Anzeige: Tabelle mit allen Positionen, die vom Schwellwert abweichen
- Freitext-Warnung: Zeigt an, wenn Artikel nicht mit Dolibarr-Produkten verknüpft sind
- Keine Auto-Updates: Nur Anzeige, keine automatische Preis-Aktualisierung
🔧 Technische Details
- matchProducts(): Lädt jetzt
pfp.quantity,pfp.pricekorrekt - Stückpreis-Berechnung:
unit_price = price / quantity(mit Fallback qty=1) - Debug-Felder:
debug_priceunddebug_qtyfür Basis-Price-Vergleich - Sprachdateien: Neue Keys für Preis-Verwaltung (de_DE)
v2.2 - Menü-Integration, ADL-Hooks & Admin-Erweiterung (19.02.2026)
Menü unter Einkauf/Lieferantenbestellungen
- Kein eigenes Top-Menü mehr: IDS Connect ist jetzt unter Einkauf > Lieferantenbestellungen > IDS Connect eingegliedert
- Untermenüs (Großhändler, Transaktionslog) als Level 2/3 unter dem IDS Connect Eintrag
- Bessere Integration in den normalen Dolibarr-Workflow
ADL-Buttons auf Produkt-Lieferantenpreisen (Hook)
- Neue Datei:
class/actions_idsconnect.class.php- Hook-Klasse fürpricesuppliercard - Zeigt ADL-Button (externer Link) direkt in der Lieferantenpreis-Tabelle auf Produktkarten
- Button nur sichtbar wenn Lieferant mit IDS Connect Großhändler verknüpft UND Lieferanten-Artikelnummer vorhanden
- Spalte erscheint nur wenn mindestens ein aktiver IDS-Supplier existiert
- Gecachte DB-Abfragen für Performance (static-Cache pro Request)
Admin Setup-Seite erweitert
- Großhändler-Schnellübersicht: Tabelle mit allen konfigurierten Großhändlern direkt auf der Einstellungsseite
- Zeigt Name, URL, IDS-Version, Status (Aktiv/Inaktiv, Testmodus) pro Großhändler
- Version prüfen: Button pro Großhändler für SV-Action (Schnittstellenversion)
Dashboard
- Shop öffnen: Neuer LI-Button (Login-Info) neben dem WKE-Button auf der Übersichtsseite
Sprachdateien
IdsconnectShowInShop- Tooltip für ADL-Button in PreistabelleIdsconnectCheckVersion- Button für Schnittstellenversion prüfen
v2.1 - WKS-Flow & URL-Handling (18.02.2026)
WKS (Warenkorb senden) - Live getestet mit Sonepar
- WKS End-to-End: Lieferantenbestellung in Dolibarr anlegen → IDS Connect Tab → "Warenkorb senden" → Artikel im Sonepar-Shop vorausgefüllt → "Nur bestellen"
- buildCartXml(): Von altem
<Artikel>-Format auf IDS Connect 2.0 umgestellt- Namespace
xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/" <OrderItem>statt<Artikel>,<ArtNo>,<Kurztext>,<NetPrice>PriceBasis=1(Dolibarr-Preise sind bereits Stückpreise)VATaus MwSt-Satz der Bestellposition
- Namespace
- launch.php: MwSt-Satz (
tva_tx) und EinheitPCEin Warenkorb-Positionen - Bestellstatus: Setzt Lieferantenbestellung auf "Bestellt" nach WKS-Versand
URL-Handling (Cross-Domain-Fix)
- Problem:
$dolibarr_main_url_rootwar192.168.155.1:8090(intern, ohne Protokoll), User greift überawl.data-it-solution.dezu → Callback-Links waren kaputt - user_base_url-Tracking: Speichert beim Launch die Domain des Users (
HTTP_HOST) in den Log-Request-Daten, callback.php liest diese für Links zurück - Protokoll-Prefix: Automatische
http://-Ergänzung wenn://fehlt - URL-Priorität für Callback-Links:
user_base_urlaus Log (Domain des Users beim Launch)IDSCONNECT_PUBLIC_URLaus Einstellungen$dolibarr_main_url_rootals Fallback
Sonepar-Shop Buttons (Erkenntnisse)
- "Warenkorb übergeben" = WKE-Callback zurück an Dolibarr (für Shop-Einkauf)
- "Nur bestellen" = Bestellung direkt bei Sonepar auslösen (für WKS-Flow)
- "Bestellen" = beides (übergeben + bestellen)
- Bei WKS "Nur bestellen" verwenden, da Bestellung in Dolibarr bereits existiert
v2.0 - Sonepar Live-Integration (18.02.2026)
Kernproblem
Die erste Version konnte den Warenkorb von Sonepar nicht empfangen. Mehrere Probleme:
enctype="multipart/form-data"fehlte im Launch-Formular- XML-Parser erkannte das IDS Connect Format nicht
- Redirect nach Callback führte zum Login (Session-Problem)
- Preiseinheit (PriceBasis) wurde nicht berücksichtigt
Sonepar XML-Format (Erkenntnisse)
Sonepar sendet IDS XML im POST-Feld warenkorb mit folgender Struktur:
<Warenkorb xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/">
<WarenkorbInfo>
<Date>2026-02-18+01:00</Date>
<Time>05:47:07+01:00</Time>
<RueckgabeKZ>Warenkorbrückgabe</RueckgabeKZ>
<Version>2.0</Version>
</WarenkorbInfo>
<Order>
<OrderInfo>
<ModeOfShipment>Lieferung</ModeOfShipment>
<Cur>EUR</Cur>
</OrderInfo>
<DeliveryPlaceInfo>
<Address>
<Name1>...</Name1><Name2>...</Name2>
<Street>...</Street><PCode>...</PCode>
<City>...</City><Country>DE</Country>
</Address>
</DeliveryPlaceInfo>
<OrderItem>
<ArtNo>0351817</ArtNo>
<Qty>100</Qty>
<QU>PCE</QU>
<Kurztext>Klauke Stossverbinder f.Massivleiter SV1525</Kurztext>
<OfferPrice>26.8</OfferPrice>
<NetPrice>16.88</NetPrice>
<PriceBasis>100</PriceBasis> <!-- Preis gilt für 100 Stück! -->
<VAT>19</VAT>
<TechnClarification>No</TechnClarification>
</OrderItem>
</Order>
</Warenkorb>
Wichtig: Namespace xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/" verhindert
direkten SimpleXML-Zugriff → Namespace-Stripping nötig.
Änderungen
callback.php - Komplett-Rewrite auf v2.0
- Versionskennung:
IDSCONNECT_CALLBACK_VERSION = '2.0'zur Identifikation - Kein Redirect mehr: Zeigt Ergebnis direkt als HTML-Seite (NOLOGIN)
- Vorher:
header('Location: idsconnectindex.php?error=...')→ Login-Problem - Nachher:
idsconnectCallbackPage()rendert eigenständige HTML-Seite
- Vorher:
- 7 Datenquellen: Durchsucht POST[warenkorb], POST[cart], FILES[warenkorb], FILES[cart], erste hochgeladene Datei, alle POST-Felder nach XML, php://input
- OCI-Format: Erkennt
NEW_ITEM-*POST-Felder (SAP OCI Punchout) - Debug-Daten: Speichert immer alle empfangenen Daten in DB (response_data JSON)
- Roh-XML: Speichert XML sofort in DB, auch bei Parse-Fehler
- Interne Links: Verwendet
$dolibarr_main_url_rootstattDOL_URL_ROOTfür korrekte Navigation nach Callback auf öffentlicher Domain
class/idsconnect.class.php - Parser erweitert
- Format 5: IDS Connect 2.5
Warenkorb/Order/OrderItemhinzugefügt - Format 6: Namespace-Stripping - entfernt
xmlnsund Prefixe, versucht alle Format-Checks erneut auf bereinigtem XML - PriceBasis: Neues Feld
PriceBasis/PE/Preiseinheitwird geparst- Einzelpreis = NetPrice / PriceBasis (z.B. 16,88 / 100 = 0,1688€/Stk)
- Angebotspreis wird analog umgerechnet
preiseinheitundraw_netpricewerden im Item-Array mitgegeben
- VAT/MwSt: MwSt-Satz wird aus
VAT/MwStgeparst und alsmwst_satzgespeichert - Erweiterte Feldnamen: ArtNo, Kurztext, Langtext, NetPrice, OfferPrice, ManufacturerID, Hinweis in den Mapping-Arrays ergänzt
- Debug-Logging: Root-Element und Kinder werden via dol_syslog geloggt
- Bessere Fehlermeldung: Zeigt Root-Element und Kinder bei "Keine Artikel gefunden"
launch.php - Formular-Fix
- enctype:
enctype="multipart/form-data"zum Launch-Formular hinzugefügt (fehlte, dadurch kamen keine Callback-Daten an)
cart_review.php - Preisanzeige verbessert
- PE-Info: Zeigt unter dem Stückpreis die Preiseinheit-Info: "16,88 / 100 Stk" wenn PriceBasis > 1
- MwSt: Verwendet
mwst_satzaus XML bei Bestellerstellung (statt 0%)
mockserver.php - Realitätsnäher
- IDS Connect 2.5 Format: Generiert
Warenkorb/Order/OrderItemstatt altes<Artikel>Format - Namespace: Verwendet
xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/"wie Sonepar - Neue Felder: PriceBasis, VAT im generierten XML
admin/setup.php - Erweiterte Konfiguration
- Öffentliche URL: Feld für IDSCONNECT_PUBLIC_URL (Reverse-Proxy)
- Callback-URL: Berechnete Anzeige (read-only, klickbar zum Kopieren)
- Mock-Server URL: Berechnete Anzeige (immer intern)
- WKS-Warnschwellen: Mengen- und Wertgrenzen konfigurierbar
- WKS-PIN: Verschlüsselte PIN für Warenkorb-Senden
v1.0 - Initiale Entwicklung (17.02.2026)
Grundgerüst
- Modul-Struktur nach Dolibarr-Standard (modIdsconnect.class.php)
- Berechtigungssystem: read, use, config, delete
- Mehrsprachig: de_DE, en_US
- SQL-Tabellen:
idsconnect_supplier,idsconnect_log
Dateien erstellt
| Datei | Zweck |
|---|---|
class/idsconnect.class.php |
Kern-Klasse: Formular-Builder, XML-Parser, XML-Generator |
class/idssupplier.class.php |
Großhändler-Konfiguration (URL, Login, Passwort) |
class/idslog.class.php |
Transaktionslog (CRUD, Status-Updates) |
callback.php |
HOOKURL-Empfänger, NOLOGIN-Seite |
launch.php |
Formular-Generator für Shop-Weiterleitung |
mockserver.php |
Test-Shop für lokale Entwicklung (NOLOGIN, nur Testmodus) |
idsconnectindex.php |
Hauptseite mit Großhändler-Liste und Log |
cart_review.php |
Empfangenen Warenkorb prüfen, Bestellung erstellen |
supplier_card.php |
Großhändler-Konfigurationsseite |
supplier_list.php |
Großhändler-Liste |
log_list.php |
Log-Übersicht mit Filter |
log_detail.php |
Log-Detailansicht (XML, Response, Fehler) |
tab_supplierorder.php |
Tab auf Lieferantenbestellungen |
test_connection.php |
AJAX-Verbindungstest |
admin/setup.php |
Modul-Einstellungen |
admin/about.php |
Über-Seite |
lib/idsconnect.lib.php |
Hilfsfunktionen, Tab-Builder |
build/buildzip.php |
Modul-ZIP erstellen |
IDS Connect Actions
| Kürzel | Bedeutung | Richtung | Status |
|---|---|---|---|
| WKE | Warenkorb empfangen | IN | Funktioniert (Sonepar getestet) |
| WKS | Warenkorb senden | OUT | Funktioniert (Sonepar getestet) |
| ADL | Artikel Deep-Link | OUT | Implementiert |
| LI | Login-Info | OUT | Implementiert |
| SV | Schnittstellenversion | OUT | Implementiert |
Sicherheit
- CSRF-Tokens auf allen Formularen
- Callback-Tokens: HMAC-SHA256, 2h gültig, einmalig verwendbar
- XXE-Schutz:
LIBXML_NONET | LIBXML_NOENT - Passwörter verschlüsselt via
dolEncrypt/dolDecrypt - Testmodus als Standard (IDSCONNECT_TESTMODE=1)
- Live-Modus erfordert Bestätigung
Sonepar-Schnittstellen
Sonepar unterstützt 3 Schnittstellen:
- IDS - XML-basiertes Punchout (das was wir implementiert haben)
- OCI - SAP Open Catalog Interface, POST-Felder
NEW_ITEM-*(ebenfalls implementiert) - UGL - ÜberGabeSchnittstelleLang, FTP-basierter Dokumentenaustausch (Angebote, Bestellungen, Lieferscheine, Rechnungen) - nicht implementiert
Architektur
WKE-Flow (Warenkorb empfangen)
1. User klickt "Zum Shop" in Dolibarr
2. launch.php generiert HTML-Formular mit:
- Shop-URL als action
- USERID, PASSWORT, AESSION (WKE)
- HOOKURL (callback.php?token=...)
3. Browser submitted Formular an Großhändler-Shop
4. User wählt Artikel im Shop
5. Shop sendet Warenkorb per POST an HOOKURL
6. callback.php empfängt, parst, speichert
7. Callback-Seite zeigt Ergebnis + Link zu cart_review.php
8. cart_review.php: Artikel prüfen → Lieferantenbestellung erstellen
Preisberechnung mit PriceBasis
Im Elektrogroßhandel werden Preise oft pro Preiseinheit (PE) angegeben:
PriceBasis=100 → NetPrice gilt für 100 Stück
Einzelpreis pro Stück = NetPrice / PriceBasis
Gesamtpreis = Qty * (NetPrice / PriceBasis)
Beispiel: 100 Stk Stoßverbinder
NetPrice=16.88, PriceBasis=100
→ Stückpreis = 16.88 / 100 = 0.1688€
→ Gesamt = 100 * 0.1688 = 16.88€
Datenbank-Tabellen
llx_idsconnect_supplier- Großhändler mit URL, Login, Passwort (verschlüsselt)llx_idsconnect_log- Transaktionslog mit Status, XML, Response-JSON, Token
Konfiguration
Dolibarr-Einstellungen (Schlüssel)
| Schlüssel | Beschreibung | Standard |
|---|---|---|
| IDSCONNECT_TESTMODE | Testmodus aktiv | 1 |
| IDSCONNECT_PUBLIC_URL | Öffentliche URL für Callback | (leer) |
| IDSCONNECT_LOG_ENABLED | Logging aktiviert | 1 |
| IDSCONNECT_WKS_WARN_QTY | WKS Warn-Menge | 0 |
| IDSCONNECT_WKS_WARN_VALUE | WKS Warn-Wert | 0 |
| IDSCONNECT_WKS_PIN | PIN für WKS (verschlüsselt) | (leer) |
Sonepar-Konfiguration
- URL:
https://www.sonepar.de/punchout/v1/ids/setup?OrganizationId=12 - Benutzer: ids
- Kundennummer: 100184
- IDS-Version: 2.0