# SubtotalTitle - Dolibarr Modul Erweitert Rechnungen, Angebote und Kundenaufträge um **Sections**, **Textzeilen** und **Zwischensummen**. **Version:** 4.2 **Autor:** Eduard Wisch **Lizenz:** GPL v3+ --- ## Features - **Sections (Produktgruppen)**: Produkte in logische Gruppen organisieren - **Textzeilen**: Freie Texte ohne Preis einfügen - **Zwischensummen**: Automatische Berechnung pro Section - **Drag & Drop**: Sortierung per Drag & Drop - **Dokument-Synchronisation**: Elemente zum PDF hinzufügen/entfernen - **Import-Funktion**: Sections von Angebot zu Auftrag zu Rechnung übernehmen - **ODT-Variablen**: Bedingte Formatierung in ODT-Templates --- ## Unterstützte Dokumenttypen | Dokumenttyp | Tabelle | Status | |-------------|---------|--------| | Rechnungen (Factures) | llx_facturedet | Vollständig | | Angebote (Propals) | llx_propaldet | Vollständig | | Kundenaufträge (Commandes) | llx_commandedet | Vollständig | --- ## Modul-Funktionen ### Sections (Überschriften) - Erstellen von Überschriften zur Strukturierung - Produkte können per Drag & Drop oder Link-Button zugeordnet werden - Optional: Zwischensumme für jede Section anzeigen - Ein-/Ausklappen von Sections ### Textzeilen - Freie Textzeilen ohne Preis - Ideal für Hinweise, Bedingungen oder Erklärungen ### Zwischensummen - Automatische Berechnung der Summe aller Produkte in einer Section - Checkbox zum Ein-/Ausschalten pro Section - Duplikat-Schutz verhindert doppelte Subtotals ### Dokument-Synchronisation - **Checkbox** bei jeder Section/Textzeile/Subtotal: Element zum Dokument hinzufügen - **Zum Dokument / Aus Dokument** Buttons: Alle Elemente auf einmal synchronisieren - **Grüner Rand** = Element ist im Dokument/PDF enthalten ### Import-Funktion (NEU in v4.1) - Sections und Textzeilen werden von Ursprungsdokument importiert - Produkte werden automatisch den passenden Sections zugeordnet (via fk_product) - Unterstützt: Angebot → Auftrag → Rechnung - Button "Import von [Ursprungsdokument]" mit Bestätigungsdialog --- ## Installation ### 1. Dateien kopieren ``` htdocs/custom/subtotaltitle/ ├── class/ │ ├── actions_subtotaltitle.class.php │ └── DocumentTypeHelper.class.php ├── ajax/ │ ├── add_to_section.php │ ├── assign_last_product.php │ ├── check_subtotal.php │ ├── cleanup_subtotals.php │ ├── create_section.php │ ├── create_textline.php │ ├── delete_section.php │ ├── delete_textline.php │ ├── edit_textline.php │ ├── fix_section_hierarchy.php │ ├── fix_sections.php │ ├── get_line_orders.php │ ├── get_sections.php │ ├── get_textlines.php │ ├── import_from_origin.php # NEU in v4.1 │ ├── mass_delete.php │ ├── move_product.php │ ├── move_section.php │ ├── remove_from_section.php │ ├── rename_section.php │ ├── reorder_all.php │ ├── reorder_invoice.php │ ├── repair_missing_subtotals.php │ ├── sync_to_facturedet.php │ └── toggle_subtotal.php ├── core/ │ ├── modules/ │ │ └── modSubtotalTitle.class.php │ └── substitutions/ │ └── functions_subtotaltitle.lib.php ├── js/ │ └── subtotaltitle.js ├── css/ │ └── subtotaltitle.css ├── lib/ │ └── subtotaltitle.lib.php └── sql/ └── llx_facture_lines_manager.sql ``` ### 2. Modul aktivieren Im Dolibarr Backend unter **Home → Setup → Modules** das Modul **SubtotalTitle** aktivieren. Die Datenbanktabelle `llx_facture_lines_manager` wird automatisch erstellt. --- ## Datenbank ### Tabelle: llx_facture_lines_manager | Feld | Typ | Beschreibung | |------|-----|--------------| | rowid | INT | Primary Key | | fk_facture | INT | FK zu Rechnung | | fk_propal | INT | FK zu Angebot | | fk_commande | INT | FK zu Kundenauftrag | | document_type | VARCHAR(20) | 'invoice', 'propal', 'order' | | line_type | VARCHAR(20) | 'section', 'product', 'text', 'subtotal' | | fk_facturedet | INT | FK zu llx_facturedet | | fk_propaldet | INT | FK zu llx_propaldet | | fk_commandedet | INT | FK zu llx_commandedet | | title | VARCHAR(255) | Titel für Sections/Text | | parent_section | INT | FK zur übergeordneten Section | | line_order | INT | Sortierreihenfolge | | show_subtotal | TINYINT | Zwischensumme anzeigen (0/1) | | collapsed | TINYINT | Section eingeklappt (0/1) | | in_facturedet | TINYINT | Im Dokument enthalten (0/1) | --- ## ODT Template Schlüsselwörter ### Zeilen-Variablen (pro Zeile in row.lines) | Variable | Wert | Beschreibung | |----------|------|--------------| | `{line_is_section}` | 1/"" | Zeile ist eine Section (Überschrift) | | `{line_is_textline}` | 1/"" | Zeile ist eine Textzeile | | `{line_is_subtotal}` | 1/"" | Zeile ist eine Zwischensumme | | `{line_is_product}` | 1/"" | Zeile ist ein Produkt mit Produktreferenz | | `{line_is_free_line}` | 1/"" | Zeile ist eine freie Zeile (ohne Produktreferenz) | | `{line_is_normal}` | 1/"" | Zeile ist normal (special_code = 0) | | `{line_is_special}` | 1/"" | Zeile ist Section, Text ODER Subtotal | | `{line_special_code}` | 0-102 | special_code Wert der Zeile | ### Globale Variablen (für das gesamte Dokument) | Variable | Wert | Beschreibung | |----------|------|--------------| | `{object_has_sections}` | 1/"" | Dokument enthält mindestens eine Section | | `{object_has_textlines}` | 1/"" | Dokument enthält mindestens eine Textzeile | | `{object_has_speciallines}` | 1/"" | Dokument enthält Sections, Textzeilen oder Subtotals | | `{object_count_sections}` | Zahl | Anzahl der Sections im Dokument | | `{object_count_textlines}` | Zahl | Anzahl der Textzeilen im Dokument | | `{object_count_subtotals}` | Zahl | Anzahl der Zwischensummen im Dokument | ### special_code Werte | Typ | special_code | |-----|-------------| | Normales Produkt | 0 | | Section (Überschrift) | 100 | | Textzeile | 101 | | Zwischensumme | 102 | ### ODT Template Beispiel ``` [!-- IF {object_has_sections} --] Dieses Dokument enthält {object_count_sections} Section(s). [!-- ENDIF {object_has_sections} --] [!-- BEGIN row.lines --] [!-- IF {line_is_section} --] ═══════════════════════════════════════ {line_desc} ═══════════════════════════════════════ [!-- ENDIF {line_is_section} --] [!-- IF {line_is_textline} --] {line_desc} [!-- ENDIF {line_is_textline} --] [!-- IF {line_is_product} --] {line_pos} {line_qty} {line_ref} {line_desc} {line_up_locale} € {line_price_ht_locale} € [!-- ENDIF {line_is_product} --] [!-- IF {line_is_free_line} --] {line_pos} {line_qty} {line_desc} {line_up_locale} € {line_price_ht_locale} € [!-- ENDIF {line_is_free_line} --] [!-- IF {line_is_subtotal} --] ─────────────────────────────────────── Zwischensumme: {line_price_ht_locale} € ─────────────────────────────────────── [!-- ENDIF {line_is_subtotal} --] [!-- END row.lines --] ``` --- ## Anforderungen - Dolibarr >= 16.0 - PHP >= 7.4 - MySQL >= 5.7 / MariaDB >= 10.3 / PostgreSQL >= 12 --- ## Changelog Siehe [ChangeLog.md](ChangeLog.md) für die vollständige Versionshistorie. ### Aktuelle Version (4.2) - Datenbank-Kompatibilität für PostgreSQL verbessert - Duplikat-Schutz für Subtotals - SQL-Injection-Schutz verbessert --- ## Lizenz Copyright (C) 2026 Eduard Wisch Dieses Programm ist freie Software: Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder Version 3 der Lizenz oder (nach Ihrer Wahl) jede spätere Version.