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 ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + foreach ($allSuppliers as $sup) { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + print '
'.$langs->trans("IdsconnectSuppliers").''.$langs->trans("IdsconnectSupplierUrl").''.$langs->trans("IdsconnectSupplierVersion").''.$langs->trans("Status").''.$langs->trans("Action").'
'; + print ''; + print ''.htmlspecialchars($sup->label).''; + print ''; + print ' ('.htmlspecialchars($sup->ref).')'; + print ''.htmlspecialchars($sup->ids_url).''.htmlspecialchars($sup->ids_version).''; + if ($sup->active) { + print ''.$langs->trans("Enabled").''; + } else { + print ''.$langs->trans("Disabled").''; + } + if ($sup->testmode) { + print ' Test'; + } + print ''; + if ($sup->active) { + print ''; + print $langs->trans("IdsconnectCheckVersion"); + 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