diff --git a/class/actions_supplierlink3.class.php b/class/actions_supplierlink3.class.php old mode 100755 new mode 100644 index 7634dc6..b39f01f --- a/class/actions_supplierlink3.class.php +++ b/class/actions_supplierlink3.class.php @@ -36,6 +36,16 @@ class ActionsSupplierLink3 extends CommonHookActions */ public $db; + /** + * @var int Debug mode (0=off, 1=on) + */ + private $debug = 0; + + /** + * @var string Debug log file path + */ + private $debugLogFile = '/tmp/supplierlink3_debug.log'; + /** * @var string Error code (or message) */ @@ -63,6 +73,16 @@ class ActionsSupplierLink3 extends CommonHookActions public $priority; + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + /** + * @var string Shop icon class (FontAwesome) + */ + private $shopIcon = 'fas fa-store'; + /** * Constructor * @@ -71,6 +91,38 @@ class ActionsSupplierLink3 extends CommonHookActions public function __construct($db) { $this->db = $db; + + // Debug-Modus aus Dolibarr-Konfiguration laden (Standard: AUS) + $this->debug = getDolGlobalInt('SUPPLIERLINK3_DEBUG_MODE', 0); + + // Shop-Icon aus Konfiguration laden + $this->shopIcon = getDolGlobalString('SUPPLIERLINK3_SHOP_ICON', 'fas fa-store'); + + // Nur loggen wenn Debug aktiviert + if ($this->debug) { + error_log('['.date('Y-m-d H:i:s').'] [CONSTRUCTOR] ActionsSupplierLink3 instanziiert'."\n", 3, $this->debugLogFile); + } + } + + /** + * Debug-Log schreiben + * + * @param string $message Nachricht + * @param string $method Methodenname + */ + private function debugLog($message, $method = '') + { + if (!$this->debug) { + return; + } + + $logLine = '['.date('Y-m-d H:i:s').']'; + if ($method) { + $logLine .= ' ['.$method.']'; + } + $logLine .= ' '.$message."\n"; + + error_log($logLine, 3, $this->debugLogFile); } @@ -401,111 +453,443 @@ class ActionsSupplierLink3 extends CommonHookActions return 1; }*/ /* Add other hook methods here... */ - public function printObjectLine($parameters, &$object, &$action, $hookmanager) + + /** + * Holt alle Lieferanten mit Shop-URL für ein Produkt + * + * @param int $fk_product Produkt-ID + * @return array Array mit Lieferanten-Daten, sortiert nach Preis aufsteigend + */ + private function getAllSuppliersForProduct($fk_product) + { + $suppliers = array(); + + $sql = "SELECT DISTINCT + pfp.fk_soc as supplier_id, + pfp.ref_fourn, + pfp.price, + pfp.quantity as min_qty, + s.nom as supplier_name, + se.shop_url + FROM ".MAIN_DB_PREFIX."product_fournisseur_price pfp + INNER JOIN ".MAIN_DB_PREFIX."societe s ON s.rowid = pfp.fk_soc + LEFT JOIN ".MAIN_DB_PREFIX."societe_extrafields se ON se.fk_object = pfp.fk_soc + WHERE pfp.fk_product = ".(int)$fk_product." + AND se.shop_url IS NOT NULL + AND se.shop_url != '' + ORDER BY pfp.price ASC"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $suppliers[] = array( + 'supplier_id' => $obj->supplier_id, + 'ref_fourn' => $obj->ref_fourn, + 'price' => $obj->price, + 'min_qty' => $obj->min_qty, + 'supplier_name' => $obj->supplier_name, + 'shop_url' => rtrim($obj->shop_url, '/'), + 'full_url' => rtrim($obj->shop_url, '/') . '/' . $obj->ref_fourn + ); + } + } + + return $suppliers; + } + + /** + * Generiert HTML-Badge für Lagerbestand + * + * 4 Zustände: + * - ROT: stock <= 0 (Nicht verfügbar) + * - ORANGE: stock < seuil_stock_alerte (Unter Mindestmenge) + * - GRAU: stock < desiredstock (Unter Wunschmenge) + * - GRÜN: stock >= desiredstock (Ausreichend) + * + * @param float $qtyStock Aktueller Lagerbestand + * @param float $desiredQty Wunschbestand + * @param float $alertQty Mindestbestand (seuil_stock_alerte) + * @return string HTML-Badge + */ + private function getStockBadgeHtml($qtyStock, $desiredQty, $alertQty = 0) + { + if ($qtyStock <= 0) { + // ROT: Nicht verfügbar (0 oder negativ) + $badgeClass = 'badge-danger'; + $icon = 'fa-times-circle'; + $tooltip = 'Nicht auf Lager'; + } elseif ($alertQty > 0 && $qtyStock < $alertQty) { + // ORANGE: Unter Mindestmenge (Alarm-Schwelle) + $badgeClass = 'badge-warning'; + $icon = 'fa-exclamation-triangle'; + $tooltip = 'Unter Mindestmenge ('.(int)$alertQty.')'; + } elseif ($desiredQty > 0 && $qtyStock < $desiredQty) { + // GRAU: Unter Wunschmenge + $badgeClass = 'badge-secondary'; + $icon = 'fa-box-open'; + $tooltip = 'Unter Wunschmenge ('.(int)$desiredQty.')'; + } else { + // GRÜN: Ausreichend auf Lager + $badgeClass = 'badge-success'; + $icon = 'fa-check-circle'; + $tooltip = 'Ausreichend auf Lager'; + } + + $html = ''; + $html .= ''; + $html .= number_format($qtyStock, 0, ',', '.'); + $html .= ''; + + return $html; + } + + /** + * Generiert Shop-Link HTML (Icon oder Modal-Trigger für mehrere Lieferanten) + * + * @param array $suppliers Array der Lieferanten + * @param int $currentSupplierId Aktueller Lieferant der Bestellung + * @param string $refFourn Lieferanten-Artikelnummer + * @param int $lineId Zeilen-ID für eindeutige Modal-ID + * @return string HTML für Shop-Link + */ + private function getShopLinkHtml($suppliers, $currentSupplierId, $refFourn, $lineId) + { + if (empty($suppliers)) { + return ''; + } + + // Fall 1: Nur ein Lieferant mit Shop-URL - direkter Link + if (count($suppliers) == 1) { + $supplier = $suppliers[0]; + $html = 'shopIcon.'">'; + $html .= ''; + return $html; + } + + // Fall 2: Mehrere Lieferanten - Modal-Trigger + $modalId = 'supplier_modal_'.$lineId; + + // Trigger-Button mit Dropdown-Pfeil + $html = 'shopIcon.'">'; + $html .= ''; + $html .= ''; + + // Modal-Container (versteckt) + $html .= '