Fix: CSS-Einbindung mit file_exists() absichern

- filemtime() warf Fehler wenn CSS-Datei nicht existiert
- Alle Update 1.2.0 Felder werden jetzt bei Aktivierung geprüft/angelegt
- SQL-Update-Skript erweitert

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-02-08 18:45:37 +01:00
parent f74f710717
commit 15fec1e8df
4 changed files with 55 additions and 7 deletions

View file

@ -783,7 +783,10 @@ $_GET['mainmenu'] = 'stundenzettel';
llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-card'); llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-card');
// Mobile CSS einbinden // Mobile CSS einbinden
print '<link rel="stylesheet" type="text/css" href="'.dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 1).'?v='.filemtime(dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 0)).'">'; $mobileCssFile = dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 0);
if (file_exists($mobileCssFile)) {
print '<link rel="stylesheet" type="text/css" href="'.dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 1).'?v='.filemtime($mobileCssFile).'">';
}
// JavaScript für Mengenprüfung // JavaScript für Mengenprüfung
print '<script type="text/javascript"> print '<script type="text/javascript">

View file

@ -458,14 +458,14 @@ class modStundenzettel extends DolibarrModules
} }
/** /**
* Fügt die Leistungsposition zur Leistungstabelle hinzu (Update 1.2.0) * Fügt die neuen Felder für Update 1.2.0 hinzu
* Wird bei jeder Modulaktivierung ausgeführt - IF NOT EXISTS verhindert Fehler * Wird bei jeder Modulaktivierung ausgeführt - IF NOT EXISTS verhindert Fehler
* *
* @return int 1 if OK, -1 if error * @return int 1 if OK, -1 if error
*/ */
private function addHourlyRateFields() private function addHourlyRateFields()
{ {
// Spalte fk_product zur Leistungstabelle hinzufügen falls nicht vorhanden // 1. Spalte fk_product zur Leistungstabelle hinzufügen falls nicht vorhanden
$sql1 = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel_leistung $sql1 = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel_leistung
ADD COLUMN IF NOT EXISTS fk_product INTEGER DEFAULT NULL ADD COLUMN IF NOT EXISTS fk_product INTEGER DEFAULT NULL
COMMENT 'Verknüpfung zur Leistungsposition (Dienstleistung)'"; COMMENT 'Verknüpfung zur Leistungsposition (Dienstleistung)'";
@ -482,7 +482,41 @@ class modStundenzettel extends DolibarrModules
} }
} }
dol_syslog("modStundenzettel::addHourlyRateFields Service product field checked/added", LOG_DEBUG); // 2. Spalte hourly_rate zur Haupttabelle hinzufügen falls nicht vorhanden
$sql2 = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel
ADD COLUMN IF NOT EXISTS hourly_rate DOUBLE(24,8) DEFAULT NULL
COMMENT 'Stundenpreis (NULL = Standard verwenden)'";
$resql2 = $this->db->query($sql2);
if (!$resql2) {
// Fallback für ältere MySQL-Versionen ohne IF NOT EXISTS
$sql2b = "SHOW COLUMNS FROM ".MAIN_DB_PREFIX."stundenzettel LIKE 'hourly_rate'";
$resql2b = $this->db->query($sql2b);
if ($resql2b && $this->db->num_rows($resql2b) == 0) {
$sql2c = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel
ADD COLUMN hourly_rate DOUBLE(24,8) DEFAULT NULL";
$this->db->query($sql2c);
}
}
// 3. Spalte hourly_rate_is_custom zur Haupttabelle hinzufügen falls nicht vorhanden
$sql3 = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel
ADD COLUMN IF NOT EXISTS hourly_rate_is_custom TINYINT DEFAULT 0 NOT NULL
COMMENT '1 = manuell geändert'";
$resql3 = $this->db->query($sql3);
if (!$resql3) {
// Fallback für ältere MySQL-Versionen ohne IF NOT EXISTS
$sql3b = "SHOW COLUMNS FROM ".MAIN_DB_PREFIX."stundenzettel LIKE 'hourly_rate_is_custom'";
$resql3b = $this->db->query($sql3b);
if ($resql3b && $this->db->num_rows($resql3b) == 0) {
$sql3c = "ALTER TABLE ".MAIN_DB_PREFIX."stundenzettel
ADD COLUMN hourly_rate_is_custom TINYINT DEFAULT 0 NOT NULL";
$this->db->query($sql3c);
}
}
dol_syslog("modStundenzettel::addHourlyRateFields All 1.2.0 fields checked/added", LOG_DEBUG);
return 1; return 1;
} }

View file

@ -1,8 +1,16 @@
-- ============================================================================ -- ============================================================================
-- Stundenzettel Update auf Version 1.2.0 -- Stundenzettel Update auf Version 1.2.0
-- Fügt Leistungsposition zu Arbeitszeiten hinzu -- Fügt Leistungsposition zu Arbeitszeiten und Stundenpreis-Felder hinzu
-- ============================================================================ -- ============================================================================
-- Leistungsposition (Dienstleistung) pro Arbeitszeit -- 1. Leistungsposition (Dienstleistung) pro Arbeitszeit
ALTER TABLE llx_stundenzettel_leistung ALTER TABLE llx_stundenzettel_leistung
ADD COLUMN IF NOT EXISTS fk_product INTEGER DEFAULT NULL COMMENT 'Verknüpfung zur Leistungsposition (Dienstleistung)'; ADD COLUMN IF NOT EXISTS fk_product INTEGER DEFAULT NULL COMMENT 'Verknüpfung zur Leistungsposition (Dienstleistung)';
-- 2. Stundenpreis in Haupttabelle
ALTER TABLE llx_stundenzettel
ADD COLUMN IF NOT EXISTS hourly_rate DOUBLE(24,8) DEFAULT NULL COMMENT 'Stundenpreis (NULL = Standard verwenden)';
-- 3. Flag ob Stundenpreis manuell gesetzt wurde
ALTER TABLE llx_stundenzettel
ADD COLUMN IF NOT EXISTS hourly_rate_is_custom TINYINT DEFAULT 0 NOT NULL COMMENT '1 = manuell geändert';

View file

@ -1084,7 +1084,10 @@ $title = $langs->trans("Stundenzettel").' - '.$order->ref;
llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-commande'); llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-commande');
// Mobile CSS einbinden // Mobile CSS einbinden
print '<link rel="stylesheet" type="text/css" href="'.dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 1).'?v='.filemtime(dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 0)).'">'; $mobileCssFile = dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 0);
if (file_exists($mobileCssFile)) {
print '<link rel="stylesheet" type="text/css" href="'.dol_buildpath('/stundenzettel/css/stundenzettel-mobile.css', 1).'?v='.filemtime($mobileCssFile).'">';
}
// Tabs - Immer die Stundenzettel-Commande-Tabs verwenden // Tabs - Immer die Stundenzettel-Commande-Tabs verwenden
// Aktiven Tab-Key basierend auf $tab bestimmen // Aktiven Tab-Key basierend auf $tab bestimmen