diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/CHANGELOG.md b/CHANGELOG.md
old mode 100644
new mode 100755
index 2c54d2d..0b5fc82
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,34 @@
---
+## 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ür `pricesuppliercard`
+- 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 Preistabelle
+- `IdsconnectCheckVersion` - Button für Schnittstellenversion prüfen
+
+---
+
## v2.1 - WKS-Flow & URL-Handling (18.02.2026)
### WKS (Warenkorb senden) - Live getestet mit Sonepar
diff --git a/README.md b/README.md
index 5cf8468..d6b9e44 100755
--- a/README.md
+++ b/README.md
@@ -24,11 +24,10 @@ Ermöglicht den direkten Wareneinkauf aus Dolibarr heraus über den Shop des Gro
- **OCI-Format**: SAP Open Catalog Interface (`NEW_ITEM-*` POST-Felder) wird ebenfalls erkannt
- **Transaktionslog**: Alle IDS-Aktionen werden protokolliert mit XML, Status, Fehlermeldungen
-### Implementiert, nicht getestet
-
-- **ADL (Artikel Deep-Link)**: Direkt zu einem Artikel im Shop springen
-- **LI (Login-Info)**: Login-Informationen abfragen
-- **SV (Schnittstellenversion)**: IDS Connect Version des Shops abfragen
+### Implementiert
+- **ADL (Artikel Deep-Link)**: Direkt zu einem Artikel im Shop springen - per Hook als Button in der Lieferantenpreis-Tabelle auf Produktkarten
+- **LI (Login-Info)**: Shop direkt öffnen (Button auf Dashboard)
+- **SV (Schnittstellenversion)**: IDS Connect Version des Shops abfragen (Button auf Admin-Seite)
## Was noch fehlt
@@ -123,6 +122,7 @@ Dolibarr → Lieferantenbestellung anlegen
| `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) |
+| `class/actions_idsconnect.class.php` | Hook: ADL-Buttons auf Produkt-Lieferantenpreisen |
| `callback.php` | HOOKURL-Empfänger (NOLOGIN) |
| `launch.php` | Formular-Generator für Shop-Weiterleitung |
| `mockserver.php` | Test-Shop (NOLOGIN, nur Testmodus) |
diff --git a/admin/setup.php b/admin/setup.php
index 92d90f1..4403a8a 100755
--- a/admin/setup.php
+++ b/admin/setup.php
@@ -229,6 +229,57 @@ print $langs->trans("IdsconnectSecurityInfoText");
print '';
+// ============================================================
+// Großhändler-Schnellübersicht mit Versionscheck
+// ============================================================
+dol_include_once('/idsconnect/class/idssupplier.class.php');
+$supplierObj = new IdsSupplier($db);
+$allSuppliers = $supplierObj->fetchAll(0);
+
+if (is_array($allSuppliers) && count($allSuppliers) > 0) {
+ print '
';
+ print '
';
+ print '';
+ print '| '.$langs->trans("IdsconnectSuppliers").' | ';
+ print ''.$langs->trans("IdsconnectSupplierUrl").' | ';
+ print ''.$langs->trans("IdsconnectSupplierVersion").' | ';
+ print ''.$langs->trans("Status").' | ';
+ print ''.$langs->trans("Action").' | ';
+ print '
';
+
+ foreach ($allSuppliers as $sup) {
+ print '';
+ print '| ';
+ print '';
+ print ''.htmlspecialchars($sup->label).'';
+ print '';
+ print ' ('.htmlspecialchars($sup->ref).')';
+ print ' | ';
+ print ''.htmlspecialchars($sup->ids_url).' | ';
+ print ''.htmlspecialchars($sup->ids_version).' | ';
+ print '';
+ if ($sup->active) {
+ print ''.$langs->trans("Enabled").'';
+ } else {
+ print ''.$langs->trans("Disabled").'';
+ }
+ if ($sup->testmode) {
+ print ' Test';
+ }
+ print ' | ';
+ print '';
+ if ($sup->active) {
+ print '';
+ print $langs->trans("IdsconnectCheckVersion");
+ print '';
+ }
+ print ' | ';
+ print '
';
+ }
+ print '
';
+}
+
+
print dol_get_fiche_end();
llxFooter();
diff --git a/callback.php b/callback.php
old mode 100644
new mode 100755
diff --git a/cart_review.php b/cart_review.php
old mode 100644
new mode 100755
diff --git a/class/actions_idsconnect.class.php b/class/actions_idsconnect.class.php
new file mode 100755
index 0000000..7485fc2
--- /dev/null
+++ b/class/actions_idsconnect.class.php
@@ -0,0 +1,195 @@
+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+/**
+ * \file class/actions_idsconnect.class.php
+ * \ingroup idsconnect
+ * \brief Hook-Klasse für IDS Connect (ADL-Buttons auf Produkt-Lieferantenpreisen)
+ */
+
+require_once DOL_DOCUMENT_ROOT.'/core/class/commonhookactions.class.php';
+
+/**
+ * Hook-Aktionen für IDS Connect
+ */
+class ActionsIdsconnect extends CommonHookActions
+{
+ /** @var DoliDB */
+ public $db;
+
+ /** @var string */
+ public $error = '';
+
+ /** @var array */
+ public $errors = array();
+
+ /** @var array */
+ public $results = array();
+
+ /** @var string HTML-Output für Hooks */
+ public $resprints;
+
+ /**
+ * Constructor
+ *
+ * @param DoliDB $db Database handler
+ */
+ public function __construct($db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * Spaltenüberschrift in der Lieferantenpreis-Tabelle
+ *
+ * @param array $parameters Hook-Parameter
+ * @param object $object Produkt-Objekt
+ * @param string $action Aktuelle Aktion
+ * @param HookManager $hookmanager Hook-Manager
+ * @return int 0=weiter
+ */
+ public function printFieldListTitle($parameters, &$object, &$action, $hookmanager)
+ {
+ if (strpos($parameters['currentcontext'], 'pricesuppliercard') === false) {
+ return 0;
+ }
+
+ // Spalte nur anzeigen wenn mindestens ein aktiver IDS-Supplier existiert
+ if (!$this->hasActiveIdsSuppliers()) {
+ return 0;
+ }
+
+ global $langs;
+ $langs->load("idsconnect@idsconnect");
+
+ print ''.img_picto($langs->trans("ModuleIdsconnectName"), 'fa-plug').' | ';
+ return 0;
+ }
+
+ /**
+ * ADL-Button pro Zeile in der Lieferantenpreis-Tabelle
+ *
+ * @param array $parameters Hook-Parameter (id_pfp, id_fourn, prod_id)
+ * @param object $object Produkt-Objekt
+ * @param string $action Aktuelle Aktion
+ * @param HookManager $hookmanager Hook-Manager
+ * @return int 0=weiter
+ */
+ public function printFieldListValue($parameters, &$object, &$action, $hookmanager)
+ {
+ if (strpos($parameters['currentcontext'], 'pricesuppliercard') === false) {
+ return 0;
+ }
+
+ // Keine Spalte wenn keine IDS-Supplier existieren
+ if (!$this->hasActiveIdsSuppliers()) {
+ return 0;
+ }
+
+ global $user, $langs;
+ $langs->load("idsconnect@idsconnect");
+
+ $html = '';
+
+ if ($user->hasRight('idsconnect', 'use')) {
+ $id_pfp = $parameters['id_pfp'];
+ $pfpMap = $this->getPfpMap($parameters['prod_id']);
+ $idsMap = $this->getIdsSupplierMap();
+
+ if (isset($pfpMap[$id_pfp])) {
+ $fk_soc = $pfpMap[$id_pfp]['fk_soc'];
+ $ref_fourn = $pfpMap[$id_pfp]['ref_fourn'];
+
+ if (isset($idsMap[$fk_soc]) && !empty($ref_fourn)) {
+ $supplier_id = $idsMap[$fk_soc];
+ $url = DOL_URL_ROOT.'/custom/idsconnect/launch.php';
+ $url .= '?supplier_id='.((int) $supplier_id);
+ $url .= '&ids_action=ADL';
+ $url .= '&artikelnr='.urlencode($ref_fourn);
+ $url .= '&token='.newToken();
+
+ $html .= 'trans("IdsconnectShowInShop")).'">';
+ $html .= img_picto($langs->trans("IdsconnectShowInShop"), 'fa-external-link-alt', 'style="color: #0077b6;"');
+ $html .= '';
+ }
+ }
+ }
+
+ $html .= ' | ';
+ print $html;
+ return 0;
+ }
+
+ /**
+ * IDS-Supplier-Map laden (fk_soc => supplier_id), gecacht
+ *
+ * @return array
+ */
+ private function getIdsSupplierMap()
+ {
+ static $map = null;
+ if ($map !== null) {
+ return $map;
+ }
+
+ $map = array();
+ $sql = "SELECT rowid, fk_soc FROM ".$this->db->prefix()."idsconnect_supplier";
+ $sql .= " WHERE active = 1 AND fk_soc IS NOT NULL AND fk_soc > 0";
+ $sql .= " AND entity IN (".getEntity('idsconnect').")";
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ while ($obj = $this->db->fetch_object($resql)) {
+ $map[$obj->fk_soc] = $obj->rowid;
+ }
+ $this->db->free($resql);
+ }
+ return $map;
+ }
+
+ /**
+ * Product-Fournisseur-Price-Map laden (pfp_id => {fk_soc, ref_fourn}), gecacht pro Produkt
+ *
+ * @param int $prod_id Produkt-ID
+ * @return array
+ */
+ private function getPfpMap($prod_id)
+ {
+ static $cache = array();
+ $prod_id = (int) $prod_id;
+ if (isset($cache[$prod_id])) {
+ return $cache[$prod_id];
+ }
+
+ $cache[$prod_id] = array();
+ $sql = "SELECT rowid, fk_soc, ref_fourn FROM ".$this->db->prefix()."product_fournisseur_price";
+ $sql .= " WHERE fk_product = ".$prod_id;
+ $resql = $this->db->query($sql);
+ if ($resql) {
+ while ($obj = $this->db->fetch_object($resql)) {
+ $cache[$prod_id][$obj->rowid] = array(
+ 'fk_soc' => $obj->fk_soc,
+ 'ref_fourn' => $obj->ref_fourn,
+ );
+ }
+ $this->db->free($resql);
+ }
+ return $cache[$prod_id];
+ }
+
+ /**
+ * Prüft ob mindestens ein aktiver IDS-Supplier existiert (gecacht)
+ *
+ * @return bool
+ */
+ private function hasActiveIdsSuppliers()
+ {
+ return count($this->getIdsSupplierMap()) > 0;
+ }
+}
diff --git a/class/idsconnect.class.php b/class/idsconnect.class.php
old mode 100644
new mode 100755
diff --git a/class/idslog.class.php b/class/idslog.class.php
old mode 100644
new mode 100755
diff --git a/class/idssupplier.class.php b/class/idssupplier.class.php
old mode 100644
new mode 100755
diff --git a/core/modules/modIdsconnect.class.php b/core/modules/modIdsconnect.class.php
index 2d5949a..20f8f28 100755
--- a/core/modules/modIdsconnect.class.php
+++ b/core/modules/modIdsconnect.class.php
@@ -82,6 +82,7 @@ class modIdsconnect extends DolibarrModules
'hooks' => array(
'data' => array(
'ordersuppliercard',
+ 'pricesuppliercard',
),
'entity' => '0',
),
@@ -164,89 +165,72 @@ class modIdsconnect extends DolibarrModules
$r++;
// ============================================================
- // Menüs
+ // Menüs - Unter Einkauf/Vertrieb > Lieferantenbestellungen
// ============================================================
$this->menu = array();
$r = 0;
- // Top-Menü
+ // IDS Connect Haupteintrag unter Lieferantenbestellungen (Level 1)
$this->menu[$r++] = array(
- 'fk_menu' => '',
- 'type' => 'top',
- 'titre' => 'ModuleIdsconnectName',
- 'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle"'),
- 'mainmenu' => 'idsconnect',
- 'leftmenu' => '',
- 'url' => '/idsconnect/idsconnectindex.php',
- 'langs' => 'idsconnect@idsconnect',
- 'position' => 1000 + $r,
- 'enabled' => 'isModEnabled("idsconnect")',
- 'perms' => '$user->hasRight("idsconnect", "read")',
- 'target' => '',
- 'user' => 0,
- );
-
- // Links-Menü: Übersicht
- $this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=idsconnect',
+ 'fk_menu' => 'fk_mainmenu=commercial,fk_leftmenu=orders_suppliers',
'type' => 'left',
- 'titre' => 'IdsconnectOverview',
- 'prefix' => img_picto('', 'fa-home', 'class="pictofixedwidth valignmiddle paddingright"'),
- 'mainmenu' => 'idsconnect',
- 'leftmenu' => 'idsconnect_overview',
+ 'titre' => 'ModuleIdsconnectName',
+ 'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle paddingright"'),
+ 'mainmenu' => 'commercial',
+ 'leftmenu' => 'idsconnect',
'url' => '/idsconnect/idsconnectindex.php',
'langs' => 'idsconnect@idsconnect',
- 'position' => 1000 + $r,
+ 'position' => 500 + $r,
'enabled' => 'isModEnabled("idsconnect")',
'perms' => '$user->hasRight("idsconnect", "read")',
'target' => '',
'user' => 0,
);
- // Links-Menü: Großhändler
+ // Großhändler (Level 2 unter IDS Connect)
$this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=idsconnect',
+ 'fk_menu' => 'fk_mainmenu=commercial,fk_leftmenu=idsconnect',
'type' => 'left',
'titre' => 'IdsconnectSuppliers',
'prefix' => img_picto('', 'fa-building', 'class="pictofixedwidth valignmiddle paddingright"'),
- 'mainmenu' => 'idsconnect',
+ 'mainmenu' => 'commercial',
'leftmenu' => 'idsconnect_suppliers',
'url' => '/idsconnect/supplier_list.php',
'langs' => 'idsconnect@idsconnect',
- 'position' => 1000 + $r,
+ 'position' => 500 + $r,
'enabled' => 'isModEnabled("idsconnect")',
'perms' => '$user->hasRight("idsconnect", "read")',
'target' => '',
'user' => 0,
);
- // Links-Menü: Großhändler anlegen
+ // Großhändler anlegen (Level 3 unter Großhändler)
$this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=idsconnect,fk_leftmenu=idsconnect_suppliers',
+ 'fk_menu' => 'fk_mainmenu=commercial,fk_leftmenu=idsconnect_suppliers',
'type' => 'left',
'titre' => 'IdsconnectNewSupplier',
- 'mainmenu' => 'idsconnect',
+ 'mainmenu' => 'commercial',
'leftmenu' => 'idsconnect_supplier_new',
'url' => '/idsconnect/supplier_card.php?action=create',
'langs' => 'idsconnect@idsconnect',
- 'position' => 1000 + $r,
+ 'position' => 500 + $r,
'enabled' => 'isModEnabled("idsconnect")',
'perms' => '$user->hasRight("idsconnect", "config")',
'target' => '',
'user' => 0,
);
- // Links-Menü: Transaktionslog
+ // Transaktionslog (Level 2 unter IDS Connect)
$this->menu[$r++] = array(
- 'fk_menu' => 'fk_mainmenu=idsconnect',
+ 'fk_menu' => 'fk_mainmenu=commercial,fk_leftmenu=idsconnect',
'type' => 'left',
'titre' => 'IdsconnectLog',
'prefix' => img_picto('', 'fa-list-alt', 'class="pictofixedwidth valignmiddle paddingright"'),
- 'mainmenu' => 'idsconnect',
+ 'mainmenu' => 'commercial',
'leftmenu' => 'idsconnect_log',
'url' => '/idsconnect/log_list.php',
'langs' => 'idsconnect@idsconnect',
- 'position' => 1000 + $r,
+ 'position' => 500 + $r,
'enabled' => 'isModEnabled("idsconnect")',
'perms' => '$user->hasRight("idsconnect", "read")',
'target' => '',
diff --git a/css/idsconnect.css b/css/idsconnect.css
old mode 100644
new mode 100755
diff --git a/idsconnectindex.php b/idsconnectindex.php
index 20b3cf4..c222bbf 100755
--- a/idsconnectindex.php
+++ b/idsconnectindex.php
@@ -119,6 +119,9 @@ if (is_array($suppliers) && count($suppliers) > 0) {
print '';
print $langs->trans("IdsconnectReceiveCart");
print ' ';
+ print '';
+ print $langs->trans("IdsconnectOpenShop");
+ print ' ';
}
print '';
print '';
diff --git a/langs/de_DE/idsconnect.lang b/langs/de_DE/idsconnect.lang
old mode 100644
new mode 100755
index 0435801..a9231fc
--- a/langs/de_DE/idsconnect.lang
+++ b/langs/de_DE/idsconnect.lang
@@ -74,6 +74,8 @@ IdsconnectOpenShop = Shop öffnen
IdsconnectSendCart = Warenkorb senden
IdsconnectReceiveCart = Warenkorb empfangen
IdsconnectDeepLink = Artikel im Shop anzeigen
+IdsconnectShowInShop = Im Shop anzeigen
+IdsconnectCheckVersion = Version prüfen
#
# Launcher / Bestätigung
diff --git a/langs/en_US/idsconnect.lang b/langs/en_US/idsconnect.lang
index 2a9af16..5c02c49 100755
--- a/langs/en_US/idsconnect.lang
+++ b/langs/en_US/idsconnect.lang
@@ -74,6 +74,8 @@ IdsconnectOpenShop = Open Shop
IdsconnectSendCart = Send Cart
IdsconnectReceiveCart = Receive Cart
IdsconnectDeepLink = Show Article in Shop
+IdsconnectShowInShop = Show in Shop
+IdsconnectCheckVersion = Check Version
#
# Launcher / Confirmation
diff --git a/launch.php b/launch.php
old mode 100644
new mode 100755
diff --git a/log_detail.php b/log_detail.php
old mode 100644
new mode 100755
diff --git a/log_list.php b/log_list.php
old mode 100644
new mode 100755
diff --git a/mockserver.php b/mockserver.php
old mode 100644
new mode 100755
diff --git a/sql/llx_idsconnect_log.key.sql b/sql/llx_idsconnect_log.key.sql
old mode 100644
new mode 100755
diff --git a/sql/llx_idsconnect_log.sql b/sql/llx_idsconnect_log.sql
old mode 100644
new mode 100755
diff --git a/sql/llx_idsconnect_supplier.key.sql b/sql/llx_idsconnect_supplier.key.sql
old mode 100644
new mode 100755
diff --git a/sql/llx_idsconnect_supplier.sql b/sql/llx_idsconnect_supplier.sql
old mode 100644
new mode 100755
diff --git a/supplier_card.php b/supplier_card.php
old mode 100644
new mode 100755
diff --git a/supplier_list.php b/supplier_list.php
old mode 100644
new mode 100755
diff --git a/tab_supplierorder.php b/tab_supplierorder.php
old mode 100644
new mode 100755
diff --git a/test_connection.php b/test_connection.php
old mode 100644
new mode 100755