* GPL v3+ — siehe COPYING */ /** * \defgroup bericht Module Bericht * \brief Arbeitsberichte aus Anhängen erstellen, im Browser annotieren und an Rechnungen anhängen. * \file htdocs/bericht/core/modules/modBericht.class.php */ include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; class modBericht extends DolibarrModules { public function __construct($db) { global $conf, $langs; $this->db = $db; $this->numero = 500033; // Frei (500021 kollidiert mit BankImport, siehe llx_rights_def) $this->rights_class = 'bericht'; $this->family = "other"; $this->module_position = '90'; $this->name = preg_replace('/^mod/i', '', get_class($this)); $this->description = "Arbeitsberichte aus Rechnungs-Anhängen erstellen, im Browser annotieren und als PDF an die Rechnung anhängen."; $this->descriptionlong = "Fügt Rechnungen, Aufträgen und Angeboten einen Reiter 'Bericht' hinzu. Anhänge auswählen, im Browser mit Pfeilen/Kreisen/Rechtecken/Text annotieren, Seiten verwalten, Deckblatt aus ODT-Vorlage einfügen und als PDF unter Verknüpfte Dokumente speichern."; $this->editor_name = 'Alles Watt läuft'; $this->editor_url = ''; $this->version = '1.1.0'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->picto = 'fa-file-pdf'; $this->module_parts = array( 'triggers' => 0, 'login' => 0, 'substitutions' => 0, 'menus' => 0, 'tpl' => 0, 'barcode' => 0, 'models' => 0, 'printing' => 0, 'theme' => 0, 'css' => array('/bericht/css/bericht.css'), 'js' => array(), 'hooks' => array(), 'moduleforexternal' => 0, ); // Datenverzeichnisse $this->dirs = array( "/bericht/temp", "/bericht/templates", "/bericht/work", ); // Konfigurationsseite im Admin-Bereich $this->config_page_url = array("setup.php@bericht"); $this->hidden = false; $this->depends = array(); $this->requiredby = array(); $this->conflictwith = array(); $this->langfiles = array("bericht@bericht"); $this->phpmin = array(7, 4); $this->need_dolibarr_version = array(19, 0); $this->need_javascript_ajax = 1; // Konstanten beim Aktivieren anlegen $this->const = array( 0 => array('BERICHT_DEFAULT_TEMPLATE', 'chaine', '', 'Standard ODT-Template für Deckblatt', 0, 'current', 0), 1 => array('BERICHT_TAB_ON_INVOICE', 'chaine', '1', 'Reiter Bericht auf Rechnungen anzeigen', 0, 'current', 0), 2 => array('BERICHT_TAB_ON_ORDER', 'chaine', '1', 'Reiter Bericht auf Aufträgen anzeigen', 0, 'current', 0), 3 => array('BERICHT_TAB_ON_PROPAL', 'chaine', '1', 'Reiter Bericht auf Angeboten anzeigen', 0, 'current', 0), 4 => array('BERICHT_BURN_ANNOTATIONS', 'chaine', '1', 'Annotationen beim Export ins PDF einbrennen', 0, 'current', 0), 5 => array('BERICHT_LIBREOFFICE_BIN', 'chaine', '/usr/bin/libreoffice', 'Pfad zu LibreOffice für ODT→PDF Konvertierung', 0, 'current', 0), 6 => array('BERICHT_TAB_ON_THIRDPARTY', 'chaine', '1', 'Reiter Berichte auf Kundenkarten (read-only Übersicht)', 0, 'current', 0), ); // Tabs werden über den Hook (actions_bericht.class.php → addMoreActionsButtons / completeTabsHead) // dynamisch hinzugefügt, weil wir die Sichtbarkeit pro Element-Typ über Konstanten steuern wollen. // Statisch geht aber auch — sicherer und einfacher: $this->tabs = array( 'invoice:+bericht:Bericht:bericht@bericht:$user->hasRight("bericht","read"):/custom/bericht/bericht_card.php?id=__ID__&element=invoice', 'order:+bericht:Bericht:bericht@bericht:$user->hasRight("bericht","read"):/custom/bericht/bericht_card.php?id=__ID__&element=order', 'propal:+bericht:Bericht:bericht@bericht:$user->hasRight("bericht","read"):/custom/bericht/bericht_card.php?id=__ID__&element=propal', 'thirdparty:+bericht:Berichte:bericht@bericht:$user->hasRight("bericht","read"):/custom/bericht/bericht_thirdparty.php?socid=__ID__', ); $this->dictionaries = array(); $this->boxes = array(); // Kein Cronjob — Cleanup expired Upload-Tokens passiert on-demand // beim Anlegen eines neuen Tokens (siehe BerichtUploadToken::create()). $this->cronjobs = array(); // Rechte — wie Stundenzettel: [4]=perms, [5]=subperms (leer) $this->rights = array(); $r = 0; $this->rights[$r][0] = $this->numero + $r; $this->rights[$r][1] = 'Berichte lesen'; $this->rights[$r][3] = 1; // Standard aktiviert $this->rights[$r][4] = 'read'; $this->rights[$r][5] = ''; $r++; $this->rights[$r][0] = $this->numero + $r; $this->rights[$r][1] = 'Berichte erstellen und bearbeiten'; $this->rights[$r][3] = 1; $this->rights[$r][4] = 'write'; $this->rights[$r][5] = ''; $r++; $this->rights[$r][0] = $this->numero + $r; $this->rights[$r][1] = 'Berichte löschen'; $this->rights[$r][3] = 1; $this->rights[$r][4] = 'delete'; $this->rights[$r][5] = ''; $r++; $this->rights[$r][0] = $this->numero + $r; $this->rights[$r][1] = 'Modul Bericht administrieren (Templates verwalten)'; $this->rights[$r][3] = 0; $this->rights[$r][4] = 'admin'; $this->rights[$r][5] = ''; $r++; // Kein Menü — Berichte werden über Tabs auf Rechnungen/Aufträgen/Angeboten aufgerufen $this->menu = array(); } /** * Beim Aktivieren ausgeführt: SQL laden, Verzeichnisse anlegen, * vorhandene Extrafields auf llx_facture_extrafields prüfen und ggf. anlegen. */ public function init($options = '') { global $conf, $langs; // SQL-Tabellen anlegen $result = $this->_load_tables('/bericht/sql/'); if ($result < 0) { return -1; } // Migrationen für bestehende Tabellen $migrations = array( // Phase 1.3: Seitenformat "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN page_format VARCHAR(8) DEFAULT 'A4'", "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN page_orientation VARCHAR(8) DEFAULT 'P'", // Phase 1.4: Layout für mehrere Bilder pro Seite "ALTER TABLE ".$this->db->prefix()."bericht_page ADD COLUMN layout VARCHAR(16) DEFAULT 'single'", // Phase 1.5: Bildgröße/-position "ALTER TABLE ".$this->db->prefix()."bericht_page ADD COLUMN image_scale FLOAT DEFAULT 1.0", "ALTER TABLE ".$this->db->prefix()."bericht_page ADD COLUMN image_align VARCHAR(16) DEFAULT 'fit'", // Phase 5.5: Bericht-Vorlagen "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN is_template TINYINT(1) DEFAULT 0", "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN template_label VARCHAR(255) DEFAULT NULL", // Phase C: Titel pro Seite (Zwischentitel) "ALTER TABLE ".$this->db->prefix()."bericht_page ADD COLUMN title VARCHAR(255) DEFAULT NULL", // Phase 5.3: Versionierung "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN version INT DEFAULT 1", "ALTER TABLE ".$this->db->prefix()."bericht ADD COLUMN fk_bericht_parent INT DEFAULT NULL", // Phase 6: Composite-PNG (Client-WYSIWYG). Wenn gesetzt, wird die Seite // komplett aus diesem einen PNG gerendert statt aus source_path + fabric_json. // Der Editor rendert sein Fabric-Canvas bei jedem Save zu einem PNG und // lädt es hoch — damit ist PDF-Output identisch mit Editor-Anzeige. "ALTER TABLE ".$this->db->prefix()."bericht_page ADD COLUMN composite_path VARCHAR(512) DEFAULT NULL", // Foto-Upload entkoppeln: Token an Dolibarr-Objekt statt an Bericht binden "ALTER TABLE ".$this->db->prefix()."bericht_upload_token ADD COLUMN fk_element INTEGER NOT NULL DEFAULT 0", "ALTER TABLE ".$this->db->prefix()."bericht_upload_token ADD COLUMN element_type VARCHAR(32) NOT NULL DEFAULT 'order'", "UPDATE ".$this->db->prefix()."bericht_upload_token SET fk_element = fk_bericht, element_type = 'order' WHERE fk_element = 0 AND fk_bericht > 0", // Phase 5.9: Materialliste pro Auftrag "CREATE TABLE IF NOT EXISTS ".$this->db->prefix()."bericht_material (" ."rowid INT AUTO_INCREMENT PRIMARY KEY," ."element_type VARCHAR(32) NOT NULL," ."fk_element INT NOT NULL," ."label VARCHAR(255) NOT NULL," ."qty FLOAT DEFAULT 1," ."unit VARCHAR(16) DEFAULT 'Stk'," ."note TEXT DEFAULT NULL," ."fk_user_creat INT NOT NULL," ."datec DATETIME NOT NULL," ."INDEX idx_bm_element (element_type, fk_element)" .") ENGINE=innodb", ); foreach ($migrations as $sql) { // Errors ignorieren — Spalten existieren ggf. schon $this->db->query($sql, 1); } // Extrafields auf facture sicherstellen — vorhandene werden NICHT angefasst require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $extrafields = new ExtraFields($this->db); $fields = array( 'auftragsnummer' => array('label' => 'Auftragsnummer', 'type' => 'varchar', 'size' => 255, 'pos' => 100), 'angebotsnummer' => array('label' => 'Angebotsnummer', 'type' => 'varchar', 'size' => 255, 'pos' => 101), 'rechnungsnummer' => array('label' => 'Rechnungsnummer', 'type' => 'varchar', 'size' => 255, 'pos' => 102), 'beschreibung' => array('label' => 'Auftragsbeschreibung', 'type' => 'text', 'size' => 2000, 'pos' => 103), 'hinweis' => array('label' => 'Hinweis', 'type' => 'varchar', 'size' => 255, 'pos' => 104), ); foreach ($fields as $name => $def) { // Existiert das Feld bereits? → nicht überschreiben $check = $this->db->query("SELECT rowid FROM ".$this->db->prefix()."extrafields" ." WHERE name = '".$this->db->escape($name)."'" ." AND elementtype = 'facture'"); if ($check && $this->db->num_rows($check) > 0) { continue; } $extrafields->addExtraField( $name, $def['label'], $def['type'], $def['pos'], $def['size'], 'facture', 0, 0, '', '', 1, '', 0, 0, '', '', 'bericht@bericht', '1' ); } $sql = array(); return $this->_init($sql, $options); } /** * Beim Deaktivieren: Konstanten/Permissions entfernen, Daten und Extrafields BLEIBEN erhalten. */ public function remove($options = '') { $sql = array(); return $this->_remove($sql, $options); } }