* * 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 core/triggers/interface_99_modMetallzuschlag_MetallzuschlagTriggers.class.php * \ingroup metallzuschlag * \brief Trigger: Kupfergehalt + Kupferzuschlag berechnen */ require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; /** * Trigger fuer automatische Kupfergehalt- und Kupferzuschlag-Berechnung */ class InterfaceMetallzuschlagTriggers extends DolibarrTriggers { /** * Constructor * * @param DoliDB $db Database handler */ public function __construct($db) { $this->db = $db; $this->name = preg_replace('/^Interface/i', '', get_class($this)); $this->family = 'products'; $this->description = "Berechnet Kupfergehalt und Kupferzuschlag auf Einkaufspreisen"; $this->version = '1.1'; $this->picto = 'fa-coins'; } /** * Trigger-Funktion * * @param string $action Trigger-Aktion * @param Object $object Betroffenes Objekt * @param User $user Ausloesender User * @param Translate $langs Sprach-Objekt * @param Conf $conf Konfiguration * @return int 0 = OK, <0 = Fehler */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { if (!isModEnabled('metallzuschlag')) { return 0; } // Produkt erstellt oder geaendert → Kupfergehalt + Kupferzuschlag berechnen if ($action === 'PRODUCT_CREATE' || $action === 'PRODUCT_MODIFY') { $kupfergehalt = $this->calculateKupfergehalt($object); if ($kupfergehalt > 0) { $this->updateKupferzuschlagForProduct($object->id, $kupfergehalt); } return 0; } return 0; } /** * Berechnet Kupfergehalt aus Aderanzahl und Querschnitt * * Formel: kupfergehalt (kg/km) = aderanzahl × querschnitt (mm²) × 8,89 * * @param Product $object Produkt-Objekt * @return float Berechneter Kupfergehalt (0 wenn nicht berechenbar) */ private function calculateKupfergehalt($object) { if (empty($object->array_options)) { $object->fetch_optionals(); } $aderanzahl = !empty($object->array_options['options_aderanzahl']) ? (int) $object->array_options['options_aderanzahl'] : 0; $querschnitt = !empty($object->array_options['options_querschnitt']) ? (float) $object->array_options['options_querschnitt'] : 0; if ($aderanzahl <= 0 || $querschnitt <= 0) { return 0; } // Kupfergewicht: Aderanzahl × Querschnitt (mm²) × 8,89 kg/(km·mm²) $kupfergehalt = $aderanzahl * $querschnitt * 8.89; // In Produkt-Extrafield speichern $currentValue = !empty($object->array_options['options_kupfergehalt']) ? (float) $object->array_options['options_kupfergehalt'] : 0; if (round($currentValue, 4) !== round($kupfergehalt, 4)) { $sql = "UPDATE ".$this->db->prefix()."product_extrafields"; $sql .= " SET kupfergehalt = ".((float) $kupfergehalt); $sql .= " WHERE fk_object = ".((int) $object->id); $resql = $this->db->query($sql); if ($resql && $this->db->affected_rows($resql) == 0) { $sql2 = "INSERT INTO ".$this->db->prefix()."product_extrafields"; $sql2 .= " (fk_object, kupfergehalt) VALUES (".((int) $object->id).", ".((float) $kupfergehalt).")"; $this->db->query($sql2); } dol_syslog("Metallzuschlag: Kupfergehalt Produkt #".$object->id.": ".$aderanzahl." × ".$querschnitt." × 8,89 = ".round($kupfergehalt, 4)." kg/km", LOG_INFO); } return $kupfergehalt; } /** * Kupferzuschlag auf allen Einkaufspreisen eines Produkts berechnen * * Logik fuer CU-Notiz: * 1. Lieferant hat eigenen Metallzuschlag (metallzuschlag_cu) → diesen nehmen * 2. Sonst: aktuellsten verfuegbaren Wert aus metallzuschlag_history * * Formel: kupferzuschlag (EUR/m) = kupfergehalt (kg/km) × CU-Notiz (EUR/100kg) / 100.000 * * @param int $productId Produkt-ID * @param float $kupfergehalt Kupfergehalt in kg/km * @return int Anzahl aktualisierter Einkaufspreise */ private function updateKupferzuschlagForProduct($productId, $kupfergehalt) { // Alle Einkaufspreise des Produkts holen $sql = "SELECT pf.rowid, pf.fk_soc"; $sql .= " FROM ".$this->db->prefix()."product_fournisseur_price pf"; $sql .= " WHERE pf.fk_product = ".((int) $productId); $resql = $this->db->query($sql); if (!$resql) { return 0; } // Aktuellste CU-Notiz aus History als Fallback vorhalten $fallbackCU = $this->getLatestCUFromHistory(); $count = 0; while ($obj = $this->db->fetch_object($resql)) { // CU-Notiz fuer diesen Lieferanten bestimmen $cuNotiz = $this->getCUForSupplier((int) $obj->fk_soc, $fallbackCU); if ($cuNotiz <= 0) { continue; } // Kupferzuschlag EUR/m = Kupfergehalt (kg/km) × CU (EUR/100kg) / 100.000 $kupferzuschlag = $kupfergehalt * $cuNotiz / 100000; // In Einkaufspreis-Extrafield schreiben if ($this->saveKupferzuschlag((int) $obj->rowid, $kupferzuschlag)) { $count++; } } if ($count > 0) { dol_syslog("Metallzuschlag: Kupferzuschlag fuer ".$count." Einkaufspreise von Produkt #".$productId." aktualisiert", LOG_INFO); } return $count; } /** * CU-Notiz fuer einen Lieferanten ermitteln * * @param int $socId Lieferanten-ID * @param float $fallbackCU Fallback-Wert aus History * @return float CU-Notiz in EUR/100kg */ private function getCUForSupplier($socId, $fallbackCU) { // Lieferant hat eigenen Wert? $sql = "SELECT metallzuschlag_cu, metallzuschlag_source"; $sql .= " FROM ".$this->db->prefix()."societe_extrafields"; $sql .= " WHERE fk_object = ".((int) $socId); $resql = $this->db->query($sql); if ($resql && $this->db->num_rows($resql) > 0) { $obj = $this->db->fetch_object($resql); if (!empty($obj->metallzuschlag_cu) && (float) $obj->metallzuschlag_cu > 0) { return (float) $obj->metallzuschlag_cu; } } // Kein eigener Wert → Fallback return $fallbackCU; } /** * Aktuellste CU-Notiz aus der History-Tabelle holen * * @return float CU-Notiz in EUR/100kg (0 wenn nichts vorhanden) */ private function getLatestCUFromHistory() { $sql = "SELECT value FROM ".$this->db->prefix()."metallzuschlag_history"; $sql .= " WHERE metal = 'CU'"; $sql .= " ORDER BY date_notiz DESC LIMIT 1"; $resql = $this->db->query($sql); if ($resql && $this->db->num_rows($resql) > 0) { $obj = $this->db->fetch_object($resql); return (float) $obj->value; } return 0; } /** * Kupferzuschlag in Einkaufspreis-Extrafield speichern * * @param int $priceId Einkaufspreis-ID (rowid) * @param float $kupferzuschlag Wert in EUR/m * @return bool true wenn gespeichert */ private function saveKupferzuschlag($priceId, $kupferzuschlag) { // UPDATE versuchen $sql = "UPDATE ".$this->db->prefix()."product_fournisseur_price_extrafields"; $sql .= " SET kupferzuschlag = ".((float) $kupferzuschlag); $sql .= " WHERE fk_object = ".((int) $priceId); $resql = $this->db->query($sql); if ($resql && $this->db->affected_rows($resql) > 0) { return true; } // Zeile existiert nicht → INSERT $sql2 = "INSERT INTO ".$this->db->prefix()."product_fournisseur_price_extrafields"; $sql2 .= " (fk_object, kupferzuschlag) VALUES (".((int) $priceId).", ".((float) $kupferzuschlag).")"; return (bool) $this->db->query($sql2); } }