feat: GlobalNotify Integration für Import-Benachrichtigungen
- Helper-Funktion notify() für sichere GlobalNotify-Nutzung - Benachrichtigung bei importierten Rechnungen (zur Prüfung) - Warnung bei Import-Fehlern - Fehler-Benachrichtigung bei IMAP-Verbindungsproblemen - Sofortige Benachrichtigung bei Exception/Fatal - countPendingInvoices() für Draft-Rechnungen-Zählung - Fallback auf dol_syslog wenn GlobalNotify nicht verfügbar - Version 3.7 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
59ce17b7b5
commit
8b0d1830a3
3 changed files with 157 additions and 1 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -2,6 +2,19 @@
|
||||||
|
|
||||||
Alle wesentlichen Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
Alle wesentlichen Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
||||||
|
|
||||||
|
## [3.7] - 2026-02-23
|
||||||
|
|
||||||
|
### Hinzugefügt
|
||||||
|
- **GlobalNotify Integration**: Benachrichtigungen über das zentrale GlobalNotify-Modul
|
||||||
|
- Import-Fehler: Warnung bei fehlgeschlagenen Importen
|
||||||
|
- Rechnungen zur Prüfung: Aktion wenn neue Rechnungen warten
|
||||||
|
- IMAP-Fehler: Warnung wenn E-Mail Postfach nicht erreichbar
|
||||||
|
- Exception/Fatal: Sofortige Benachrichtigung bei Abstürzen
|
||||||
|
- **Helper-Funktion**: `notify()` für sichere GlobalNotify-Nutzung mit Fallback
|
||||||
|
|
||||||
|
### Hinweis
|
||||||
|
GlobalNotify ist optional. Ohne das Modul werden Benachrichtigungen ins Dolibarr-Log geschrieben.
|
||||||
|
|
||||||
## [3.6] - 2026-02-23
|
## [3.6] - 2026-02-23
|
||||||
|
|
||||||
### Behoben
|
### Behoben
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,57 @@ class CronImportZugferd
|
||||||
*/
|
*/
|
||||||
private $startTime = 0;
|
private $startTime = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification via GlobalNotify (if available)
|
||||||
|
*
|
||||||
|
* @param string $type 'error', 'warning', 'info', 'action'
|
||||||
|
* @param string $title Title
|
||||||
|
* @param string $message Message
|
||||||
|
* @param string $actionUrl URL for action button
|
||||||
|
* @param string $actionLabel Label for action button
|
||||||
|
* @return bool True if sent via GlobalNotify
|
||||||
|
*/
|
||||||
|
protected function notify($type, $title, $message, $actionUrl = '', $actionLabel = '')
|
||||||
|
{
|
||||||
|
if (!isModEnabled('globalnotify')) {
|
||||||
|
dol_syslog("ImportZugferd [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$classFile = dol_buildpath('/globalnotify/class/globalnotify.class.php', 0);
|
||||||
|
if (!file_exists($classFile)) {
|
||||||
|
dol_syslog("ImportZugferd [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once $classFile;
|
||||||
|
|
||||||
|
if (!class_exists('GlobalNotify')) {
|
||||||
|
dol_syslog("ImportZugferd [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($type) {
|
||||||
|
case 'error':
|
||||||
|
GlobalNotify::error('importzugferd', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
GlobalNotify::warning('importzugferd', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
break;
|
||||||
|
case 'action':
|
||||||
|
GlobalNotify::actionRequired('importzugferd', $title, $message, $actionUrl, $actionLabel ?: 'Aktion erforderlich');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GlobalNotify::info('importzugferd', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
dol_syslog("GlobalNotify error: ".$e->getMessage(), LOG_ERR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
|
@ -226,17 +277,34 @@ class CronImportZugferd
|
||||||
$this->cronLog("Completed: imported={$this->imported_count}, skipped={$this->skipped_count}, errors={$this->error_count}, duration={$duration}s");
|
$this->cronLog("Completed: imported={$this->imported_count}, skipped={$this->skipped_count}, errors={$this->error_count}, duration={$duration}s");
|
||||||
$this->cronLog("========== CRON END (success) ==========");
|
$this->cronLog("========== CRON END (success) ==========");
|
||||||
|
|
||||||
|
// Send GlobalNotify notifications
|
||||||
|
$this->sendImportNotifications();
|
||||||
|
|
||||||
return ($this->error_count > 0) ? -1 : 0;
|
return ($this->error_count > 0) ? -1 : 0;
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->error = 'Exception: '.$e->getMessage();
|
$this->error = 'Exception: '.$e->getMessage();
|
||||||
$this->cronLog("EXCEPTION: ".$e->getMessage()."\n".$e->getTraceAsString(), 'ERROR');
|
$this->cronLog("EXCEPTION: ".$e->getMessage()."\n".$e->getTraceAsString(), 'ERROR');
|
||||||
$this->cronLog("========== CRON END (exception) ==========");
|
$this->cronLog("========== CRON END (exception) ==========");
|
||||||
|
$this->notify(
|
||||||
|
'error',
|
||||||
|
'ZUGFeRD Import fehlgeschlagen',
|
||||||
|
'Exception: '.$e->getMessage(),
|
||||||
|
dol_buildpath('/importzugferd/admin/setup.php', 1),
|
||||||
|
'Einstellungen prüfen'
|
||||||
|
);
|
||||||
return -1;
|
return -1;
|
||||||
} catch (Throwable $t) {
|
} catch (Throwable $t) {
|
||||||
$this->error = 'Fatal: '.$t->getMessage();
|
$this->error = 'Fatal: '.$t->getMessage();
|
||||||
$this->cronLog("FATAL: ".$t->getMessage()."\n".$t->getTraceAsString(), 'ERROR');
|
$this->cronLog("FATAL: ".$t->getMessage()."\n".$t->getTraceAsString(), 'ERROR');
|
||||||
$this->cronLog("========== CRON END (fatal) ==========");
|
$this->cronLog("========== CRON END (fatal) ==========");
|
||||||
|
$this->notify(
|
||||||
|
'error',
|
||||||
|
'ZUGFeRD Import Absturz',
|
||||||
|
'Fatal: '.$t->getMessage(),
|
||||||
|
dol_buildpath('/importzugferd/admin/setup.php', 1),
|
||||||
|
'Einstellungen prüfen'
|
||||||
|
);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -645,4 +713,79 @@ class CronImportZugferd
|
||||||
dol_syslog("CronImportZugferd: Keeping error file in watch folder: " . $file, LOG_INFO);
|
dol_syslog("CronImportZugferd: Keeping error file in watch folder: " . $file, LOG_INFO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notifications based on import results
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function sendImportNotifications()
|
||||||
|
{
|
||||||
|
// Check for errors
|
||||||
|
if ($this->error_count > 0) {
|
||||||
|
$errorSummary = count($this->errors) > 0 ? implode(', ', array_slice($this->errors, 0, 3)) : 'Siehe Log';
|
||||||
|
$this->notify(
|
||||||
|
'warning',
|
||||||
|
$this->error_count.' ZUGFeRD Import-Fehler',
|
||||||
|
$errorSummary,
|
||||||
|
dol_buildpath('/importzugferd/list.php?status=error', 1),
|
||||||
|
'Fehler anzeigen'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for imported invoices that need review
|
||||||
|
if ($this->imported_count > 0) {
|
||||||
|
// Count pending invoices (drafts needing approval)
|
||||||
|
$pendingCount = $this->countPendingInvoices();
|
||||||
|
|
||||||
|
if ($pendingCount > 0) {
|
||||||
|
$this->notify(
|
||||||
|
'action',
|
||||||
|
$this->imported_count.' ZUGFeRD Rechnungen importiert',
|
||||||
|
"{$pendingCount} Lieferantenrechnungen warten auf Prüfung und Freigabe",
|
||||||
|
dol_buildpath('/fourn/facture/list.php?search_status=0', 1),
|
||||||
|
'Rechnungen prüfen'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// All auto-created and validated
|
||||||
|
$this->notify(
|
||||||
|
'info',
|
||||||
|
$this->imported_count.' ZUGFeRD Rechnungen importiert',
|
||||||
|
'Alle Rechnungen wurden erfolgreich verarbeitet',
|
||||||
|
dol_buildpath('/fourn/facture/list.php', 1),
|
||||||
|
'Anzeigen'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IMAP connection issues
|
||||||
|
if (strpos($this->error, 'IMAP connection failed') !== false) {
|
||||||
|
$this->notify(
|
||||||
|
'error',
|
||||||
|
'IMAP Verbindung fehlgeschlagen',
|
||||||
|
'E-Mail Postfach für ZUGFeRD-Import nicht erreichbar',
|
||||||
|
dol_buildpath('/importzugferd/admin/setup.php', 1),
|
||||||
|
'IMAP prüfen'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count pending (draft) supplier invoices
|
||||||
|
*
|
||||||
|
* @return int Number of draft supplier invoices
|
||||||
|
*/
|
||||||
|
protected function countPendingInvoices()
|
||||||
|
{
|
||||||
|
$sql = "SELECT COUNT(*) as cnt FROM ".MAIN_DB_PREFIX."facture_fourn";
|
||||||
|
$sql .= " WHERE fk_statut = 0"; // Draft status
|
||||||
|
$sql .= " AND entity IN (".getEntity('facture_fourn').")";
|
||||||
|
|
||||||
|
$resql = $this->db->query($sql);
|
||||||
|
if ($resql) {
|
||||||
|
$obj = $this->db->fetch_object($resql);
|
||||||
|
return (int) $obj->cnt;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class modImportZugferd extends DolibarrModules
|
||||||
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@importzugferd'
|
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@importzugferd'
|
||||||
|
|
||||||
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
||||||
$this->version = '3.6';
|
$this->version = '3.7';
|
||||||
// Url to the file with your last numberversion of this module
|
// Url to the file with your last numberversion of this module
|
||||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue