Version 4.2: PostgreSQL-Kompatibilität, GlobalNotify, Dokumentation
- fix: DELETE mit JOIN durch Subquery ersetzt (PostgreSQL-kompatibel) - feat: GlobalNotify Integration für Fehler-Benachrichtigungen - feat: subtotaltitle_notify() Helper-Funktion - docs: ChangeLog.md komplett überarbeitet (alle Versionen) - docs: README.md aktualisiert mit allen Features und Dateistruktur Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
9a8f5431e1
commit
27481bab31
7 changed files with 297 additions and 127 deletions
73
ChangeLog.md
73
ChangeLog.md
|
|
@ -1,10 +1,73 @@
|
||||||
# CHANGELOG MODULE SUBTOTALTITLE FOR [DOLIBARR ERP CRM](https://www.dolibarr.org)
|
# CHANGELOG MODULE SUBTOTALTITLE FOR [DOLIBARR ERP CRM](https://www.dolibarr.org)
|
||||||
|
|
||||||
## 1.1
|
Alle wichtigen Änderungen werden hier dokumentiert.
|
||||||
|
|
||||||
- **Zwischensumme bei Section-Löschung mitlöschen**: Wenn eine Produktgruppe über Dolibarrs Standard-Löschbutton (confirm_deleteline) gelöscht wird, werden zugehörige Zwischensummen automatisch aus facturedet und facture_lines_manager mitgelöscht
|
Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/),
|
||||||
- **Verwaiste Subtotals aufräumen**: Nach jeder Zeilenlöschung werden verwaiste Zwischensummen (parent_section zeigt auf nicht-existierende Section) automatisch bereinigt
|
und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||||
|
|
||||||
## 1.0
|
## [4.2] - 2026-03-03
|
||||||
|
|
||||||
Initial version
|
### Fixed
|
||||||
|
- **Datenbank-Kompatibilität**: DELETE mit JOIN durch Subquery ersetzt für PostgreSQL-Kompatibilität
|
||||||
|
- **Duplikat-Schutz für Subtotals**: Prüfung in Detail-Tabelle UND Manager-Tabelle vor dem Erstellen
|
||||||
|
- **SQL-Injection-Schutz**: `addslashes()` durch `$db->escape()` ersetzt
|
||||||
|
- **Präzisere Duplikat-Erkennung**: LIKE durch exakten Match ersetzt
|
||||||
|
|
||||||
|
## [4.1] - 2026-03-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Import-Funktion für Produktgruppen**: Sections, Textzeilen und Subtotals können von Angebot zu Auftrag und von Auftrag zu Rechnung importiert werden
|
||||||
|
- **Automatisches Produkt-Mapping**: Produkte werden anhand der `fk_product` den passenden Sections zugeordnet
|
||||||
|
- **Import-Button in GUI**: Neuer Button "Import von [Ursprungsdokument]" mit Bestätigungsdialog
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Rang-Synchronisation**: `rang` in Dolibarr-Tabelle und `line_order` in Manager-Tabelle werden beim Import synchronisiert
|
||||||
|
|
||||||
|
## [4.0] - 2026-02-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Multi-Dokument-Support**: Vollständige Unterstützung für Rechnungen, Angebote UND Kundenaufträge
|
||||||
|
- **DocumentTypeHelper-Klasse**: Zentrale Verwaltung der Tabellennamen pro Dokumenttyp
|
||||||
|
- **Einheitliche API**: Alle AJAX-Endpunkte unterstützen `document_type` Parameter
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Datenbank-Schema erweitert**: `fk_propal`, `fk_commande`, `fk_propaldet`, `fk_commandedet` hinzugefügt
|
||||||
|
- **Hooks erweitert**: `propalcard` und `ordercard` zum Hook-Array hinzugefügt
|
||||||
|
|
||||||
|
## [3.0] - 2026-02-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Dokument-Synchronisation**: "Zum Dokument" / "Aus Dokument" Buttons für Batch-Sync
|
||||||
|
- **In-Dokument-Checkbox**: Einzelne Elemente können zum PDF hinzugefügt/entfernt werden
|
||||||
|
- **Grüner Rand**: Visuelle Kennzeichnung für im Dokument enthaltene Elemente
|
||||||
|
- **ODT-Substitutionsvariablen**: `line_is_section`, `line_is_textline`, `line_is_subtotal`, etc.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **special_code Werte**: 100=Section, 101=Text, 102=Subtotal
|
||||||
|
|
||||||
|
## [2.0] - 2026-02-20
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Drag & Drop Sortierung**: Sections und Produkte können per Drag & Drop sortiert werden
|
||||||
|
- **Link-Button**: Produkte können über Button einer Section zugeordnet werden
|
||||||
|
- **Collapse/Expand**: Sections können ein-/ausgeklappt werden
|
||||||
|
- **Verwaiste Zeilen Button**: Button zum Entfernen verwaister Manager-Einträge
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Hardcodierte Pfade**: Relative Pfade statt absoluter Pfade
|
||||||
|
|
||||||
|
## [1.1] - 2026-02-15
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Zwischensumme bei Section-Löschung**: Zugehörige Subtotals werden beim Löschen einer Section mitgelöscht
|
||||||
|
- **Verwaiste Subtotals aufräumen**: Automatische Bereinigung nach jeder Zeilenlöschung
|
||||||
|
|
||||||
|
## [1.0] - 2026-02-01
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Initiale Version
|
||||||
|
- **Sections (Überschriften)**: Produkte in Gruppen organisieren
|
||||||
|
- **Textzeilen**: Freie Texte ohne Preis einfügen
|
||||||
|
- **Zwischensummen**: Automatische Berechnung pro Section
|
||||||
|
- **Manager-Tabelle**: `llx_facture_lines_manager` für Strukturverwaltung
|
||||||
|
- Nur Rechnungen-Support (facturedet)
|
||||||
|
|
|
||||||
264
README.md
264
README.md
|
|
@ -2,9 +2,147 @@
|
||||||
|
|
||||||
Erweitert Rechnungen, Angebote und Kundenaufträge um **Sections**, **Textzeilen** und **Zwischensummen**.
|
Erweitert Rechnungen, Angebote und Kundenaufträge um **Sections**, **Textzeilen** und **Zwischensummen**.
|
||||||
|
|
||||||
|
**Version:** 4.2
|
||||||
|
**Autor:** Eduard Wisch <data@data-it-solution.de>
|
||||||
|
**Lizenz:** GPL v3+
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔑 ODT Template Schlüsselwörter
|
## 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)
|
### Zeilen-Variablen (pro Zeile in row.lines)
|
||||||
|
|
||||||
|
|
@ -77,128 +215,26 @@ Zwischensumme: {line_price_ht_locale} €
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📋 Modul-Funktionen
|
## Anforderungen
|
||||||
|
|
||||||
### Sections (Überschriften)
|
- Dolibarr >= 16.0
|
||||||
- Erstellen von Überschriften zur Strukturierung
|
- PHP >= 7.4
|
||||||
- Produkte können per Drag & Drop oder Link-Button zugeordnet werden
|
- MySQL >= 5.7 / MariaDB >= 10.3 / PostgreSQL >= 12
|
||||||
- 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
|
|
||||||
|
|
||||||
### 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
|
|
||||||
- Buttons werden nur angezeigt wenn Sections oder Textzeilen vorhanden sind
|
|
||||||
|
|
||||||
### Unterstützte Dokumenttypen
|
|
||||||
- Rechnungen (Factures)
|
|
||||||
- Angebote (Propals)
|
|
||||||
- Kundenaufträge (Commandes)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 Installation
|
## Changelog
|
||||||
|
|
||||||
### 1. Dateien kopieren
|
Siehe [ChangeLog.md](ChangeLog.md) für die vollständige Versionshistorie.
|
||||||
|
|
||||||
```
|
### Aktuelle Version (4.2)
|
||||||
htdocs/custom/subtotaltitle/
|
- Datenbank-Kompatibilität für PostgreSQL verbessert
|
||||||
├── class/
|
- Duplikat-Schutz für Subtotals
|
||||||
│ ├── actions_subtotaltitle.class.php
|
- SQL-Injection-Schutz verbessert
|
||||||
│ └── DocumentTypeHelper.class.php
|
|
||||||
├── ajax/
|
|
||||||
│ ├── add_to_section.php
|
|
||||||
│ ├── assign_last_product.php
|
|
||||||
│ ├── cleanup_subtotals.php
|
|
||||||
│ ├── create_section.php
|
|
||||||
│ ├── create_textline.php
|
|
||||||
│ ├── get_textlines.php
|
|
||||||
│ ├── move_section.php
|
|
||||||
│ ├── reorder_all.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.
|
|
||||||
|
|
||||||
### 3. Modul-Konfiguration
|
|
||||||
|
|
||||||
In `core/modules/modSubtotalTitle.class.php` muss folgendes gesetzt sein:
|
|
||||||
|
|
||||||
```php
|
|
||||||
$this->module_parts = array(
|
|
||||||
'substitutions' => 1, // Für ODT-Variablen
|
|
||||||
'hooks' => array(
|
|
||||||
'data' => array('invoicecard', 'propalcard', 'ordercard'),
|
|
||||||
'entity' => '0'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🗄️ Datenbank
|
## Lizenz
|
||||||
|
|
||||||
### 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) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 Changelog
|
|
||||||
|
|
||||||
### Version 1.0
|
|
||||||
- Initiale Version mit Section-, Text- und Subtotal-Unterstützung
|
|
||||||
- ODT-Substitutionsvariablen
|
|
||||||
- Multi-Dokument-Support (Rechnungen, Angebote, Kundenaufträge)
|
|
||||||
- Drag & Drop Sortierung
|
|
||||||
- Dokument-Synchronisation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 Lizenz
|
|
||||||
|
|
||||||
Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -557,6 +557,14 @@ if ($action == 'check') {
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$db->rollback();
|
$db->rollback();
|
||||||
subtotaltitle_debug_log('❌ Import fehlgeschlagen: '.$e->getMessage());
|
subtotaltitle_debug_log('❌ Import fehlgeschlagen: '.$e->getMessage());
|
||||||
|
|
||||||
|
// Benachrichtigung über GlobalNotify (falls verfügbar)
|
||||||
|
subtotaltitle_notify(
|
||||||
|
'error',
|
||||||
|
'Import fehlgeschlagen',
|
||||||
|
'Produktgruppen-Import von '.$origin['type'].' #'.$origin['id'].' nach '.$target_type.' #'.$target_id.' fehlgeschlagen: '.$e->getMessage()
|
||||||
|
);
|
||||||
|
|
||||||
echo json_encode(array('success' => false, 'error' => $e->getMessage()));
|
echo json_encode(array('success' => false, 'error' => $e->getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,13 @@ if ($action == 'add') {
|
||||||
subtotaltitle_debug_log('📝 SQL: '.$sql_ins);
|
subtotaltitle_debug_log('📝 SQL: '.$sql_ins);
|
||||||
|
|
||||||
if (!$db->query($sql_ins)) {
|
if (!$db->query($sql_ins)) {
|
||||||
echo json_encode(array('success' => false, 'error' => $db->lasterror()));
|
$error_msg = $db->lasterror();
|
||||||
|
subtotaltitle_notify(
|
||||||
|
'error',
|
||||||
|
'Sync fehlgeschlagen',
|
||||||
|
'Fehler beim Hinzufügen zu '.$tables['lines_table'].': '.$error_msg
|
||||||
|
);
|
||||||
|
echo json_encode(array('success' => false, 'error' => $error_msg));
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1271,12 +1271,14 @@ class ActionsSubtotalTitle extends CommonHookActions
|
||||||
$tables = DocumentTypeHelper::getTableNames($docType);
|
$tables = DocumentTypeHelper::getTableNames($docType);
|
||||||
if (!$tables) return;
|
if (!$tables) return;
|
||||||
|
|
||||||
// 1. CLEANUP: Lösche verwaiste Einträge
|
// 1. CLEANUP: Lösche verwaiste Einträge (Produkte deren Detail-Zeile nicht mehr existiert)
|
||||||
$sql_cleanup = "DELETE m FROM ".MAIN_DB_PREFIX."facture_lines_manager m";
|
// Subquery-basiert für Kompatibilität mit MySQL, PostgreSQL und anderen Datenbanken
|
||||||
$sql_cleanup .= " LEFT JOIN ".MAIN_DB_PREFIX.$tables['lines_table']." d ON m.".$tables['fk_line']." = d.rowid";
|
$sql_cleanup = "DELETE FROM ".MAIN_DB_PREFIX."facture_lines_manager";
|
||||||
$sql_cleanup .= " WHERE m.".$tables['fk_parent']." = ".(int)$document_id;
|
$sql_cleanup .= " WHERE ".$tables['fk_parent']." = ".(int)$document_id;
|
||||||
$sql_cleanup .= " AND m.line_type = 'product'";
|
$sql_cleanup .= " AND document_type = '".$db->escape($docType)."'";
|
||||||
$sql_cleanup .= " AND d.rowid IS NULL";
|
$sql_cleanup .= " AND line_type = 'product'";
|
||||||
|
$sql_cleanup .= " AND ".$tables['fk_line']." IS NOT NULL";
|
||||||
|
$sql_cleanup .= " AND ".$tables['fk_line']." NOT IN (SELECT rowid FROM ".MAIN_DB_PREFIX.$tables['lines_table'].")";
|
||||||
$result = $db->query($sql_cleanup);
|
$result = $db->query($sql_cleanup);
|
||||||
|
|
||||||
// 2. Hole alle Produktzeilen des Dokuments mit rang
|
// 2. Hole alle Produktzeilen des Dokuments mit rang
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class modSubtotalTitle extends DolibarrModules
|
||||||
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@subtotaltitle'
|
$this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@subtotaltitle'
|
||||||
|
|
||||||
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z'
|
||||||
$this->version = '4.1';
|
$this->version = '4.4';
|
||||||
// Url to the file with your last numberversion of this module
|
// Url to the file with your last numberversion of this module
|
||||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,3 +103,58 @@ function subtotaltitle_debug_log($message, $force = false)
|
||||||
error_log('[SubtotalTitle] ' . $message);
|
error_log('[SubtotalTitle] ' . $message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sendet Benachrichtigung über GlobalNotify (falls verfügbar)
|
||||||
|
* Fallback: Schreibt ins Dolibarr-Log
|
||||||
|
*
|
||||||
|
* @param string $type 'error', 'warning', 'info', 'action'
|
||||||
|
* @param string $title Kurzer Titel
|
||||||
|
* @param string $message Detaillierte Nachricht
|
||||||
|
* @param string $actionUrl URL für Aktions-Button (optional)
|
||||||
|
* @param string $actionLabel Label für Aktions-Button (optional)
|
||||||
|
* @return bool True wenn über GlobalNotify gesendet
|
||||||
|
*/
|
||||||
|
function subtotaltitle_notify($type, $title, $message, $actionUrl = '', $actionLabel = '')
|
||||||
|
{
|
||||||
|
global $db;
|
||||||
|
|
||||||
|
// Prüfe ob GlobalNotify aktiv und verfügbar
|
||||||
|
if (!isModEnabled('globalnotify')) {
|
||||||
|
dol_syslog("SubtotalTitle [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$classFile = dol_buildpath('/globalnotify/class/globalnotify.class.php', 0);
|
||||||
|
if (!file_exists($classFile)) {
|
||||||
|
dol_syslog("SubtotalTitle [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once $classFile;
|
||||||
|
|
||||||
|
if (!class_exists('GlobalNotify')) {
|
||||||
|
dol_syslog("SubtotalTitle [{$type}]: {$title} - {$message}", LOG_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($type) {
|
||||||
|
case 'error':
|
||||||
|
GlobalNotify::error('subtotaltitle', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
GlobalNotify::warning('subtotaltitle', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
break;
|
||||||
|
case 'action':
|
||||||
|
GlobalNotify::actionRequired('subtotaltitle', $title, $message, $actionUrl, $actionLabel ?: 'Aktion erforderlich');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
GlobalNotify::info('subtotaltitle', $title, $message, $actionUrl, $actionLabel);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
dol_syslog("GlobalNotify error: ".$e->getMessage(), LOG_ERR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue