kundenkarte/CLAUDE.md
data 65f24495e6 docs: Changelog v8.5/v8.6 und CLAUDE.md aktualisiert
- ChangeLog: v8.5 (Werkzeuge, Zubehör, Ausgebaut) und v8.6 (has_product, Decommissioned-Default, Select2-Fix)
- CLAUDE.md: Neue Abschnitte für Ausgebaut-Status, Mein Betrieb, Select2-Kategorie-Filter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 21:23:48 +01:00

11 KiB

CLAUDE_CODE_DISABLE_AUTO_MEMORY=0

KundenKarte Module - Entwicklungshinweise

Dolibarr App Navigation (Vor/Zurück Pfeile)

Problem

Die Dolibarr Mobile App hat eigene Navigations-Pfeile (vorheriger/nächster Kunde), die zwischen Datensätzen navigieren. Diese verwenden andere Parameter als unsere Module erwarten:

  • Kunden-Navigation: Dolibarr verwendet socid, Module erwarten oft id
  • Kontakt-Navigation: Dolibarr verwendet contactid, Module erwarten oft id

Wenn man diese Pfeile auf einem Modul-Tab verwendet, verliert das Modul die ID und zeigt einen Fehler oder leere Seite.

Lösung: Beide Parameter akzeptieren

In JEDEM Tab-PHP-File muss am Anfang beide Parameter akzeptiert werden:

Für Kunden-Tabs (thirdparty):

// Get parameters
// Support both 'id' and 'socid' for compatibility with Dolibarr's customer navigation arrows
$id = GETPOSTINT('id');
if ($id <= 0) {
    $id = GETPOSTINT('socid');
}

Für Kontakt-Tabs (contact):

// Get parameters
// Support both 'id' and 'contactid' for compatibility with Dolibarr's contact navigation arrows
$id = GETPOSTINT('id');
if ($id <= 0) {
    $id = GETPOSTINT('contactid');
}

Betroffene Dateien in diesem Modul

  • tabs/anlagen.php - Kunden-Anlagen (socid)
  • tabs/favoriteproducts.php - Kunden-Favoriten (socid)
  • tabs/contact_anlagen.php - Kontakt-Anlagen (contactid)
  • tabs/contact_favoriteproducts.php - Kontakt-Favoriten (contactid)

Best Practices für zukünftige Module

  1. IMMER beide Parameter akzeptieren - id UND socid/contactid
  2. Tab-Definition in modXxx.class.php verwendet ?id=__ID__ - das ist korrekt
  3. Dolibarr's dol_banner_tab() generiert die Navigationspfeile mit socid/contactid
  4. Fallback bei fehlender ID - zur Liste weiterleiten, nicht Fehler zeigen:
if ($id <= 0) {
    header('Location: '.DOL_URL_ROOT.'/societe/list.php');
    exit;
}

Mobile Ansicht - Einheitliche Button-Größen

Problem

Auf mobilen Geräten haben die Buttons (Kompakt, Aufklappen, Einklappen, PDF Export) unterschiedliche Größen.

Lösung

CSS Media Queries für einheitliche Button-Größen:

@media (max-width: 768px) {
    .kundenkarte-tree-controls {
        justify-content: center !important;
        flex-wrap: wrap !important;
        gap: 8px !important;
    }

    .kundenkarte-tree-controls .button {
        flex: 1 1 auto !important;
        min-width: 80px !important;
        max-width: 150px !important;
        padding: 10px 8px !important;
        font-size: 12px !important;
        text-align: center !important;
    }
}

@media (max-width: 480px) {
    /* 2x2 Grid auf sehr kleinen Bildschirmen */
    .kundenkarte-tree-controls {
        display: grid !important;
        grid-template-columns: 1fr 1fr !important;
    }
}

Migrationen

Alle Datenbankänderungen werden als idempotente Migrationen in modKundenKarte.class.php implementiert:

  • runMigrations() wird bei jeder Modulaktivierung aufgerufen
  • Jede Migration prüft zuerst, ob die Änderung bereits existiert
  • Später werden Migrationen entfernt und Tabellen direkt korrekt erstellt

Dateistruktur

  • tabs/anlagen.php - Hauptansicht für Anlagen auf Kundenebene
  • tabs/contact_anlagen.php - Anlagen für Kontakte
  • tabs/favoriteproducts.php - Lieblingsprodukte auf Kundenebene
  • tabs/contact_favoriteproducts.php - Lieblingsprodukte für Kontakte
  • admin/anlage_types.php - Verwaltung der Element-Typen
  • ajax/ - AJAX-Endpunkte für dynamische Funktionen
  • js/kundenkarte.js - Alle JavaScript-Komponenten
  • css/kundenkarte.css - Alle Styles (Dark Mode)

Wichtige Hinweise

FontAwesome Icons

  • Dolibarr verwendet FontAwesome 4.x Format: fa fa-icon-name
  • NICHT: fas fa-icon-name oder far fa-icon-name

Badge-Farben

  • Können pro Feld in Admin > Element-Typen konfiguriert werden
  • Spalte badge_color in llx_kundenkarte_anlage_type_field
  • Hex-Format: #RRGGBB

Datei-Vorschau Tooltip

  • AJAX-Endpoint: ajax/file_preview.php
  • Zeigt Thumbnails für Bilder, Icons für Dokumente
  • Hover über Datei-Badge im Baum

PWA Mobile App

Übersicht

Offline-fähige Progressive Web App für Elektriker zur Schaltschrank-Dokumentation vor Ort.

Dateien

  • pwa.php - Haupteinstieg (HTML/CSS/JS Container, lädt jQuery aus Dolibarr)
  • pwa_auth.php - Token-basierte Authentifizierung (15 Tage gültig)
  • ajax/pwa_api.php - Alle AJAX-Endpoints für die PWA
  • js/pwa.js - Komplette App-Logik (jQuery, als IIFE mit jQuery-Parameter)
  • css/pwa.css - Mobile-First Design, Dolibarr Dark Theme Variablen
  • sw.js - Service Worker für Offline-Cache (v6.1)
  • manifest.json - Web App Manifest für Installation

Workflow

  1. Login mit Dolibarr-Credentials → Token wird lokal gespeichert
  2. Kunde suchen → Anlagen werden gecached
  3. Kontakt-Adressen (Gebäude/Standorte) aufklappen → Anlagen pro Adresse
  4. Anlage mit Schaltplan-Editor auswählen → Daten werden gecached
  5. Offline arbeiten: Hutschienen, Automaten hinzufügen
  6. Änderungen werden in lokaler Queue gespeichert
  7. Bei Internetverbindung: Automatische Synchronisierung

Design-System

  • CSS-Variablen basierend auf Dolibarr Dark Theme (--colorbackbody, --colortext, etc.)
  • Theme-Farbe --primary wird dynamisch aus Dolibarr-Config geladen (THEME_ELDY_TOPMENU_BACK1)
  • Buttons: --butactionbg (goldbraun) statt blau
  • Header: sticky, primary-Farbe

Kontakt-Adressen

  • get_anlagen API liefert anlagen (Kunden-Ebene) + contacts (Adressen)
  • Kontakt-Gruppen (Gebäude/Standorte) werden OBEN als vertikale Liste dargestellt
  • Chevron-Pfeil zeigt Aufklapp-Status, Anlagen werden bei Klick geladen
  • Kunden-Anlagen darunter mit Kunden-Adresse als Trennlabel
  • get_contact_anlagen API lädt Anlagen pro Kontakt-Adresse bei Bedarf
  • Layout: Alles untereinander (Handy-optimiert), keine Grid-Spalten

Schaltplan-Editor

  • Equipment-Blöcke als CSS Grid (grid-template-columns: repeat(totalTE, 1fr))
  • Blöcke positioniert per grid-column basierend auf position_te und width_te
  • Equipment-Blöcke: 80px Höhe, Sicherungsautomat-Optik mit Border und Schatten
  • block_label und block_color aus Backend (wie Website)
  • Abgang-Labels (Outputs) werden über/unter den Automaten angezeigt
  • Connections mit fk_target IS NULL = Ausgänge/Abgänge
  • Intelligente Positionsberechnung mit Lücken-Erkennung (getMaxGap)
  • +-Button disabled wenn Hutschiene voll, Typ-Buttons gefiltert nach verfügbarer Breite
  • Hutschiene zeigt belegt/gesamt TE

Navigation & State

  • Browser-History Support (hardware Zurück-Button funktioniert)
  • Session-State wird in sessionStorage gespeichert (Screen, Kunde, Anlage)
  • Bei Seiten-Refresh wird letzter Zustand wiederhergestellt
  • Popstate-Handler: Lädt Anlagen-Daten nach falls Liste leer (z.B. nach Refresh→Back)
  • Sync-Button lädt jetzt erst Offline-Queue, dann Daten neu

Anlagen-Übersicht

  • Anlagen-Cards: Horizontales Layout (Icon links, Titel rechts), volle Breite
  • Einspaltiges vertikales Layout - optimiert fürs Handy

Token-Authentifizierung

  • Tokens enthalten: user_id, login, created, expires, hash
  • Hash = MD5(user_id + login + MAIN_SECURITY_SALT)
  • Gültigkeit: 15 Tage
  • Gespeichert in localStorage
  • $user->getrights() wird nach Token-Validierung aufgerufen

Offline-Sync

  • Alle Änderungen werden in offlineQueue (localStorage) gespeichert
  • Badge zeigt Anzahl ungesyncte Änderungen
  • Sync-Button oder automatisch bei Online-Event
  • Bei Sync werden Aktionen der Reihe nach ausgeführt

Installation auf Smartphone

  1. PWA im Browser öffnen: https://domain/dolibarr/custom/kundenkarte/pwa.php
  2. Browser-Menü → "Zum Startbildschirm hinzufügen"
  3. App öffnet sich als Standalone ohne Browser-UI

FI/RCD-Schutzgruppen (v7.5)

  • Equipment kann einem Schutzgerät (FI/RCD) zugeordnet werden
  • fk_protection in llx_kundenkarte_equipment speichert die ID des schützenden Equipment
  • Im Editor: Farbige Ränder zeigen Schutzgruppen-Zugehörigkeit
  • get_protection_devices API liefert verfügbare Schutzgeräte für Dropdown

Gebündelte Terminals (v7.5)

  • Multi-Phasen-Abgänge für Drehstrom-Verbraucher (E-Herd, DLE)
  • bundled_terminals = 'all' in Connection bedeutet: Alle Terminals belegt
  • Im Editor: Ein Pfeil spannt über alle Terminals des Equipment
  • Label wird zentriert über alle Terminals angezeigt
  • Checkbox "Alle bündeln" nur bei Equipment mit >1 Terminal sichtbar

Terminal-Konfiguration (v7.5)

  • terminals_config JSON im Equipment-Typ definiert Terminal-Positionen
  • Format: {"terminals":[{"pos":"top"},{"pos":"top"},{"pos":"bottom"}...]}
  • getTerminalCount(type, position, fallback) zählt Terminals pro Position
  • Ermöglicht: 4 TE Breite aber nur 3 Terminals (z.B. Neozed 3F)

Grid-Layout (5 Zeilen)

  • Zeile 1: Abgang-Labels oben (terminal-label-cell.label-row-top)
  • Zeile 2: Terminal-Punkte oben (terminal-point.terminal-row-top)
  • Zeile 3: Equipment-Blöcke
  • Zeile 4: Terminal-Punkte unten (terminal-point.terminal-row-bottom)
  • Zeile 5: Abgang-Labels unten (terminal-label-cell.label-row-bottom)

Ausgebaut-Status (v8.0)

Spalten

  • decommissioned (tinyint DEFAULT 0) in llx_kundenkarte_anlage
  • date_decommissioned (date NULL) in llx_kundenkarte_anlage

Verhalten

  • Toggle per Button am Element im Baum und Graph
  • Ausgebaute Elemente: opacity: 0.4, dashed border, Badge "Ausgebaut"
  • Toggle-Button in Toolbar: Klasse .show-decommissioned auf .kundenkarte-tree
  • Admin-Setting KUNDENKARTE_SHOW_DECOMMISSIONED für Standard-Sichtbarkeit
  • Graph-View: Nodes mit Klasse .decommissioned (35% opacity, dashed border)

Mein Betrieb / Werkzeuge (v8.5)

Übersicht

Eigene Seite für Firmen-Equipment (Werkzeuge, Maschinen, Messgeräte).

Dateien

  • werkzeuge.php - Baumansicht für eigene Firma (fk_soc = mysoc->id)
  • class/anlageaccessory.class.php - Zubehör-Klasse mit CRUD + Bestellfunktion
  • ajax/anlage_accessory.php - AJAX-Endpunkte für Zubehör

System

  • Neues System WERKZEUG (ID 26) in llx_c_kundenkarte_anlage_system
  • Menüpunkt unter KundenKarte > Mein Betrieb
  • System-Filter fix auf "WERKZEUG"

Produkt-Zuordnung

  • fk_product in llx_kundenkarte_anlage verknüpft mit Dolibarr-Produkt
  • Autocomplete-Suche via ajax/equipment.php?action=get_products
  • Anzeige: Ref + Label + Preis unter Element im Baum
  • Typ-Flag has_product: Steuert ob Produkt-Zeile im Formular sichtbar ist
  • data-has-product Attribut auf <option> für JS-Steuerung

Zubehör-System

  • Tabelle llx_kundenkarte_anlage_accessory (fk_anlage, fk_product, qty, rang, note)
  • Typ-Flag has_accessories steuert Verfügbarkeit
  • Lieferantenbestellung via CommandeFournisseur generierbar

Select2 mit Kategorie-Filter

Problem & Lösung

In anlagen.php und contact_anlagen.php gibt es einen Kategorie-Filter (Gebäude/Element), der die Typ-Options per JS filtert und Select2 neu initialisiert.

Wichtig: Nach initSelect2() muss der Wert mit .trigger("change") gesetzt werden, damit Select2 den aktuellen Wert korrekt anzeigt:

initSelect2();
if (currentVal && $typeSelect.find('option[value="' + currentVal + '"]').length) {
    $typeSelect.val(currentVal).trigger("change");
}

Ablauf in filterTypes()

  1. currentVal sichern
  2. HTML aus allOptionsHtml zurücksetzen
  3. Nicht passende Options entfernen
  4. Select2 initialisieren
  5. Wert mit .trigger("change") wiederherstellen