fix: Add try-catch to prevent cronjob from hanging
- Wrap updatePrices() in try-catch for fatal errors - Separate try-catch for GlobalNotify and mail sending - Prevents SMTP timeouts from blocking the entire cronjob Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c478e5003b
commit
af137e7d83
1 changed files with 107 additions and 95 deletions
202
class/preisbot.class.php
Normal file → Executable file
202
class/preisbot.class.php
Normal file → Executable file
|
|
@ -54,117 +54,129 @@ class PreisBot
|
|||
{
|
||||
global $conf, $user, $langs;
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||
try {
|
||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||
|
||||
$priceSource = getDolGlobalString('PREISBOT_PRICE_SOURCE', 'cheapest');
|
||||
$priceDirection = getDolGlobalString('PREISBOT_PRICE_DIRECTION', 'up_only');
|
||||
$minMargin = (float) getDolGlobalString('PREISBOT_MIN_MARGIN', 20);
|
||||
$priceSource = getDolGlobalString('PREISBOT_PRICE_SOURCE', 'cheapest');
|
||||
$priceDirection = getDolGlobalString('PREISBOT_PRICE_DIRECTION', 'up_only');
|
||||
$minMargin = (float) getDolGlobalString('PREISBOT_MIN_MARGIN', 20);
|
||||
|
||||
$updated = 0;
|
||||
$skipped = 0;
|
||||
$errors = 0;
|
||||
$priceChanges = array(); // Für Mail-Bericht
|
||||
$updated = 0;
|
||||
$skipped = 0;
|
||||
$errors = 0;
|
||||
$priceChanges = array();
|
||||
|
||||
// Hole alle Produkte mit gesetztem Gewinnaufschlag (nur zum Verkauf stehende)
|
||||
$sql = "SELECT p.rowid, p.ref, p.label, p.price, pe.preisbot_margin";
|
||||
$sql .= " FROM ".$this->db->prefix()."product as p";
|
||||
$sql .= " LEFT JOIN ".$this->db->prefix()."product_extrafields as pe ON pe.fk_object = p.rowid";
|
||||
$sql .= " WHERE pe.preisbot_margin IS NOT NULL";
|
||||
$sql .= " AND pe.preisbot_margin >= ".((float) $minMargin);
|
||||
$sql .= " AND p.tosell = 1"; // Nur Produkte die zum Verkauf stehen
|
||||
$sql .= " AND p.entity IN (".getEntity('product').")";
|
||||
// Hole alle Produkte mit gesetztem Gewinnaufschlag (nur zum Verkauf stehende)
|
||||
$sql = "SELECT p.rowid, p.ref, p.label, p.price, pe.preisbot_margin";
|
||||
$sql .= " FROM ".$this->db->prefix()."product as p";
|
||||
$sql .= " LEFT JOIN ".$this->db->prefix()."product_extrafields as pe ON pe.fk_object = p.rowid";
|
||||
$sql .= " WHERE pe.preisbot_margin IS NOT NULL";
|
||||
$sql .= " AND pe.preisbot_margin >= ".((float) $minMargin);
|
||||
$sql .= " AND p.tosell = 1";
|
||||
$sql .= " AND p.entity IN (".getEntity('product').")";
|
||||
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$productId = $obj->rowid;
|
||||
$currentPrice = (float) $obj->price;
|
||||
$margin = (float) $obj->preisbot_margin;
|
||||
|
||||
// Hole Einkaufspreis basierend auf Einstellung
|
||||
$buyPrice = $this->getSupplierPrice($productId, $priceSource);
|
||||
|
||||
if ($buyPrice <= 0) {
|
||||
$skipped++;
|
||||
continue;
|
||||
$resql = $this->db->query($sql);
|
||||
if (!$resql) {
|
||||
$this->error = $this->db->lasterror();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Berechne neuen Verkaufspreis
|
||||
$newPrice = $buyPrice * (1 + ($margin / 100));
|
||||
$newPrice = round($newPrice, 2);
|
||||
while ($obj = $this->db->fetch_object($resql)) {
|
||||
$productId = $obj->rowid;
|
||||
$currentPrice = (float) $obj->price;
|
||||
$margin = (float) $obj->preisbot_margin;
|
||||
|
||||
// Prüfe Preisrichtung
|
||||
if ($priceDirection === 'up_only' && $newPrice < $currentPrice) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
// Hole Einkaufspreis basierend auf Einstellung
|
||||
$buyPrice = $this->getSupplierPrice($productId, $priceSource);
|
||||
|
||||
// Nur aktualisieren wenn Preis sich ändert
|
||||
if (abs($newPrice - $currentPrice) < 0.01) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
if ($buyPrice <= 0) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Preis aktualisieren
|
||||
$product = new Product($this->db);
|
||||
$product->fetch($productId);
|
||||
// Berechne neuen Verkaufspreis
|
||||
$newPrice = $buyPrice * (1 + ($margin / 100));
|
||||
$newPrice = round($newPrice, 2);
|
||||
|
||||
// updatePrice($newprice, $newpricebase, $user, $newvat, $newminprice, $level, $newnpr, $newpbq, $ignore_autogen, $localtaxes_array, $newdefaultvatcode, $price_label, $notrigger)
|
||||
// Wir aktualisieren NUR den Preis, behalten aber alle anderen Werte bei
|
||||
$result = $product->updatePrice(
|
||||
$newPrice, // neuer Preis
|
||||
$product->price_base_type, // HT oder TTC - BEIBEHALTEN
|
||||
$user, // User
|
||||
$product->tva_tx, // MwSt-Satz - BEIBEHALTEN
|
||||
$product->price_min, // Mindestpreis - BEIBEHALTEN
|
||||
0, // Level (Preisstufe)
|
||||
$product->tva_npr, // NPR - BEIBEHALTEN
|
||||
0, // price by quantity
|
||||
0, // ignore autogen
|
||||
array(), // localtaxes
|
||||
$product->default_vat_code, // default vat code - BEIBEHALTEN
|
||||
'Preisbot' // price_label - Bezeichnung der Preisänderung
|
||||
);
|
||||
// Prüfe Preisrichtung
|
||||
if ($priceDirection === 'up_only' && $newPrice < $currentPrice) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($result > 0) {
|
||||
$updated++;
|
||||
$diff = $newPrice - $currentPrice;
|
||||
$diffPercent = $currentPrice > 0 ? round(($diff / $currentPrice) * 100, 2) : 0;
|
||||
// Nur aktualisieren wenn Preis sich ändert
|
||||
if (abs($newPrice - $currentPrice) < 0.01) {
|
||||
$skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$priceChanges[] = array(
|
||||
'ref' => $obj->ref,
|
||||
'label' => $obj->label,
|
||||
'old_price' => $currentPrice,
|
||||
'new_price' => $newPrice,
|
||||
'diff' => $diff,
|
||||
'diff_percent' => $diffPercent,
|
||||
'margin' => $margin,
|
||||
'buy_price' => $buyPrice
|
||||
// Preis aktualisieren
|
||||
$product = new Product($this->db);
|
||||
$product->fetch($productId);
|
||||
|
||||
$result = $product->updatePrice(
|
||||
$newPrice,
|
||||
$product->price_base_type,
|
||||
$user,
|
||||
$product->tva_tx,
|
||||
$product->price_min,
|
||||
0,
|
||||
$product->tva_npr,
|
||||
0,
|
||||
0,
|
||||
array(),
|
||||
$product->default_vat_code,
|
||||
'Preisbot'
|
||||
);
|
||||
|
||||
$this->output .= "Produkt ".$obj->ref.": ".$currentPrice." -> ".$newPrice." EUR (Aufschlag: ".$margin."%)\n";
|
||||
} else {
|
||||
$errors++;
|
||||
$this->errors[] = "Fehler bei Produkt ".$obj->ref.": ".$product->error;
|
||||
if ($result > 0) {
|
||||
$updated++;
|
||||
$diff = $newPrice - $currentPrice;
|
||||
$diffPercent = $currentPrice > 0 ? round(($diff / $currentPrice) * 100, 2) : 0;
|
||||
|
||||
$priceChanges[] = array(
|
||||
'ref' => $obj->ref,
|
||||
'label' => $obj->label,
|
||||
'old_price' => $currentPrice,
|
||||
'new_price' => $newPrice,
|
||||
'diff' => $diff,
|
||||
'diff_percent' => $diffPercent,
|
||||
'margin' => $margin,
|
||||
'buy_price' => $buyPrice
|
||||
);
|
||||
|
||||
$this->output .= "Produkt ".$obj->ref.": ".$currentPrice." -> ".$newPrice." EUR (Aufschlag: ".$margin."%)\n";
|
||||
} else {
|
||||
$errors++;
|
||||
$this->errors[] = "Fehler bei Produkt ".$obj->ref.": ".$product->error;
|
||||
}
|
||||
}
|
||||
|
||||
$this->output .= "\n--- Zusammenfassung ---\n";
|
||||
$this->output .= "Aktualisiert: ".$updated."\n";
|
||||
$this->output .= "Übersprungen: ".$skipped."\n";
|
||||
$this->output .= "Fehler: ".$errors."\n";
|
||||
|
||||
// Benachrichtigung und Mail nur wenn es Änderungen gab
|
||||
if ($updated > 0) {
|
||||
try {
|
||||
$this->sendNotification($priceChanges, $updated, $errors);
|
||||
} catch (Exception $e) {
|
||||
$this->output .= "Warnung: GlobalNotify fehlgeschlagen: ".$e->getMessage()."\n";
|
||||
}
|
||||
try {
|
||||
$this->sendMailReport($priceChanges, $updated, $skipped, $errors);
|
||||
} catch (Exception $e) {
|
||||
$this->output .= "Warnung: Mail-Versand fehlgeschlagen: ".$e->getMessage()."\n";
|
||||
}
|
||||
}
|
||||
|
||||
return ($errors > 0) ? -1 : 0;
|
||||
} catch (Exception $e) {
|
||||
$this->error = 'PreisBot Exception: '.$e->getMessage();
|
||||
$this->output .= 'FEHLER: '.$e->getMessage()."\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
$this->output .= "\n--- Zusammenfassung ---\n";
|
||||
$this->output .= "Aktualisiert: ".$updated."\n";
|
||||
$this->output .= "Übersprungen: ".$skipped."\n";
|
||||
$this->output .= "Fehler: ".$errors."\n";
|
||||
|
||||
// Benachrichtigung und Mail nur wenn es Änderungen gab
|
||||
if ($updated > 0) {
|
||||
$this->sendNotification($priceChanges, $updated, $errors);
|
||||
$this->sendMailReport($priceChanges, $updated, $skipped, $errors);
|
||||
}
|
||||
|
||||
return ($errors > 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue