From f79e126c8c7a83773cd3254427fbc82dce9ff2fb Mon Sep 17 00:00:00 2001 From: "matthias.lotz" Date: Tue, 23 Dec 2025 14:48:44 +0100 Subject: [PATCH] DokuWiki Integration: wiki_doku_id aus Name+Modell, zentraler Namespace konfigurierbar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - wiki_doku_id wird nun aus equipment.name und equipment.model kombiniert generiert - Systemparameter 'dokuwiki.central_documentation_namespace' für konfigurierbaren Namespace - Verbessertes Error-Handling in dokuwiki_client mit detaillierteren Fehlermeldungen - Docker-Netzwerk Unterstützung dokumentiert - Gelöschte veraltete WordPress-API Dateien --- .../openworkshop-odoo-api.php | 300 ------------------ open_workshop-api-for-wordpress/readme.txt | 30 -- open_workshop_dokuwiki/README.md | 60 +++- open_workshop_dokuwiki/__manifest__.py | 2 +- .../data/dokuwiki_uebersicht_template.txt | 24 -- .../maintenance_equipment_status_data.xml | 4 +- .../models/dokuwiki_client.py | 43 ++- .../models/maintenance_equipment.py | 135 +++++++- .../models/maintenance_equipment_status.py | 16 + .../models/res_config_settings.py | 2 + 10 files changed, 233 insertions(+), 383 deletions(-) delete mode 100644 open_workshop-api-for-wordpress/openworkshop-odoo-api.php delete mode 100644 open_workshop-api-for-wordpress/readme.txt delete mode 100644 open_workshop_dokuwiki/data/dokuwiki_uebersicht_template.txt diff --git a/open_workshop-api-for-wordpress/openworkshop-odoo-api.php b/open_workshop-api-for-wordpress/openworkshop-odoo-api.php deleted file mode 100644 index e5def94..0000000 --- a/open_workshop-api-for-wordpress/openworkshop-odoo-api.php +++ /dev/null @@ -1,300 +0,0 @@ - 'array', - 'sanitize_callback' => array( $this, 'sanitize_settings' ), - 'default' => array( - 'base_url' => '', - 'api_token' => '', - 'machines_endpoint' => '/api/v1/machines', - ), - ) - ); - - add_settings_section( - 'openworkshop_odoo_api_main', - __( 'Odoo API Einstellungen', 'openworkshop-odoo-api' ), - '__return_false', - 'openworkshop-odoo-api' - ); - - add_settings_field( - 'base_url', - __( 'Odoo Basis-URL', 'openworkshop-odoo-api' ), - array( $this, 'render_field_base_url' ), - 'openworkshop-odoo-api', - 'openworkshop_odoo_api_main' - ); - - add_settings_field( - 'machines_endpoint', - __( 'Endpoint für Maschinenliste', 'openworkshop-odoo-api' ), - array( $this, 'render_field_machines_endpoint' ), - 'openworkshop-odoo-api', - 'openworkshop_odoo_api_main' - ); - - add_settings_field( - 'api_token', - __( 'API Token (optional)', 'openworkshop-odoo-api' ), - array( $this, 'render_field_api_token' ), - 'openworkshop-odoo-api', - 'openworkshop_odoo_api_main' - ); - } - - public function sanitize_settings( $input ) { - $output = array(); - - $output['base_url'] = isset( $input['base_url'] ) - ? esc_url_raw( rtrim( $input['base_url'], '/' ) ) - : ''; - - $output['machines_endpoint'] = isset( $input['machines_endpoint'] ) - ? sanitize_text_field( $input['machines_endpoint'] ) - : '/api/v1/machines'; - - $output['api_token'] = isset( $input['api_token'] ) - ? sanitize_text_field( $input['api_token'] ) - : ''; - - return $output; - } - - public function get_settings() { - $settings = get_option( self::OPTION_NAME, array() ); - $defaults = array( - 'base_url' => '', - 'api_token' => '', - 'machines_endpoint' => '/api/v1/machines', - ); - - return wp_parse_args( $settings, $defaults ); - } - - public function render_settings_page() { - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - $settings = $this->get_settings(); - ?> -
-

-
- -
- -

-

- [openworkshop_machines] -

-
- get_settings(); - ?> - -

- -

- get_settings(); - ?> - -

- -

- get_settings(); - ?> - -

- -

- 0, - ), - $atts, - 'openworkshop_machines' - ); - - $data = $this->fetch_machines(); - - if ( is_wp_error( $data ) ) { - return '

' . esc_html__( 'Fehler beim Laden der Maschinendaten aus Odoo.', 'openworkshop-odoo-api' ) . '

'; - } - - if ( ! is_array( $data ) || empty( $data ) ) { - return '

' . esc_html__( 'Keine Maschinen gefunden.', 'openworkshop-odoo-api' ) . '

'; - } - - $limit = intval( $atts['limit'] ); - if ( $limit > 0 ) { - $data = array_slice( $data, 0, $limit ); - } - - ob_start(); - ?> -
- - - - - - - - - - - - - - - - - -
- - - - - -
-
- get_settings(); - - if ( empty( $settings['base_url'] ) ) { - return new WP_Error( 'openworkshop_no_base_url', __( 'Keine Odoo Basis-URL konfiguriert.', 'openworkshop-odoo-api' ) ); - } - - $url = $settings['base_url'] . $settings['machines_endpoint']; - - $args = array( - 'timeout' => 10, - 'headers' => array( - 'Accept' => 'application/json', - ), - ); - - if ( ! empty( $settings['api_token'] ) ) { - $args['headers']['Authorization'] = 'Bearer ' . $settings['api_token']; - } - - $response = wp_remote_get( $url, $args ); - - if ( is_wp_error( $response ) ) { - return $response; - } - - $code = wp_remote_retrieve_response_code( $response ); - $body = wp_remote_retrieve_body( $response ); - - if ( $code < 200 || $code >= 300 ) { - return new WP_Error( 'openworkshop_bad_status', sprintf( 'HTTP %d', $code ) ); - } - - $data = json_decode( $body, true ); - if ( json_last_error() !== JSON_ERROR_NONE ) { - return new WP_Error( 'openworkshop_json_error', json_last_error_msg() ); - } - - return $data; - } -} - -function openworkshop_odoo_api_bootstrap() { - static $instance = null; - if ( $instance === null ) { - $instance = new OpenWorkshop_Odoo_API_Plugin(); - } - return $instance; -} - -openworkshop_odoo_api_bootstrap(); diff --git a/open_workshop-api-for-wordpress/readme.txt b/open_workshop-api-for-wordpress/readme.txt deleted file mode 100644 index cfae512..0000000 --- a/open_workshop-api-for-wordpress/readme.txt +++ /dev/null @@ -1,30 +0,0 @@ -=== OpenWorkshop Odoo API === -Contributors: hobbyhimmel -Tags: odoo, api, openworkshop, integration -Requires at least: 5.8 -Tested up to: 6.6 -Stable tag: 0.1.0 -License: GPLv3 -License URI: https://www.gnu.org/licenses/gpl-3.0.html - -Dieses Plugin bindet Maschinendaten aus einer Odoo/OpenWorkshop-Installation via REST-API in WordPress ein. - -== Beschreibung == - -Das Plugin stellt u.a. den Shortcode [openworkshop_machines] bereit, der eine einfache Maschinenliste -auf Basis eines JSON-Endpunkts in Odoo rendert. - -In den Einstellungen kann die Basis-URL der Odoo-Instanz, der Endpoint (z.B. /api/v1/machines) sowie ein -optionaler API-Token hinterlegt werden. - -== Installation == - -1. ZIP in WordPress unter Plugins → Installieren → Plugin hochladen hochladen. -2. Aktivieren. -3. Unter Einstellungen → OpenWorkshop Odoo API die Basis-URL und den Endpoint konfigurieren. -4. Den Shortcode [openworkshop_machines] in einer Seite oder einem Beitrag einfügen. - -== Changelog == - -= 0.1.0 = -* Erste Version. diff --git a/open_workshop_dokuwiki/README.md b/open_workshop_dokuwiki/README.md index da70a7e..cad0deb 100644 --- a/open_workshop_dokuwiki/README.md +++ b/open_workshop_dokuwiki/README.md @@ -93,6 +93,13 @@ dokuwiki.overview_columns = Name|Hersteller|Modell|Seriennummer|Kosten|Garantie| dokuwiki.overview_column_data = {name}|{partner_id}|{model}|{serial_no}|{cost}|{warranty_date}|{location}|{ows_machine_id.category_icon} ``` +### Beispiel 4: Mit Tags + +```python +dokuwiki.overview_columns = Status|Name|Typ|Tags|Standort|Dokumentation +dokuwiki.overview_column_data = {status_smiley}|{name}|{model}|{tags_list}|{location}|{wiki_doku_link} +``` + **Wichtig:** Anzahl der Pipes muss übereinstimmen! - 3 Pipes = 4 Spalten - Spalten und Daten müssen gleiche Anzahl haben @@ -167,14 +174,45 @@ dokuwiki.overview_column_data = {name}|{partner_id}|{model}|{serial_no}|{cost}|{ ## Automatische Updates -Die Übersichtstabelle wird **NICHT** automatisch bei Equipment-Änderungen aktualisiert. +Die Übersichtstabelle kann optional automatisch bei Equipment-Änderungen aktualisiert werden. -**Manueller Sync empfohlen:** +### Manueller Sync (empfohlen) + +**Manueller Sync empfohlen für:** - Nach Massen-Importen - Einmal täglich/wöchentlich - Bei strukturellen Änderungen (neue Bereiche, etc.) -**Alternativ: Cronjob einrichten** +**Vorteil:** Performanter, keine zusätzliche Last bei jeder Equipment-Änderung + +### Automatischer Sync bei Equipment-Änderungen + +**Was passiert beim Speichern eines Equipment?** + +1. **Equipment-Detailseite wird immer aktualisiert** wenn: + - Eines der überwachten Felder geändert wurde (siehe unten) + - `wiki_auto_sync` für das Equipment aktiviert ist (Standard: `True`) + - Equipment bereits synchronisiert wurde (`wiki_synced = True`) + +2. **Übersichtstabelle wird zusätzlich aktualisiert** wenn: + - Alle Bedingungen von (1) erfüllt sind UND + - Systemparameter `dokuwiki.auto_update_overview_table = True` gesetzt ist + +**Überwachte Felder (lösen Sync aus):** +- `name`, `serial_no`, `ows_area_id`, `category_id`, `status_id` +- `model`, `partner_id`, `location`, `note`, `image_1920`, `tag_ids` + +**Aktivierung Übersichtstabellen-Sync:** +```python +# In Odoo: Einstellungen → Technisch → Parameter → Systemparameter +dokuwiki.auto_update_overview_table = True +``` + +**Achtung:** +- Bei vielen gleichzeitigen Equipment-Änderungen kann dies Performance-Probleme verursachen! +- Die komplette Übersichtstabelle wird bei jeder Änderung neu generiert (ca. 156 Zeilen) + +### Cronjob (Alternative) ```python # In Odoo: Einstellungen → Technisch → Automatisierung → Geplante Aktionen @@ -207,6 +245,12 @@ Alle Platzhalter aus dem Detail-Template sind verfügbar! - `{partner_id}` - Lieferant (Name) - `{partner_ref}` - Lieferanten-Referenz +## Tags (falls maintenance_equipment_tags installiert) + +- `{tags}` - Komma-separierte Liste aller Tags (z.B. "Holz, CNC, Einweisung erforderlich") +- `{tags_list}` - DokuWiki Bullet-Liste mit Zeilenumbrüchen (ideal für Tabellenzellen) +- `{tags_count}` - Anzahl der zugewiesenen Tags + ## Spezial-Felder - `{view_type}` - "Bereich" oder "Einsatzzweck" @@ -216,7 +260,7 @@ Alle Platzhalter aus dem Detail-Template sind verfügbar! - `{odoo_link}` - Fertiger Link zur Odoo Equipment-Seite - `{odoo_url}` - URL zur Odoo Equipment-Seite (ohne Link-Markup) - `{sync_datetime}` - Aktuelles Datum/Zeit -- `{image}` - Equipment-Bild (300px Breite) - Format: `{{:media_id?300}}` +- `{image}` - Equipment-Bild (100px Breite) - Format: `{{:media_id?100}}` - `{image_large}` - Equipment-Bild (Originalgröße) - Format: `{{:media_id}}` - `{image_id}` - Media-ID des Bildes (z.B. werkstatt:ausruestung:media:sabako-laser.jpg) @@ -236,7 +280,7 @@ Alle Platzhalter aus dem Detail-Template sind verfügbar! - **Pipe als Trenner**: Zwischen Spalten `|` verwenden - **Leere Werte**: Werden automatisch durch `-` ersetzt - **Links**: `{wiki_doku_link}` und `{odoo_link}` enthalten bereits DokuWiki Link-Syntax -- **Bilder**: `{image}` ist bereits formatiert mit `{{:...?300}}` +- **Bilder**: `{image}` ist bereits formatiert mit `{{:...?100}}` - **ows.machine**: Immer mit Präfix `ows_machine_id.` (z.B. `{ows_machine_id.location}`) ## Beispiel-Konfigurationen @@ -258,3 +302,9 @@ Daten: {status_smiley}|{ows_machine_id.category_icon}|{partner_id}|{note}|{mod Spalten: Name|Status|Kategorie|Hersteller|Modell|S/N|Kosten|Garantie|Standort|Bereich|Bild|Doku Daten: {name}|{status_smiley}|{ows_machine_id.category_icon}|{partner_id}|{model}|{serial_no}|{cost}|{warranty_date}|{location}|{ows_area}|{image}|{wiki_doku_link} ``` + +### Mit Tags +``` +Spalten: Name|Status|Tags|Hersteller|Standort|Doku +Daten: {name}|{status_smiley}|{tags_list}|{partner_id}|{location}|{wiki_doku_link} +``` diff --git a/open_workshop_dokuwiki/__manifest__.py b/open_workshop_dokuwiki/__manifest__.py index e1aa87a..7c1353f 100644 --- a/open_workshop_dokuwiki/__manifest__.py +++ b/open_workshop_dokuwiki/__manifest__.py @@ -31,7 +31,7 @@ ACL: * Phase 1: Nur @odoo Gruppe hat Zugriff * Phase 2: @werkstatt bekommt Lesezugriff auf Hauptseiten, Edit-Zugriff auf Doku-Seiten """, - 'author': 'Open Workshop', + 'author': 'Hobbyhimmel', 'website': 'https://hobbyhimmel.de', 'license': 'LGPL-3', 'depends': [ diff --git a/open_workshop_dokuwiki/data/dokuwiki_uebersicht_template.txt b/open_workshop_dokuwiki/data/dokuwiki_uebersicht_template.txt deleted file mode 100644 index 3e049ee..0000000 --- a/open_workshop_dokuwiki/data/dokuwiki_uebersicht_template.txt +++ /dev/null @@ -1,24 +0,0 @@ -====== Geräte & Maschinen - Übersicht ====== - -Diese Seite wird automatisch von Odoo aktualisiert und bietet eine sortier- und filterbare Übersicht aller Geräte und Maschinen. - -**Letztes Update:** {{SYNC_DATETIME}} - - -^ Name ^ Status ^ Sicherheits-Kategorie ^ Bereich ^ Standort ^ Bild ^ -{{EQUIPMENT_TABLE_ROWS}} - - ----- - -**Hinweis:** Diese Tabelle ist interaktiv: - * Klicken Sie auf die Spaltenköpfe zum Sortieren - * Nutzen Sie das Suchfeld zum Filtern - * Klicken Sie auf den Namen für die Detail-Dokumentation - -**Symbole:** - * 🟢 Grün = Keine Einweisung erforderlich - * 🟡 Gelb = Einweisung empfohlen - * 🔴 Rot = Einweisung zwingend erforderlich - -//Automatisch generiert aus Odoo - Änderungen werden beim nächsten Sync überschrieben// diff --git a/open_workshop_dokuwiki/data/maintenance_equipment_status_data.xml b/open_workshop_dokuwiki/data/maintenance_equipment_status_data.xml index 9eef744..ada5b18 100644 --- a/open_workshop_dokuwiki/data/maintenance_equipment_status_data.xml +++ b/open_workshop_dokuwiki/data/maintenance_equipment_status_data.xml @@ -3,11 +3,11 @@ - :-) + 😊 - :-( + ☹️ diff --git a/open_workshop_dokuwiki/models/dokuwiki_client.py b/open_workshop_dokuwiki/models/dokuwiki_client.py index 097f717..455f51c 100644 --- a/open_workshop_dokuwiki/models/dokuwiki_client.py +++ b/open_workshop_dokuwiki/models/dokuwiki_client.py @@ -42,15 +42,34 @@ class DokuWikiClient(models.AbstractModel): "- dokuwiki.password" ) + # URL validieren/normalisieren + if not wiki_url.startswith(('http://', 'https://')): + raise UserError(f"DokuWiki URL muss mit http:// oder https:// beginnen: {wiki_url}") + try: + _logger.info(f"Verbinde zu DokuWiki: {wiki_url} (User: {wiki_user})") wiki = DokuWiki(wiki_url, wiki_user, wiki_password) # Test-Verbindung version = wiki.version - _logger.info(f"DokuWiki-Verbindung erfolgreich: {version}") + _logger.info(f"DokuWiki-Verbindung erfolgreich: Version {version}") return wiki except DokuWikiError as e: - _logger.error(f"DokuWiki-Verbindung fehlgeschlagen: {e}") - raise UserError(f"Verbindung zu DokuWiki fehlgeschlagen: {e}") + error_details = f"URL: {wiki_url}, User: {wiki_user}, Fehler: {e}" + _logger.error(f"DokuWiki-Verbindung fehlgeschlagen: {error_details}") + raise UserError( + f"Verbindung zu DokuWiki fehlgeschlagen.\n\n" + f"Details:\n" + f"- URL: {wiki_url}\n" + f"- User: {wiki_user}\n" + f"- Fehler: {e}\n\n" + f"Hinweise:\n" + f"- Prüfen Sie ob die URL korrekt ist (sollte auf /lib/exe/xmlrpc.php zeigen)\n" + f"- Stellen Sie sicher, dass XML-RPC in DokuWiki aktiviert ist\n" + f"- Prüfen Sie die Benutzer-Zugangsdaten" + ) + except Exception as e: + _logger.error(f"Unerwarteter Fehler bei DokuWiki-Verbindung: {e}", exc_info=True) + raise UserError(f"Unerwarteter Fehler: {e}") @api.model def create_page(self, page_id, content, summary="Erstellt von Odoo"): @@ -71,12 +90,24 @@ class DokuWikiClient(models.AbstractModel): wiki = self._get_wiki_connection() try: + _logger.info(f"Erstelle/Aktualisiere Wiki-Seite: {page_id} ({len(content)} Zeichen)") wiki.pages.set(page_id, content, summary=summary) - _logger.info(f"Wiki-Seite erstellt/aktualisiert: {page_id}") + _logger.info(f"Wiki-Seite erfolgreich erstellt/aktualisiert: {page_id}") return True except DokuWikiError as e: - _logger.error(f"Fehler beim Erstellen der Wiki-Seite {page_id}: {e}") - raise UserError(f"Fehler beim Erstellen der Wiki-Seite: {e}") + _logger.error(f"DokuWiki API Fehler bei Seite {page_id}: {e}", exc_info=True) + raise UserError( + f"Fehler beim Erstellen der Wiki-Seite '{page_id}':\n\n" + f"{e}\n\n" + f"Mögliche Ursachen:\n" + f"- XML-RPC nicht aktiviert in DokuWiki\n" + f"- Keine Schreibrechte für den Namespace\n" + f"- Ungültige Zeichen in der Page-ID\n" + f"- DokuWiki gibt Fehler/Warnings aus (prüfen Sie die DokuWiki-Logs)" + ) + except Exception as e: + _logger.error(f"Unerwarteter Fehler beim Erstellen der Seite {page_id}: {e}", exc_info=True) + raise UserError(f"Unerwarteter Fehler: {e}") @api.model def get_page(self, page_id): diff --git a/open_workshop_dokuwiki/models/maintenance_equipment.py b/open_workshop_dokuwiki/models/maintenance_equipment.py index fef3123..5071bc7 100644 --- a/open_workshop_dokuwiki/models/maintenance_equipment.py +++ b/open_workshop_dokuwiki/models/maintenance_equipment.py @@ -9,6 +9,63 @@ _logger = logging.getLogger(__name__) class MaintenanceEquipment(models.Model): + """ + Erweitert das Maintenance Equipment Modell um DokuWiki-Integration. + Diese Klasse ermöglicht die Synchronisation von Werkstatt-Equipment-Daten mit einem + DokuWiki-System. Jedes Equipment erhält eine zentrale Dokumentationsseite sowie + verschiedene Ansichtsseiten (nach Bereich, später auch nach Einsatzzweck). + Hauptfunktionen: + - Automatische Generierung von Wiki-Seiten aus Equipment-Daten + - Template-basierte Wiki-Seiten-Erstellung (verwendet c_template aus DokuWiki) + - Bild-Upload und Einbindung in Wiki-Seiten + - Zentrale Dokumentationsseite pro Equipment (manuell erweiterbar) + - Bereichs-spezifische Übersichtsseiten (automatisch aktualisiert) + - Automatische Übersichtstabelle aller Equipment (DataTable mit Sortierung/Filterung) + - Automatische Synchronisation bei Feldänderungen (optional) + Wiki-Seitenstruktur: + - werkstatt:ausruestung:doku:{wiki_doku_id} - Zentrale Dokumentation + - werkstatt:ausruestung:{area}:{wiki_doku_id} - Bereichsansicht + - werkstatt:ausruestung:uebersicht - Equipment-Übersichtstabelle + Neue Felder: + - image_1920: Bild des Equipment (wird automatisch ins Wiki hochgeladen) + - wiki_doku_id: Eindeutige ID für Wiki-Dokumentation (aus Equipment-Name generiert) + - wiki_page_url: Berechnete URL zur Wiki-Seite + - wiki_synced: Status der Synchronisation + - wiki_last_sync: Zeitstempel der letzten Synchronisation + - wiki_auto_sync: Schalter für automatische Synchronisation bei Änderungen + Template-System: + Die Wiki-Seiten werden aus einem Template (werkstatt:ausruestung:c_template) + generiert, das folgende Platzhalter unterstützt: + - {feldname} - Direkte Equipment-Felder (z.B. {name}, {serial_no}) + - {ows_machine_id.feldname} - Maschinenfelder (z.B. {ows_machine_id.power}) + - {wiki_doku_page} - ID der zentralen Dokumentationsseite + - {wiki_doku_link} - DokuWiki-Link zur Dokumentationsseite + - {image} - Bild-Einbindung (wird automatisch hochgeladen) + - {tags} - Komma-separierte Tag-Liste + - {sync_datetime} - Zeitstempel der Synchronisation + Übersichtstabelle: + Generiert eine zentrale Übersichtstabelle aller Equipment mit konfigurierbaren + Spalten. Die Tabelle verwendet das DokuWiki DataTable-Plugin für interaktive + Sortierung und Filterung. Konfiguration über Systemparameter: + - dokuwiki.overview_page_id - Seiten-ID der Übersicht + - dokuwiki.overview_title - Titel der Seite + - dokuwiki.overview_columns - Spaltenüberschriften (pipe-separiert) + - dokuwiki.overview_column_data - Spaltendaten mit Platzhaltern + Verwendung: + 1. Equipment anlegen/bearbeiten in Odoo + 2. Bereich (ows_area_id) setzen (erforderlich für Wiki-Sync) + 3. Optional: Bild hochladen (wird automatisch ins Wiki übertragen) + 4. "Zum Wiki synchronisieren" klicken (oder automatisch bei Änderungen) + 5. Wiki-Seiten werden erstellt/aktualisiert + 6. "Wiki-Seite öffnen" für direkten Browser-Zugriff + Notes: + - Zentrale Dokumentationsseite wird nur beim ersten Sync erstellt + - Bereichsansichten werden bei jedem Sync aktualisiert + - Bilder werden als werkstatt:ausruestung:media:{wiki_doku_id}.jpg gespeichert + - Wiki-Namen werden normalisiert (Umlaute, Sonderzeichen, Kleinschreibung) + - Bei fehlendem Template wird Fallback-Inhalt verwendet + - Übersichtstabelle kann manuell oder automatisch aktualisiert werden + """ _inherit = 'maintenance.equipment' # Bild-Feld @@ -23,7 +80,7 @@ class MaintenanceEquipment(models.Model): wiki_doku_id = fields.Char( string='Wiki Dokumentations-ID', readonly=True, - help='Eindeutige ID für die zentrale Wiki-Dokumentation (generiert aus Equipment-Namen, z.B. "formatkreissaege")' + help='Eindeutige ID für die zentrale Wiki-Dokumentation (generiert aus Equipment-Namen, z.B. "formatkreissaege", und Modell "bosch-abc" -> "formatkreissaege-bosch-abc")' ) wiki_page_url = fields.Char( string='Wiki-Seiten URL', @@ -63,8 +120,8 @@ class MaintenanceEquipment(models.Model): def _get_wiki_doku_id(self): """ - Generiert die Wiki-Dokumentations-ID aus dem Equipment-Namen. - Format: normalisierter_name (z.B. "formatkreissaege", "tischkreissaege") + Generiert die Wiki-Dokumentations-ID aus dem Equipment-Namen und Modell. + Format: normalisierter_name-normalisiertes_modell (z.B. "formatkreissaege-bosch-abc") Returns: str: Wiki-Doku-ID oder False wenn keine ID vorhanden @@ -75,9 +132,13 @@ class MaintenanceEquipment(models.Model): if self.wiki_doku_id: return self.wiki_doku_id - # Generiere aus Equipment-Namen + # Generiere aus Equipment-Namen und Modell if self.name: - return self._normalize_wiki_name(self.name) + normalized_name = self._normalize_wiki_name(self.name) + if self.model: + normalized_model = self._normalize_wiki_name(self.model) + return f"{normalized_name}-{normalized_model}" + return normalized_name return False @@ -103,14 +164,23 @@ class MaintenanceEquipment(models.Model): def _get_wiki_doku_page_id(self): """ Generiert die Wiki-Page-ID für die zentrale Dokumentation. - Format: werkstatt:ausruestung:doku:{wiki_doku_id} + Format: {central_namespace}:{wiki_doku_id} + Der Namespace ist über Systemparameter 'dokuwiki.central_documentation_namespace' konfigurierbar. Returns: str: Page-ID der zentralen Doku """ self.ensure_one() + + # Namespace aus Systemparameter laden + IrConfigParameter = self.env['ir.config_parameter'].sudo() + central_namespace = IrConfigParameter.get_param( + 'dokuwiki.central_documentation_namespace', + default='werkstatt:ausruestung:doku' + ) + wiki_doku_id = self._get_wiki_doku_id() - return f"werkstatt:ausruestung:doku:{wiki_doku_id}" + return f"{central_namespace}:{wiki_doku_id}" def _normalize_wiki_name(self, name): """ @@ -250,6 +320,19 @@ class MaintenanceEquipment(models.Model): 'partner_ref': self.partner_ref or '', } + # Tags hinzufügen (falls vorhanden) + if hasattr(self, 'tag_ids') and self.tag_ids: + # Komma-separierte Liste für Template + values['tags'] = ', '.join(self.tag_ids.mapped('name')) + # DokuWiki Bullet-Liste für Tabellenzellen + values['tags_list'] = ' * ' + '\\\\ * '.join(self.tag_ids.mapped('name')) if self.tag_ids else '' + # Anzahl der Tags + values['tags_count'] = str(len(self.tag_ids)) + else: + values['tags'] = '' + values['tags_list'] = '' + values['tags_count'] = '0' + # ows.machine Felder hinzufügen (falls verknüpft) if self.ows_machine_id: machine = self.ows_machine_id @@ -377,12 +460,12 @@ class MaintenanceEquipment(models.Model): str: Wiki-Markup-Inhalt """ self.ensure_one() + if self.model: + model_part = f" - Modell: {self.model}" + else: + model_part = "" - content = f"""====== {self.name} - Dokumentation ====== - -**Bereich:** {self.ows_area_id.name if self.ows_area_id else 'Nicht zugeordnet'} -**Kategorie:** {self.category_id.name if self.category_id else 'Keine'} -**Seriennummer:** {self.serial_no or 'Keine'} + content = f"""====== {self.name}{model_part} ====== ===== Beschreibung ===== @@ -421,9 +504,11 @@ Hier kann die Dokumentation für {self.name} geschrieben werden. if not self.name: raise UserError("Equipment-Name muss gesetzt sein für Wiki-Synchronisation!") - # wiki_doku_id beim ersten Sync setzen (aus Equipment-Namen generieren) + # wiki_doku_id beim ersten Sync setzen (aus Equipment-Namen und Modell generieren) if not self.wiki_doku_id: - generated_id = self._normalize_wiki_name(self.name) + generated_id = self._get_wiki_doku_id() + if not generated_id: + generated_id = self._normalize_wiki_name(self.name) self.write({'wiki_doku_id': generated_id}) _logger.info(f"Wiki-Doku-ID für {self.name} gesetzt: {generated_id}") @@ -521,7 +606,11 @@ Hier kann die Dokumentation für {self.name} geschrieben werden. result = super().write(vals) # Felder die eine Synchronisation auslösen - sync_fields = {'name', 'serial_no', 'area_id', 'category_id'} + sync_fields = {'name', 'serial_no', 'ows_area_id', 'category_id', 'status_id', + 'model', 'partner_id', 'location', 'note', 'image_1920', 'tag_ids'} + + # Flag ob Übersichtstabelle aktualisiert werden soll + should_update_overview = False if sync_fields & set(vals.keys()): # Nur synchronisieren wenn auto_sync aktiviert und bereits synced @@ -529,6 +618,7 @@ Hier kann die Dokumentation für {self.name} geschrieben werden. if record.wiki_auto_sync and record.wiki_synced: try: record.sync_to_dokuwiki() + should_update_overview = True except Exception as e: _logger.warning(f"Automatische Wiki-Sync fehlgeschlagen: {e}") # Nicht abbrechen, nur loggen @@ -536,6 +626,21 @@ Hier kann die Dokumentation für {self.name} geschrieben werden. # Sync-Status zurücksetzen record.write({'wiki_synced': False}) + # Optional: Übersichtstabelle aktualisieren + if should_update_overview: + IrConfigParameter = self.env['ir.config_parameter'].sudo() + auto_update_overview = IrConfigParameter.get_param( + 'dokuwiki.auto_update_overview_table', + default='False' + ) + + if auto_update_overview.lower() == 'true': + try: + self.env['maintenance.equipment'].action_sync_overview_table() + _logger.info("Übersichtstabelle automatisch aktualisiert") + except Exception as e: + _logger.warning(f"Automatische Übersichtstabellen-Sync fehlgeschlagen: {e}") + return result # ========================================== diff --git a/open_workshop_dokuwiki/models/maintenance_equipment_status.py b/open_workshop_dokuwiki/models/maintenance_equipment_status.py index 96e933f..e158e34 100644 --- a/open_workshop_dokuwiki/models/maintenance_equipment_status.py +++ b/open_workshop_dokuwiki/models/maintenance_equipment_status.py @@ -3,6 +3,22 @@ from odoo import fields, models class MaintenanceEquipmentStatus(models.Model): + """ + Extension of the maintenance.equipment.status model to add DokuWiki smiley support. + + This class extends the standard Odoo maintenance equipment status model to include + a smiley field that can be used for DokuWiki integration. The smiley field allows + administrators to associate DokuWiki emoticon syntax with each maintenance equipment + status, enabling visual representation of equipment status in DokuWiki documentation. + + The smiley field accepts DokuWiki emoticon syntax (e.g., ':-)', ':-(', ':-D', etc.) + which can be used to display appropriate emoticons when exporting or displaying + equipment status information in DokuWiki format. + + This extension is particularly useful for workshops or maintenance departments that + use DokuWiki as their documentation platform and want to have a visual representation + of equipment status alongside textual information. + """ _inherit = 'maintenance.equipment.status' smiley = fields.Char( diff --git a/open_workshop_dokuwiki/models/res_config_settings.py b/open_workshop_dokuwiki/models/res_config_settings.py index 2c3752c..cdeab1d 100644 --- a/open_workshop_dokuwiki/models/res_config_settings.py +++ b/open_workshop_dokuwiki/models/res_config_settings.py @@ -30,10 +30,12 @@ class ResConfigSettings(models.TransientModel): 'dokuwiki.url': 'https://wiki.hobbyhimmel.de', 'dokuwiki.user': 'odoo.odoo', 'dokuwiki.password': 'CHANGE_ME', + 'dokuwiki.central_documentation_namespace': 'werkstatt:ausruestung:doku', 'dokuwiki.overview_page_id': 'werkstatt:ausruestung:start', 'dokuwiki.overview_title': 'Geräte & Maschinen - Übersicht', 'dokuwiki.overview_columns': 'Name|Zustand|Sicherheit|Bereich|Standort|Bild', 'dokuwiki.overview_column_data': '[[{wiki_page_id}|{name}]]|{status_smiley}|{ows_machine_id.category_icon}|{ows_area}|{location}|{image}', + 'dokuwiki.auto_update_overview_table': 'False', # Automatische Übersichtstabellen-Aktualisierung bei Equipment-Änderungen } # Nur fehlende Parameter anlegen