Update documentation for EspoCRM Best Practices and Validator Tool
This commit is contained in:
@@ -1,11 +1,29 @@
|
|||||||
# EspoCRM Best Practices & Entwicklungsrichtlinien
|
# EspoCRM Best Practices & Entwicklungsrichtlinien
|
||||||
|
|
||||||
**Version:** 2.1
|
**Version:** 2.2
|
||||||
**Datum:** 9. März 2026
|
**Datum:** 10. März 2026
|
||||||
**Zielgruppe:** AI Code Agents & Entwickler
|
**Zielgruppe:** AI Code Agents & Entwickler
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 🔄 Letzte Änderungen (v2.2 - 10. März 2026)
|
||||||
|
|
||||||
|
**Kritische Erkenntnisse:**
|
||||||
|
- ✅ **Service-Klassen sind PFLICHT**: Neue Section über erforderliche Service-Klassen
|
||||||
|
- ✅ **InjectableFactory-Fehler**: Detaillierter Troubleshooting-Guide hinzugefügt
|
||||||
|
- ✅ **validate_and_rebuild.py v2.0**: Erweiterte Log-Prüfung und CRUD-Tests
|
||||||
|
- ✅ **Real-World-Beispiel**: CAICollection/CAdvowareAkten Fehlerfall dokumentiert
|
||||||
|
|
||||||
|
**Tools:**
|
||||||
|
- 🆕 Minimierter/Verbose Output-Modus
|
||||||
|
- 🆕 Log-Prüfung nach jedem API-Request
|
||||||
|
- 🆕 CRUD-Tests für alle Entities
|
||||||
|
- 🆕 KI-freundliches JSON-Feedback
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 📋 Inhaltsverzeichnis
|
## 📋 Inhaltsverzeichnis
|
||||||
|
|
||||||
1. [Projekt-Übersicht](#projekt-übersicht)
|
1. [Projekt-Übersicht](#projekt-übersicht)
|
||||||
@@ -273,6 +291,90 @@ client/custom/ # Frontend-Code
|
|||||||
- `stream: true` - Stream/Activity Feed
|
- `stream: true` - Stream/Activity Feed
|
||||||
- `calendar: true` - Für Entities mit Datum-Feldern
|
- `calendar: true` - Für Entities mit Datum-Feldern
|
||||||
|
|
||||||
|
### Service-Klassen (KRITISCH!)
|
||||||
|
|
||||||
|
**⚠️ PFLICHT:** Jede Custom Entity MUSS eine Service-Klasse haben!
|
||||||
|
|
||||||
|
**Problem:** Ohne Service-Klasse gibt EspoCRM beim Zugriff folgenden Fehler:
|
||||||
|
```
|
||||||
|
CRITICAL: InjectableFactory: Class 'Espo\Custom\Services\{EntityName}' does not exist.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Lösung:** Erstelle für jede Entity eine Service-Klasse:
|
||||||
|
|
||||||
|
**Datei:** `custom/Espo/Custom/Services/{EntityName}.php`
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
|
||||||
|
use Espo\Services\Record;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service für {EntityName} Entity
|
||||||
|
*/
|
||||||
|
class {EntityName} extends Record
|
||||||
|
{
|
||||||
|
// Basis-Service-Funktionalität wird von Record geerbt
|
||||||
|
// Custom Business Logic kann hier hinzugefügt werden
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Minimale Service-Klasse:**
|
||||||
|
- Erbt von `\Espo\Services\Record`
|
||||||
|
- Muss im Namespace `Espo\Custom\Services` sein
|
||||||
|
- Klassenname muss exakt dem Entity-Namen entsprechen
|
||||||
|
- Mindestens leerer Body erforderlich
|
||||||
|
|
||||||
|
**Erweiterte Service mit Custom Logic:**
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
|
||||||
|
use Espo\Services\Record;
|
||||||
|
use Espo\Core\Exceptions\Forbidden;
|
||||||
|
use Espo\Core\Exceptions\NotFound;
|
||||||
|
|
||||||
|
class {EntityName} extends Record
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Custom Business Logic Methode
|
||||||
|
*/
|
||||||
|
public function customAction(string $id, \stdClass $data): array
|
||||||
|
{
|
||||||
|
// ACL Check
|
||||||
|
if (!$this->getAcl()->checkEntityEdit($this->entityType)) {
|
||||||
|
throw new Forbidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Entity
|
||||||
|
$entity = $this->getEntityManager()->getEntity($this->entityType, $id);
|
||||||
|
if (!$entity) {
|
||||||
|
throw new NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Business Logic hier
|
||||||
|
$entity->set('status', 'Processed');
|
||||||
|
$this->getEntityManager()->saveEntity($entity);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
'id' => $entity->getId()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Best Practice:**
|
||||||
|
1. ✅ Erstelle Service-Klasse SOFORT bei Entity-Erstellung
|
||||||
|
2. ✅ Auch wenn initial leer, erstelle sie trotzdem
|
||||||
|
3. ✅ Nutze Service für Business Logic statt Hooks
|
||||||
|
4. ✅ Verwende Type Hints für bessere IDE-Unterstützung
|
||||||
|
5. ✅ Dokumentiere Custom-Methoden mit DocBlocks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### i18n (Internationalisierung)
|
### i18n (Internationalisierung)
|
||||||
|
|
||||||
**KRITISCH:** Immer BEIDE Sprachen pflegen!
|
**KRITISCH:** Immer BEIDE Sprachen pflegen!
|
||||||
@@ -1282,35 +1384,113 @@ php custom/scripts/workflow_manager.php list
|
|||||||
|
|
||||||
## Testing & Validierung
|
## Testing & Validierung
|
||||||
|
|
||||||
### Validierungs-Tool
|
### Validierungs-Tool v2.0 (Erweitert)
|
||||||
|
|
||||||
**Haupt-Tool:** `custom/scripts/validate_and_rebuild.py`
|
**Haupt-Tool:** `custom/scripts/validate_and_rebuild.py`
|
||||||
|
|
||||||
|
#### Verwendung
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Vollständige Validierung + Rebuild
|
# Standard: Minimaler Output, vollständige Tests
|
||||||
python3 custom/scripts/validate_and_rebuild.py
|
python3 custom/scripts/validate_and_rebuild.py
|
||||||
|
|
||||||
|
# Verbose: Detaillierte Ausgabe für Debugging
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py -v
|
||||||
|
|
||||||
# Nur Validierung (kein Rebuild)
|
# Nur Validierung (kein Rebuild)
|
||||||
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
|
||||||
# Mit E2E Tests überspringen
|
# Ohne Entity CRUD-Tests
|
||||||
python3 custom/scripts/validate_and_rebuild.py --skip-e2e
|
python3 custom/scripts/validate_and_rebuild.py --skip-tests
|
||||||
|
|
||||||
|
# Mit Custom-Credentials
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --username admin --password secret
|
||||||
|
|
||||||
|
# Mit Custom Base-URL
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --base-url http://my-espo.local
|
||||||
```
|
```
|
||||||
|
|
||||||
**Das Tool prüft:**
|
#### Was das Tool prüft
|
||||||
|
|
||||||
|
**Phase 1: Statische Validierung**
|
||||||
1. ✅ JSON-Syntax aller Custom-Dateien
|
1. ✅ JSON-Syntax aller Custom-Dateien
|
||||||
2. ✅ Relationship-Konsistenz (bidirektionale Links)
|
2. ✅ Relationship-Konsistenz (bidirektionale Links)
|
||||||
3. ✅ Formula-Script Platzierung
|
3. ✅ Erforderliche Dateien (scopes, i18n)
|
||||||
4. ✅ i18n-Vollständigkeit (de_DE + en_US)
|
4. ✅ Dateirechte (www-data:www-data) + Auto-Fix
|
||||||
5. ✅ Layout-Struktur (bottomPanelsDetail, detail.json)
|
5. ✅ PHP-Syntax (php -l)
|
||||||
6. ✅ Dateirechte (www-data:www-data)
|
|
||||||
7. ✅ CSS-Validierung (csslint)
|
|
||||||
8. ✅ JavaScript-Validierung (jshint)
|
|
||||||
9. ✅ PHP-Syntax (php -l)
|
|
||||||
10. ✅ EspoCRM Rebuild
|
|
||||||
11. ✅ E2E-Tests (CRUD-Operationen)
|
|
||||||
|
|
||||||
**Bei Fehlern:** Automatische Fehlerlog-Analyse der letzten 50 Log-Zeilen!
|
**Phase 2: Rebuild mit Log-Prüfung**
|
||||||
|
6. ✅ Cache-Clearing
|
||||||
|
7. ✅ EspoCRM Rebuild
|
||||||
|
8. ✅ **Log-Prüfung direkt nach Rebuild** (mit präzisen Zeitstempeln)
|
||||||
|
|
||||||
|
**Phase 3: Live Entity-Tests** (wenn nicht übersprungen)
|
||||||
|
9. ✅ **CREATE** - Eintrag erstellen + Log-Check
|
||||||
|
10. ✅ **READ** - Eintrag lesen + Log-Check
|
||||||
|
11. ✅ **UPDATE** - Eintrag aktualisieren + Log-Check
|
||||||
|
12. ✅ **LIST** - Liste abrufen + Log-Check
|
||||||
|
13. ✅ **DELETE** - Eintrag löschen + Log-Check
|
||||||
|
14. ✅ Automatisches Cleanup aller Test-Records
|
||||||
|
|
||||||
|
#### Neue Features (v2.0)
|
||||||
|
|
||||||
|
**1. Log-Integration:**
|
||||||
|
- Nach **jedem** API-Request werden Logs geprüft
|
||||||
|
- Präzise Zeitstempel (nur Logs seit Request-Start)
|
||||||
|
- Test bricht ab bei Fehler in Logs
|
||||||
|
- Filtert bekannte unwichtige Meldungen
|
||||||
|
|
||||||
|
**2. Intelligenter Output:**
|
||||||
|
- **Standard-Modus:** Nur Ergebnisse (✓/✗)
|
||||||
|
- **Verbose-Modus (`-v`):** Detaillierte Informationen, Timing, Debugging
|
||||||
|
|
||||||
|
**3. CRUD-Tests für alle Entities:**
|
||||||
|
- Testet jede Custom-Entity einzeln
|
||||||
|
- Validiert kompletten Lifecycle
|
||||||
|
- Prüft API-Responses
|
||||||
|
- Detektiert Service-Klassen-Fehler
|
||||||
|
|
||||||
|
**4. KI-freundliches Feedback:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"summary": {
|
||||||
|
"errors": 0,
|
||||||
|
"warnings": 1,
|
||||||
|
"entities_checked": 28
|
||||||
|
},
|
||||||
|
"errors": [],
|
||||||
|
"warnings": ["..."],
|
||||||
|
"recommendations": [
|
||||||
|
"Fehlende Service-Klassen - erstelle für jede Entity eine Service-Klasse",
|
||||||
|
"Unvollständige Übersetzungen - füge fehlende i18n-Dateien hinzu"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**5. Fehler-Abbruch bei Log-Errors:**
|
||||||
|
- Script bricht sofort ab wenn Rebuild Fehler in Logs produziert
|
||||||
|
- Zeigt relevante Fehlermeldungen an
|
||||||
|
- Keine weiteren Tests bei kritischen Fehlern
|
||||||
|
|
||||||
|
#### Typischer Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Nach Code-Änderungen: Quick Check
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
|
||||||
|
# 2. Vor Deployment: Vollständiger Test
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py -v
|
||||||
|
|
||||||
|
# 3. Rebuild ohne Tests (schneller)
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --skip-tests
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bei Fehlern:** Das Tool zeigt automatisch:
|
||||||
|
- Fehlerlog-Analyse
|
||||||
|
- Betroffene Dateien
|
||||||
|
- Konkrete Fehlermeldungen
|
||||||
|
- Empfohlene Fixes
|
||||||
|
|
||||||
### End-to-End Tests
|
### End-to-End Tests
|
||||||
|
|
||||||
@@ -1542,6 +1722,102 @@ docker exec espocrm php -l custom/Espo/Custom/Controllers/MyController.php
|
|||||||
- [ ] Action-Methode korrekt benannt? (postAction..., getAction...)
|
- [ ] Action-Methode korrekt benannt? (postAction..., getAction...)
|
||||||
- [ ] ACL-Rechte?
|
- [ ] ACL-Rechte?
|
||||||
|
|
||||||
|
### ⚠️ KRITISCH: InjectableFactory Error (Service-Klasse fehlt)
|
||||||
|
|
||||||
|
**Fehlermeldung in Logs:**
|
||||||
|
```
|
||||||
|
CRITICAL: (0) InjectableFactory: Class 'Espo\Custom\Services\{EntityName}' does not exist.
|
||||||
|
:: GET /{EntityName} :: /var/www/html/application/Espo/Core/InjectableFactory.php(164)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Symptome:**
|
||||||
|
- Entity in UI sichtbar, aber nicht aufrufbar
|
||||||
|
- API-Requests schlagen fehl (leer oder 500 Error)
|
||||||
|
- Fehler tritt bei JEDEM Zugriff auf die Entity auf
|
||||||
|
- Rebuild erfolgreich, aber Funktionalität fehlt
|
||||||
|
|
||||||
|
**Ursache:**
|
||||||
|
Für die Custom Entity `{EntityName}` wurde keine Service-Klasse erstellt. EspoCRM sucht nach `custom/Espo/Custom/Services/{EntityName}.php` und findet sie nicht.
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
|
||||||
|
**Schritt 1:** Erstelle Service-Datei
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Erstelle Datei
|
||||||
|
touch custom/Espo/Custom/Services/{EntityName}.php
|
||||||
|
```
|
||||||
|
|
||||||
|
**Schritt 2:** Füge minimale Service-Klasse ein
|
||||||
|
|
||||||
|
**Datei:** `custom/Espo/Custom/Services/{EntityName}.php`
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
|
||||||
|
use Espo\Services\Record;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service für {EntityName} Entity
|
||||||
|
*/
|
||||||
|
class {EntityName} extends Record
|
||||||
|
{
|
||||||
|
// Basis-Funktionalität wird von Record geerbt
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Schritt 3:** Rebuild + Cache Clear
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Schritt 4:** Verifizieren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prüfe ob Fehler weg sind
|
||||||
|
docker exec espocrm bash -c 'tail -n 50 /var/www/html/data/logs/espo-$(date +%Y-%m-%d).log | grep -i "InjectableFactory"'
|
||||||
|
|
||||||
|
# Test API-Zugriff
|
||||||
|
docker exec espocrm bash -c 'curl -s -X GET "http://localhost/api/v1/{EntityName}" -u "admin:admin"'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Prävention:**
|
||||||
|
1. ✅ **Immer** Service-Klasse bei Entity-Erstellung mit anlegen
|
||||||
|
2. ✅ Nutze `validate_and_rebuild.py` - detektiert fehlende Services
|
||||||
|
3. ✅ Prüfe Logs nach Rebuild auf InjectableFactory-Fehler
|
||||||
|
4. ✅ Teste Entity-Zugriff nach Erstellung
|
||||||
|
|
||||||
|
**Real-World-Beispiel (März 2026):**
|
||||||
|
|
||||||
|
**Problem:**
|
||||||
|
- Entities `CAICollection` und `CAdvowareAkten` nicht aufrufbar
|
||||||
|
- Logs zeigten: `Class 'Espo\Custom\Services\CAICollection' does not exist`
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
```bash
|
||||||
|
# Service-Klassen erstellt
|
||||||
|
cat > custom/Espo/Custom/Services/CAICollection.php << 'EOF'
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
use Espo\Services\Record;
|
||||||
|
class CAICollection extends Record {}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > custom/Espo/Custom/Services/CAdvowareAkten.php << 'EOF'
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
use Espo\Services\Record;
|
||||||
|
class CAdvowareAkten extends Record {}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Rebuild
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py
|
||||||
|
```
|
||||||
|
|
||||||
|
**Ergebnis:** ✅ Beide Entities sofort funktionsfähig, keine Fehler mehr in Logs
|
||||||
|
|
||||||
### Formula triggert nicht
|
### Formula triggert nicht
|
||||||
|
|
||||||
**Checklist:**
|
**Checklist:**
|
||||||
|
|||||||
@@ -1,12 +1,69 @@
|
|||||||
# EspoCRM Validator & Rebuild Tool
|
# EspoCRM Validator & Rebuild Tool v2.0
|
||||||
|
|
||||||
|
**Letzte Aktualisierung:** 10. März 2026
|
||||||
|
**Tool:** `custom/scripts/validate_and_rebuild.py`
|
||||||
|
|
||||||
## Übersicht
|
## Übersicht
|
||||||
|
|
||||||
Das neue Python-basierte Validierungs-Tool `validate_and_rebuild.py` ersetzt das bisherige Bash-Script und bietet erweiterte Prüfungen für EspoCRM Custom-Entities.
|
Erweiterte Python-Tool zur Validierung von EspoCRM Custom-Entities mit intelligenter Log-Prüfung und CRUD-Tests. Version 2.0 bietet minimalen/verbose Output, Live-Entity-Tests und KI-freundliches Feedback.
|
||||||
|
|
||||||
## Features
|
## 🆕 Neue Features in v2.0
|
||||||
|
|
||||||
### ✅ Automatische Validierungen
|
### 1. Intelligenter Output-Modus
|
||||||
|
- **Standard-Modus:** Minimale Ausgabe, nur Ergebnisse
|
||||||
|
- **Verbose-Modus (`-v`):** Detaillierte Informationen mit Timing
|
||||||
|
|
||||||
|
### 2. Log-Prüfung mit präzisen Zeitstempeln
|
||||||
|
- Prüft Logs nach **jedem** API-Request
|
||||||
|
- Nur Logs seit Request-Start
|
||||||
|
- Test bricht ab bei Fehler in Logs
|
||||||
|
- Filtert bekannte unwichtige Meldungen
|
||||||
|
|
||||||
|
### 3. CRUD-Tests für alle Entities
|
||||||
|
- CREATE, READ, UPDATE, LIST, DELETE
|
||||||
|
- Log-Check nach jeder Operation
|
||||||
|
- Automatisches Cleanup
|
||||||
|
- Detektiert fehlende Service-Klassen
|
||||||
|
|
||||||
|
### 4. KI-freundliches JSON-Feedback
|
||||||
|
- Strukturierte Fehleranalyse
|
||||||
|
- Konkrete Empfehlungen
|
||||||
|
- Maschinenlesbar
|
||||||
|
|
||||||
|
## Verwendung
|
||||||
|
|
||||||
|
### Basis-Befehle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Standard: Minimaler Output, vollständige Tests
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py
|
||||||
|
|
||||||
|
# Verbose: Detaillierte Ausgabe für Debugging
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py -v
|
||||||
|
|
||||||
|
# Nur Validierung (kein Rebuild)
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
|
||||||
|
# Ohne Entity-Tests (schneller)
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --skip-tests
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erweiterte Parameter
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Custom Base-URL
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --base-url http://my-espo.local
|
||||||
|
|
||||||
|
# Custom Credentials
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --username admin --password secret
|
||||||
|
|
||||||
|
# Kombination
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py -v --skip-tests --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validierungsphasen
|
||||||
|
|
||||||
|
### Phase 1: Statische Validierung
|
||||||
|
|
||||||
1. **JSON-Syntax-Prüfung**
|
1. **JSON-Syntax-Prüfung**
|
||||||
- Validiert alle `.json` Dateien im `custom/` Verzeichnis
|
- Validiert alle `.json` Dateien im `custom/` Verzeichnis
|
||||||
@@ -15,182 +72,310 @@ Das neue Python-basierte Validierungs-Tool `validate_and_rebuild.py` ersetzt das
|
|||||||
2. **Relationship-Konsistenz**
|
2. **Relationship-Konsistenz**
|
||||||
- Prüft bidirektionale Relationships (hasMany/hasOne)
|
- Prüft bidirektionale Relationships (hasMany/hasOne)
|
||||||
- Validiert `foreign`-Links zwischen Entities
|
- Validiert `foreign`-Links zwischen Entities
|
||||||
- Überprüft `relationName`-Konsistenz
|
- Überprüft `relationName`-Konsistenz bei M2M
|
||||||
- Erkennt fehlende Gegenseiten-Definitionen
|
- Erkennt fehlende Gegenseiten-Definitionen
|
||||||
|
|
||||||
3. **Formula-Script Platzierung**
|
3. **Erforderliche Dateien**
|
||||||
- Prüft ob Formula-Scripts in `/formula/` statt `/entityDefs/` liegen
|
- Prüft Vorhandensein von scopes-Dateien
|
||||||
- Warnt vor leeren Formula-Definitionen
|
- Validiert i18n-Dateien (de_DE + en_US)
|
||||||
|
- Warnt bei fehlenden Translations
|
||||||
|
|
||||||
4. **i18n-Vollständigkeit**
|
4. **Dateirechte**
|
||||||
- Findet fehlende Übersetzungen (de_DE / en_US)
|
- Prüft Owner (www-data:www-data) in:
|
||||||
- Prüft Link-Labels für alle Custom-Relationships
|
- `custom/Espo/Custom/Resources/`
|
||||||
- Warnt bei komplett fehlenden i18n-Dateien
|
- `client/custom/`
|
||||||
|
- `data/` (inkl. config.php)
|
||||||
|
- Korrigiert automatisch (664/775)
|
||||||
|
|
||||||
5. **Layout-Struktur**
|
5. **PHP-Syntax-Validierung**
|
||||||
- Validiert clientDefs und bottomPanels
|
- Validiert alle Custom-PHP-Klassen
|
||||||
- Findet unnötige `false`-Elemente
|
- Nutzt `php -l` für Syntax-Check
|
||||||
|
|
||||||
6. **Dateirechte** (✨ ERWEITERT)
|
### Phase 2: Rebuild mit Log-Prüfung
|
||||||
- Prüft Owner (www-data:www-data) in DREI Bereichen:
|
|
||||||
- `custom/Espo/Custom/Resources/` - Custom Metadata
|
|
||||||
- `client/custom/` - Frontend JavaScript & CSS
|
|
||||||
- `data/` - **INKL. config.php & config-internal.php**
|
|
||||||
- Korrigiert Permissions automatisch (664 für Dateien, 775 für Verzeichnisse)
|
|
||||||
- **Hebt kritische System-Dateien hervor** (config.php, config-internal.php)
|
|
||||||
|
|
||||||
7. **CSS-Validierung**
|
6. **Cache-Clearing**
|
||||||
- Validiert Syntax aller CSS-Dateien
|
- Löscht EspoCRM-Cache vor Rebuild
|
||||||
- Prüft Klammer-Balance und grundlegende Struktur
|
|
||||||
|
|
||||||
8. **JavaScript-Validierung**
|
7. **EspoCRM Rebuild**
|
||||||
- Prüft Syntax aller JS-Dateien in `client/custom/src/`
|
- Führt `php command.php rebuild` aus
|
||||||
|
- **Prüft Logs direkt nach Rebuild**
|
||||||
|
- Bricht ab bei Fehlern in Logs
|
||||||
|
|
||||||
9. **PHP-Validierung**
|
### Phase 3: Live Entity-Tests (optional)
|
||||||
- Validiert PHP-Syntax aller Custom-Klassen
|
|
||||||
|
|
||||||
10. **Rebuild-Ausführung**
|
Für jede Custom Entity (außer Junction Tables):
|
||||||
- Führt `rebuild.php` nur aus, wenn keine kritischen Fehler vorliegen
|
|
||||||
|
|
||||||
## Verwendung
|
8. **CREATE Test**
|
||||||
|
- Erstellt Test-Record via API
|
||||||
|
- Prüft Logs nach Request
|
||||||
|
- Validiert Response
|
||||||
|
|
||||||
### Direkt ausführen
|
9. **READ Test**
|
||||||
```bash
|
- Liest erstellten Record
|
||||||
cd /path/to/espocrm
|
- Prüft Logs
|
||||||
python3 custom/scripts/validate_and_rebuild.py
|
- Validiert Daten
|
||||||
|
|
||||||
|
10. **UPDATE Test**
|
||||||
|
- Aktualisiert Record
|
||||||
|
- Prüft Logs
|
||||||
|
- Validiert Änderung
|
||||||
|
|
||||||
|
11. **LIST Test**
|
||||||
|
- Ruft Entity-Liste ab
|
||||||
|
- Prüft Logs
|
||||||
|
- Validiert Response
|
||||||
|
|
||||||
|
12. **DELETE Test**
|
||||||
|
- Löscht Test-Record
|
||||||
|
- Prüft Logs
|
||||||
|
- Entfernt aus Cleanup-Liste
|
||||||
|
|
||||||
|
13. **Automatisches Cleanup**
|
||||||
|
- Löscht alle verbliebenen Test-Records
|
||||||
|
|
||||||
|
## Output-Beispiele
|
||||||
|
|
||||||
|
### Standard-Modus (Minimal)
|
||||||
|
|
||||||
|
```
|
||||||
|
EspoCRM Validator & Rebuild Tool v2.0
|
||||||
|
|
||||||
|
1. JSON-SYNTAX VALIDIERUNG
|
||||||
|
✓ Alle 746 JSON-Dateien valide
|
||||||
|
|
||||||
|
2. RELATIONSHIP-KONSISTENZ
|
||||||
|
✓ 51 Relationships geprüft
|
||||||
|
|
||||||
|
3. ERFORDERLICHE DATEIEN
|
||||||
|
✗ 1 fehlende Dateien
|
||||||
|
CVMHBeteiligte: scopes/CVMHBeteiligte.json fehlt
|
||||||
|
|
||||||
|
4. DATEIRECHTE-PRÜFUNG
|
||||||
|
✓ Alle Dateirechte korrekt (www-data:www-data)
|
||||||
|
|
||||||
|
5. PHP-SYNTAX VALIDIERUNG
|
||||||
|
✓ Alle 353 PHP-Dateien valide
|
||||||
|
|
||||||
|
6. ESPOCRM REBUILD
|
||||||
|
✓ Rebuild erfolgreich abgeschlossen
|
||||||
|
|
||||||
|
7. ENTITY CRUD-TESTS
|
||||||
|
|
||||||
|
Ergebnis: 18 erfolgreich, 0 fehlgeschlagen
|
||||||
|
✓ Alle 18 Entities getestet
|
||||||
|
|
||||||
|
ZUSAMMENFASSUNG
|
||||||
|
|
||||||
|
WARNUNGEN: 1
|
||||||
|
⚠ CVMHBeteiligte: scopes/CVMHBeteiligte.json fehlt
|
||||||
|
|
||||||
|
✓ ERFOLGREICH ABGESCHLOSSEN
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Verbose-Modus (`-v`)
|
||||||
|
|
||||||
|
```
|
||||||
|
EspoCRM Validator & Rebuild Tool v2.0
|
||||||
|
Verbose-Modus aktiviert
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
1. JSON-SYNTAX VALIDIERUNG
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ℹ Prüfe 746 JSON-Dateien...
|
||||||
|
✓ Alle 746 JSON-Dateien valide
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
6. ESPOCRM REBUILD
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ℹ Container: espocrm
|
||||||
|
ℹ Lösche Cache...
|
||||||
|
ℹ Starte Rebuild...
|
||||||
|
✓ Rebuild erfolgreich abgeschlossen
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
7. ENTITY CRUD-TESTS
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ℹ Teste 18 Custom-Entities...
|
||||||
|
▶ CAICollection: Create... ✓ 0.042s
|
||||||
|
ID: 69b00123456789abc
|
||||||
|
▶ CAICollection: Read... ✓ 0.028s
|
||||||
|
Name: Test CAICollection 1710065432
|
||||||
|
▶ CAICollection: Update... ✓ 0.035s
|
||||||
|
▶ CAICollection: List... ✓ 0.031s
|
||||||
|
12 Einträge
|
||||||
|
▶ CAICollection: Delete... ✓ 0.029s
|
||||||
|
|
||||||
|
[... weitere Entities ...]
|
||||||
|
|
||||||
|
ℹ Ergebnis: 18 erfolgreich, 0 fehlgeschlagen
|
||||||
|
✓ Alle 18 Entities getestet
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bei Fehlern (mit Log-Analyse)
|
||||||
|
|
||||||
|
```
|
||||||
|
7. ENTITY CRUD-TESTS
|
||||||
|
|
||||||
|
▶ CAICollection: Create... ✗ 0.018s
|
||||||
|
Logs enthalten Fehler!
|
||||||
|
✗ Log-Fehler bei CREATE:
|
||||||
|
[2026-03-10 12:34:56] CRITICAL: InjectableFactory: Class 'Espo\Custom\Services\CAICollection' does not exist.
|
||||||
|
:: GET /CAICollection :: /var/www/html/application/Espo/Core/InjectableFactory.php(164)
|
||||||
|
|
||||||
|
ZUSAMMENFASSUNG
|
||||||
|
|
||||||
|
KI-FEEDBACK:
|
||||||
|
{
|
||||||
|
"status": "failed",
|
||||||
|
"summary": {
|
||||||
|
"errors": 1,
|
||||||
|
"warnings": 0,
|
||||||
|
"entities_checked": 28
|
||||||
|
},
|
||||||
|
"errors": ["InjectableFactory: Class 'Espo\\Custom\\Services\\CAICollection' does not exist"],
|
||||||
|
"recommendations": [
|
||||||
|
"KRITISCH: Service-Klassen fehlen! Erstelle Services in custom/Espo/Custom/Services/"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
⚠ TESTS FEHLGESCHLAGEN
|
||||||
|
```
|
||||||
|
|
||||||
## Exit Codes
|
## Exit Codes
|
||||||
|
|
||||||
- `0` - Erfolg: Alle Validierungen bestanden, Rebuild erfolgreich
|
- `0` - Erfolg: Alle Validierungen bestanden, Rebuild erfolgreich
|
||||||
- `1` - Fehler: Kritische Fehler gefunden oder Rebuild fehlgeschlagen
|
- `1` - Fehler: Kritische Fehler gefunden oder Rebuild/Tests fehlgeschlagen
|
||||||
|
|
||||||
## Output-Format
|
|
||||||
|
|
||||||
Das Script verwendet farbcodierte Ausgaben:
|
|
||||||
|
|
||||||
- 🟢 **Grün (✓)**: Erfolgreich / OK
|
|
||||||
- 🟡 **Gelb (⚠)**: Warnungen (nicht kritisch)
|
|
||||||
- 🔴 **Rot (✗)**: Fehler (kritisch, Rebuild wird abgebrochen)
|
|
||||||
- 🔵 **Blau (ℹ)**: Informationen
|
|
||||||
|
|
||||||
## Fehlertypen
|
## Fehlertypen
|
||||||
|
|
||||||
### Kritische Fehler (Rebuild-Abbruch)
|
### Kritische Fehler (Rebuild-Abbruch)
|
||||||
- JSON-Syntax-Fehler
|
- JSON-Syntax-Fehler
|
||||||
|
- PHP-Syntax-Fehler
|
||||||
- Fehlende Relationship-Definitionen
|
- Fehlende Relationship-Definitionen
|
||||||
- Falsch platzierte Formula-Scripts
|
- Rebuild-Fehler
|
||||||
|
- **Log-Fehler nach Rebuild**
|
||||||
|
|
||||||
### Warnungen (kein Abbruch)
|
### Warnungen (kein Abbruch)
|
||||||
- Fehlende i18n-Übersetzungen
|
- Fehlende i18n-Übersetzungen
|
||||||
- Layout-Strukturprobleme
|
- Fehlende scopes-Dateien
|
||||||
- Dateirechte-Probleme
|
- Dateirechte-Probleme (werden auto-korrigiert)
|
||||||
|
|
||||||
## Beispiel-Output
|
### Test-Fehler (kein Abbruch bei --skip-tests)
|
||||||
|
- Entity-Tests schlagen fehl
|
||||||
|
- API-Authentifizierung fehlgeschlagen
|
||||||
|
- Service-Klassen fehlen (wird erkannt!)
|
||||||
|
|
||||||
|
## Häufige Fehler und Lösungen
|
||||||
|
|
||||||
|
### 1. InjectableFactory: Service-Klasse fehlt
|
||||||
|
|
||||||
|
**Symptom:**
|
||||||
```
|
```
|
||||||
EspoCRM Custom Entity Validator & Rebuild Tool
|
CRITICAL: InjectableFactory: Class 'Espo\Custom\Services\{Entity}' does not exist
|
||||||
Arbeitsverzeichnis: /var/lib/docker/volumes/vmh-espocrm_espocrm/_data
|
|
||||||
|
|
||||||
======================================================================
|
|
||||||
1. JSON-SYNTAX VALIDIERUNG
|
|
||||||
======================================================================
|
|
||||||
|
|
||||||
✓ Alle 547 JSON-Dateien sind syntaktisch korrekt
|
|
||||||
|
|
||||||
======================================================================
|
|
||||||
2. RELATIONSHIP-KONSISTENZ
|
|
||||||
======================================================================
|
|
||||||
|
|
||||||
✗ 4 Relationship-Fehler gefunden:
|
|
||||||
• Contact.cBankverbindungenContact: Ziel-Entity 'CBankverbindung' existiert nicht
|
|
||||||
• CMietobjekt.vmhRumungsklages → CVmhRumungsklage: Foreign link 'mietobjekte' fehlt
|
|
||||||
|
|
||||||
======================================================================
|
|
||||||
ZUSAMMENFASSUNG
|
|
||||||
======================================================================
|
|
||||||
|
|
||||||
FEHLER: 4
|
|
||||||
✗ Contact.cBankverbindungenContact: Ziel-Entity 'CBankverbindung' existiert nicht
|
|
||||||
...
|
|
||||||
|
|
||||||
REBUILD ABGEBROCHEN: Kritische Fehler müssen behoben werden!
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Erweiterung
|
**Lösung:**
|
||||||
|
|
||||||
Das Script ist modular aufgebaut. Neue Validierungen können einfach hinzugefügt werden:
|
|
||||||
|
|
||||||
```python
|
|
||||||
def validate_custom_check(self) -> bool:
|
|
||||||
"""Eigene Validierung."""
|
|
||||||
print_header("X. CUSTOM CHECK")
|
|
||||||
|
|
||||||
# Prüflogik hier
|
|
||||||
if error_found:
|
|
||||||
self.errors.append("Fehlerbeschreibung")
|
|
||||||
return False
|
|
||||||
|
|
||||||
print_success("Check erfolgreich")
|
|
||||||
return True
|
|
||||||
```
|
|
||||||
|
|
||||||
Dann in `validate_all()` hinzufügen:
|
|
||||||
|
|
||||||
```python
|
|
||||||
if not self.validate_custom_check():
|
|
||||||
all_valid = False
|
|
||||||
```
|
|
||||||
|
|
||||||
## Anforderungen
|
|
||||||
|
|
||||||
- Python 3.6+
|
|
||||||
- Keine zusätzlichen Packages erforderlich (nur Standard-Library)
|
|
||||||
- Optionale sudo-Rechte für Dateirechte-Korrektur
|
|
||||||
|
|
||||||
## Integration in Workflow
|
|
||||||
|
|
||||||
Das Script kann in automatisierte Workflows integriert werden:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# In CI/CD Pipeline
|
# Service-Klasse erstellen
|
||||||
python3 custom/scripts/validate_and_rebuild.py || exit 1
|
cat > custom/Espo/Custom/Services/{Entity}.php << 'EOF'
|
||||||
|
<?php
|
||||||
|
namespace Espo\Custom\Services;
|
||||||
|
use Espo\Services\Record;
|
||||||
|
class {Entity} extends Record {}
|
||||||
|
EOF
|
||||||
|
|
||||||
# Als Git Pre-Commit Hook
|
# Rebuild
|
||||||
#!/bin/bash
|
|
||||||
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Script findet rebuild.php nicht
|
|
||||||
```bash
|
|
||||||
# Stelle sicher, dass du im EspoCRM-Root bist
|
|
||||||
cd /var/lib/docker/volumes/vmh-espocrm_espocrm/_data
|
|
||||||
python3 custom/scripts/validate_and_rebuild.py
|
python3 custom/scripts/validate_and_rebuild.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dateirechte können nicht korrigiert werden
|
### 2. API-Tests schlagen fehl (401 Unauthorized)
|
||||||
```bash
|
|
||||||
# Manuell mit sudo korrigieren
|
**Symptom:**
|
||||||
sudo chown -R www-data:www-data custom/
|
```
|
||||||
sudo find custom/ -type f -exec chmod 664 {} \;
|
Ergebnis: 0 erfolgreich, 18 fehlgeschlagen
|
||||||
sudo find custom/ -type d -exec chmod 775 {} \;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Python3 nicht verfügbar
|
**Lösung:**
|
||||||
```bash
|
```bash
|
||||||
# Ubuntu/Debian
|
# Korrigiere Credentials
|
||||||
sudo apt-get install python3
|
python3 custom/scripts/validate_and_rebuild.py --username admin --password correct-password
|
||||||
|
|
||||||
# CentOS/RHEL
|
# Oder überspringe Tests
|
||||||
sudo yum install python3
|
python3 custom/scripts/validate_and_rebuild.py --skip-tests
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Relationship-Fehler
|
||||||
|
|
||||||
|
**Symptom:**
|
||||||
|
```
|
||||||
|
✗ EntityA.linkB → EntityB: Foreign link 'linkA' fehlt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Lösung:**
|
||||||
|
Füge bidirektionalen Link in EntityB hinzu - siehe ESPOCRM_BEST_PRACTICES.md
|
||||||
|
|
||||||
|
## Workflow-Beispiele
|
||||||
|
|
||||||
|
### Development Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Nach Code-Änderungen: Quick Check
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
|
||||||
|
# 2. Wenn OK: Rebuild durchführen
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --skip-tests
|
||||||
|
|
||||||
|
# 3. Vor Git-Commit: Vollständiger Test
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### CI/CD Integration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/espocrm-validate.yml
|
||||||
|
- name: Validate EspoCRM
|
||||||
|
run: python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
|
||||||
|
- name: Run Entity Tests
|
||||||
|
run: |
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py \
|
||||||
|
--base-url http://localhost \
|
||||||
|
--username ci-user \
|
||||||
|
--password ${{ secrets.ESPOCRM_PASSWORD }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pre-Commit Hook
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# .git/hooks/pre-commit
|
||||||
|
|
||||||
|
python3 custom/scripts/validate_and_rebuild.py --dry-run
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Validation failed! Fix errors before committing."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
```
|
```
|
||||||
|
|
||||||
## Siehe auch
|
## Siehe auch
|
||||||
|
|
||||||
- [README.md](../../README.md) - Hauptdokumentation
|
- [ESPOCRM_BEST_PRACTICES.md](../ESPOCRM_BEST_PRACTICES.md) - Vollständige Best Practices
|
||||||
- [CUSTOM_DIRECTORY.md](../CUSTOM_DIRECTORY.md) - Custom-Verzeichnis-Struktur
|
- [CHANGELOG_2026-03-10.md](../CHANGELOG_2026-03-10.md) - Letzte Änderungen
|
||||||
- [workflow_manager.php](workflow_manager.php) - Workflow-Management-Tool
|
- [E2E_TESTS_README.md](E2E_TESTS_README.md) - E2E Tests (deprecated, integriert in validator)
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
**v2.0 (10. März 2026):**
|
||||||
|
- ✅ Log-Prüfung mit präzisen Zeitstempeln
|
||||||
|
- ✅ CRUD-Tests für alle Entities
|
||||||
|
- ✅ Minimaler/Verbose Output-Modus
|
||||||
|
- ✅ KI-freundliches JSON-Feedback
|
||||||
|
- ✅ Service-Klassen-Fehler-Detektion
|
||||||
|
|
||||||
|
**v1.0 (9. März 2026):**
|
||||||
|
- ✅ Initiale Version mit statischer Validierung
|
||||||
|
- ✅ JSON, PHP, Relationship-Checks
|
||||||
|
- ✅ Automatische Dateirechte-Korrektur
|
||||||
|
|||||||
Reference in New Issue
Block a user