Update documentation and configuration for architecture changes; remove CAIKnowledge and related entities; update microtime values in config and state files
This commit is contained in:
@@ -334,6 +334,19 @@ cat custom/docs/ESPOCRM_BEST_PRACTICES.md | grep -A 200 "Troubleshooting"
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Architektur-Update (26. März 2026)
|
||||
|
||||
**Änderungen:**
|
||||
- ✅ `CAIKnowledge` entfernt (Hooks, Controller, i18n, Metadata)
|
||||
- ✅ `CAICollections` / `CAICollectionCDokumente` entfernt
|
||||
- ✅ `CAdvowareAkten` entfernt → ersetzt durch `CAkten`
|
||||
- ✅ AI-Sync-Architektur: CDokumente → CAkten (direkte n:1, kein Junction Table)
|
||||
- ✅ Neues Feld `aiProvider` auf CAkten (ragflow/xai, Default: ragflow)
|
||||
- ✅ Hook-Chain: UpdateJunctionSyncStatus → UpdateLastSyncFromDocuments
|
||||
- ✅ ESPOCRM_BEST_PRACTICES.md auf v2.5 aktualisiert
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Reorganisation (9. März 2026)
|
||||
|
||||
**Änderungen:**
|
||||
@@ -356,6 +369,6 @@ cat custom/docs/ESPOCRM_BEST_PRACTICES.md | grep -A 200 "Troubleshooting"
|
||||
|
||||
---
|
||||
|
||||
**Letzte Aktualisierung:** 9. März 2026
|
||||
**Letzte Aktualisierung:** 26. März 2026
|
||||
|
||||
**Für Fragen:** Siehe `custom/docs/ESPOCRM_BEST_PRACTICES.md`
|
||||
|
||||
@@ -1,11 +1,35 @@
|
||||
# EspoCRM Best Practices & Entwicklungsrichtlinien
|
||||
|
||||
**Version:** 2.4
|
||||
**Datum:** 12. März 2026
|
||||
**Version:** 2.5
|
||||
**Datum:** 26. März 2026
|
||||
**Zielgruppe:** AI Code Agents & Entwickler
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Letzte Änderungen (v2.5 - 26. März 2026)
|
||||
|
||||
**Architektur-Refactoring:**
|
||||
- ✅ **CAIKnowledge entfernt**: Entity vollständig entfernt (inkl. Hooks, Controller, i18n, Metadata)
|
||||
- ✅ **CAICollections/CAICollectionCDokumente entfernt**: Junction-Entity-Architektur aufgegeben
|
||||
- ✅ **CAdvowareAkten entfernt**: Durch `CAkten` ersetzt (direkter Link zu CDokumente via `cAktenId`)
|
||||
- ✅ **CAkten** ist nun zentrales AI+Advoware-Sync-Entity mit eigenen Status-Feldern
|
||||
- ✅ **`aiProvider` Feld**: Neues Enum-Feld in CAkten (`ragflow` / `xai`, Standard: `ragflow`)
|
||||
- ✅ **AI-Felder direkt auf CDokumente**: `aiSyncStatus`, `aiLastSync`, `aiFileId`, `aiCollectionId`, `aiSyncHash`
|
||||
|
||||
**Hook-Architektur neu:**
|
||||
- ✅ **CDokumente/UpdateJunctionSyncStatus** (AfterSave): Markiert CDokumente + CAkten als `unclean` bei Änderungen
|
||||
- ✅ **CAkten/UpdateLastSyncFromDocuments** (BeforeSave): Aggregiert Status aller CDokumente per PDO-Query
|
||||
- ✅ **CAkten/PropagateDocumentsUp** (AfterSave): Propagiert Dokument-Verlinkungen zu Räumungsklage/Mietinkasso
|
||||
- ⚠️ **CAIKnowledge-Hooks entfernt**: CheckGlobalSyncStatus, DokumenteSyncStatus, PropagateDocumentsUp
|
||||
|
||||
**Dokumentierte Patterns:**
|
||||
- Direkte n:1 CDokumente → CAkten Beziehung (kein Junction Table)
|
||||
- Worst-Case-Status-Aggregation via Raw PDO (BeforeSave-Hook)
|
||||
- Globaler Sync-Status (`globalSyncStatus`, `globalLastSync`) auf CAkten
|
||||
- AI-Provider-Auswahl als Enum-Feld (ragflow/xai)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Letzte Änderungen (v2.4 - 12. März 2026)
|
||||
|
||||
**Neue Features:**
|
||||
@@ -124,28 +148,30 @@ client/custom/ # Frontend-Code
|
||||
|
||||
### Custom Entities Übersicht
|
||||
|
||||
**19 Custom Entities implementiert (Stand: März 2026):**
|
||||
**17 Custom Entities implementiert (Stand: 26. März 2026):**
|
||||
|
||||
| Entity | Beschreibung | Hooks | Typ |
|
||||
|--------|--------------|-------|-----|
|
||||
| `CAdressen` | Adressen-Verwaltung | - | Base |
|
||||
| `CAICollections` | AI-Dokumenten-Sammlungen | - | Base |
|
||||
| `CAICollectionCDokumente` | Junction: Collections ↔ Dokumente | - | Junction |
|
||||
| `CAkten` | Akten (Advoware + AI Sync) | ✅ UpdateLastSync, PropagateDocumentsUp | Base |
|
||||
| `CBankverbindungen` | Bankdaten (IBAN/BIC) | ✅ Validierung | Base |
|
||||
| `CBeteiligte` | Beteiligte Personen | - | Base |
|
||||
| `CCallQueues` | Call-Warteschlangen | - | Base |
|
||||
| `CDokumente` | Dokumenten-Management | ✅ Hash-Berechnung | Base |
|
||||
| `CKuendigung` | Kündigungen | - | Base |
|
||||
| `CMietinkasso` | Mietinkasso-Fälle | - | Base |
|
||||
| `CDokumente` | Dokumenten-Management | ✅ Hash-Berechnung, UpdateJunctionSyncStatus | Base |
|
||||
| `CKuendigung` | Kündigungen | ✅ CreateAdvowareAkte, SyncAdvowareAkte | Base |
|
||||
| `CMietinkasso` | Mietinkasso-Fälle | ✅ PropagateDocuments | Base |
|
||||
| `CMietobjekt` | Mietobjekte | - | Base |
|
||||
| `CPuls` | Posteingangs-System | ✅ Statistik | Base |
|
||||
| `CPulsTeamZuordnung` | Puls-Team-Zuordnungen | - | Base |
|
||||
| `CVMHBeteiligte` | VMH-spezifische Beteiligte | - | Base |
|
||||
| `CVmhErstgespraech` | Erstgespräche | - | Base |
|
||||
| `CVmhMietverhltnis` | Mietverhältnisse | - | Base |
|
||||
| `CVmhRumungsklage` | Räumungsklagen | - | Base |
|
||||
| `CVmhRumungsklage` | Räumungsklagen | ✅ PropagateDocuments | Base |
|
||||
| `CVmhVermieter` | Vermieter | - | Base |
|
||||
|
||||
> ⚠️ **Entfernt (März 2026):** `CAIKnowledge`, `CAICollections`, `CAICollectionCDokumente`, `CAdvowareAkten`
|
||||
> — Die AI-Sync-Logik läuft jetzt direkt über `CAkten` ↔ `CDokumente` (n:1).
|
||||
|
||||
**Standard-Entities erweitert:**
|
||||
- `Contact` - Erweiterterte Kontakt-Felder
|
||||
- `Call` - Custom Call-Felder
|
||||
@@ -157,10 +183,17 @@ client/custom/ # Frontend-Code
|
||||
- `Team` - Team-Anpassungen
|
||||
- `BpmnUserTask` - Workflow-Task-Erweiterungen
|
||||
|
||||
**Implementierte Hooks:**
|
||||
1. **CBankverbindungen/BankdatenValidation** - IBAN/BIC-Validierung mit Modulo-97
|
||||
2. **CDokumente/CDokumente** - MD5/SHA256-Hash-Berechnung für Uploads
|
||||
3. **CPuls/UpdateTeamStats** - Automatische Statistik-Berechnung
|
||||
**Implementierte Hooks (Stand: 26. März 2026):**
|
||||
1. **CBankverbindungen/BankdatenValidation** (BeforeSave) - IBAN/BIC-Validierung mit Modulo-97
|
||||
2. **CDokumente/CDokumente** (BeforeSave) - Blake3/MD5-Hash-Berechnung für Uploads
|
||||
3. **CDokumente/UpdateJunctionSyncStatus** (AfterSave) - Setzt `syncStatus` + `aiSyncStatus` = `unclean` bei Dokumentänderungen; triggert CAkten-Aggregation
|
||||
4. **CAkten/UpdateLastSyncFromDocuments** (BeforeSave) - Aggregiert Advoware- und AI-Sync-Status aller CDokumente per PDO (worst-case)
|
||||
5. **CAkten/PropagateDocumentsUp** (AfterSave) - Propagiert `cAktenId`-Änderungen zu Räumungsklage/Mietinkasso
|
||||
6. **CKuendigung/CreateAdvowareAkte** (AfterSave) - Erstellt CAkten-Eintrag bei neuer Kündigung
|
||||
7. **CKuendigung/SyncAdvowareAkte** (AfterSave) - Synchronisiert Aktennummer mit Kündigung
|
||||
8. **CMietinkasso/PropagateDocuments** (AfterRelate/AfterUnrelate) - Propagiert Dokumente zu Räumungsklage
|
||||
9. **CVmhRumungsklage/PropagateDocuments** (AfterRelate/AfterUnrelate) - Propagiert Dokumente zu Mietinkasso
|
||||
10. **CPuls/UpdateTeamStats** (AfterSave) - Automatische Statistik-Berechnung
|
||||
|
||||
---
|
||||
|
||||
@@ -236,7 +269,7 @@ client/custom/ # Frontend-Code
|
||||
- `CMietobjekt` - Mietobjekte
|
||||
- `CVmhMietverhltnis` - Mietverhältnisse (VMH = Vermieter Helden)
|
||||
- `CKuendigung` - Kündigungen
|
||||
- `CAICollections` - AI Collections
|
||||
- `CAkten` - Akten (Advoware + AI Sync)
|
||||
|
||||
### Entity Definition Template
|
||||
|
||||
@@ -1538,13 +1571,12 @@ class PropagateDocuments implements AfterRelate, AfterUnrelate
|
||||
|
||||
**Down-Propagierung (Räumungsklage → unten):**
|
||||
- Hook in Räumungsklage/Mietinkasso
|
||||
- Bei Dokumenten-Link → propagiere zu AdvowareAkten + AIKnowledge
|
||||
- Deren Hooks versuchen zurück zu propagieren → blockiert durch Loop-Schutz
|
||||
- Bei Dokumenten-Link → propagiere zu CAkten
|
||||
- CAkten-Hook (`UpdateLastSyncFromDocuments`) aggregiert Status
|
||||
|
||||
**Up-Propagierung (AdvowareAkten → oben):**
|
||||
- Hook in AdvowareAkten/AIKnowledge
|
||||
- Bei Dokumenten-Link → propagiere zu Räumungsklage/Mietinkasso
|
||||
- Deren Hooks propagieren zu anderen Kind-Entities
|
||||
**Up-Propagierung (CAkten → oben):**
|
||||
- Hook in CAkten (`PropagateDocumentsUp`)
|
||||
- Bei `cAktenId`-Änderung → propagiere zu Räumungsklage/Mietinkasso
|
||||
- Loop-Schutz verhindert Rück-Propagierung
|
||||
|
||||
**Loop-Schutz Mechanismus:**
|
||||
@@ -1832,6 +1864,56 @@ class UpdateTeamStats implements BeforeSave
|
||||
|
||||
---
|
||||
|
||||
#### Beispiel 4: Sync-Status-Aggregation (CAkten ↔ CDokumente)
|
||||
|
||||
**Dateien:**
|
||||
- `custom/Espo/Custom/Hooks/CDokumente/UpdateJunctionSyncStatus.php`
|
||||
- `custom/Espo/Custom/Hooks/CAkten/UpdateLastSyncFromDocuments.php`
|
||||
|
||||
**Use Case:** Wenn ein Dokument geändert wird → CDokumente markiert sich als `unclean` → CAkten aggregiert den schlechtesten Status aller Dokumente via Raw PDO.
|
||||
|
||||
**Hook-Chain:**
|
||||
```
|
||||
CDokumente (AfterSave)
|
||||
UpdateJunctionSyncStatus
|
||||
→ setzt dokument.syncStatus = 'unclean'
|
||||
→ setzt dokument.aiSyncStatus = 'unclean'
|
||||
→ speichert Dokument (skipHooks: true)
|
||||
→ löst CAkten.save() aus (silent: true)
|
||||
→ CAkten (BeforeSave)
|
||||
UpdateLastSyncFromDocuments
|
||||
→ PDO-Query: MAX(lastSyncTimestamp), MAX(aiLastSync), worst-case Status
|
||||
→ setzt akte.syncStatus, akte.aiSyncStatus, akte.lastSync, akte.aiLastSync
|
||||
```
|
||||
|
||||
**Trigger-Felder (UpdateJunctionSyncStatus):**
|
||||
```php
|
||||
private function hasRelevantChanges(Entity $entity): bool
|
||||
{
|
||||
$relevantFields = ['name', 'description', 'dokument', 'dokumentId',
|
||||
'preview', 'previewId', 'fileStatus'];
|
||||
foreach ($relevantFields as $field) {
|
||||
if ($entity->isAttributeChanged($field)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
**Status-Aggregation (worst-case Logic in CAkten/UpdateLastSyncFromDocuments):**
|
||||
```
|
||||
failed > unclean/new/null > synced
|
||||
```
|
||||
Wenn ein einziges Dokument `failed` ist → Akte zeigt `failed`.
|
||||
|
||||
**Wichtige Punkte:**
|
||||
- Skip bei `isNew()` (neue Entities haben noch keine Dokumente)
|
||||
- Skip bei `skipHooks` - verhindert Endlos-Rekursion
|
||||
- PDO-Query statt EntityManager für Aggregation (Performance)
|
||||
- AI-Felder auf CDokumente: `aiSyncStatus`, `aiLastSync`, `aiFileId`, `aiCollectionId`, `aiSyncHash`
|
||||
- AI-Provider-Auswahl auf CAkten: `aiProvider` (ragflow/xai, Standard: ragflow)
|
||||
|
||||
---
|
||||
|
||||
### Best Practices für Hooks
|
||||
|
||||
#### ✅ DO
|
||||
@@ -2535,34 +2617,24 @@ docker exec espocrm bash -c 'curl -s -X GET "http://localhost/api/v1/{EntityName
|
||||
3. ✅ Prüfe Logs nach Rebuild auf InjectableFactory-Fehler
|
||||
4. ✅ Teste Entity-Zugriff nach Erstellung
|
||||
|
||||
**Real-World-Beispiel (März 2026):**
|
||||
**Real-World-Beispiel (März 2026 → historisch):**
|
||||
|
||||
**Problem:**
|
||||
- Entities `CAICollection` und `CAdvowareAkten` nicht aufrufbar
|
||||
- Logs zeigten: `Class 'Espo\Custom\Services\CAICollection' does not exist`
|
||||
> ⚠️ **VERALTET** — `CAICollection` und `CAdvowareAkten` wurden entfernt.
|
||||
> Die AI-Sync-Logik läuft seit 26. März 2026 über `CAkten` direkt.
|
||||
>
|
||||
> Das Pattern (Service-Klasse erstellen) bleibt gültig für alle neuen Entities:
|
||||
|
||||
**Lösung:**
|
||||
```bash
|
||||
# Service-Klassen erstellt
|
||||
cat > custom/Espo/Custom/Services/CAICollection.php << 'EOF'
|
||||
```php
|
||||
// Für jede neue Custom Entity eine leere Service-Klasse anlegen:
|
||||
cat > custom/Espo/Custom/Services/CMeineEntity.php << 'EOF'
|
||||
<?php
|
||||
namespace Espo\Custom\Services;
|
||||
use Espo\Services\Record;
|
||||
class CAICollection extends Record {}
|
||||
class CMeineEntity 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
|
||||
**Regelfall:** Rebuild schlägt mit `Class 'Espo\Custom\Services\...' does not exist` fehl → Service-Datei fehlt.
|
||||
|
||||
### Formula triggert nicht
|
||||
|
||||
@@ -2573,56 +2645,12 @@ python3 custom/scripts/validate_and_rebuild.py
|
||||
|
||||
### Bekannte i18n-Warnungen (nicht kritisch)
|
||||
|
||||
**Stand: März 2026**
|
||||
**Stand: 26. März 2026**
|
||||
|
||||
Die folgenden i18n-Link-Labels fehlen aktuell (funktional keine Auswirkung):
|
||||
> ✅ Die früheren Warnungen zu `CAICollections` und `CAdvowareAkten` sind entfallen, da diese Entities entfernt wurden.
|
||||
|
||||
```
|
||||
⚠ CDokumente (en_US): Link 'cAICollections' fehlt in i18n
|
||||
⚠ CAICollections (de_DE): Link 'meetings' fehlt in i18n
|
||||
⚠ CAICollections (de_DE): Link 'cDokumente' fehlt in i18n
|
||||
⚠ CAICollections (en_US): Link 'cDokumente' fehlt in i18n
|
||||
```
|
||||
|
||||
**Behebung (optional):**
|
||||
|
||||
**Datei:** `custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json`
|
||||
```json
|
||||
{
|
||||
"links": {
|
||||
"cAICollections": "AI Collections"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Datei:** `custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json`
|
||||
```json
|
||||
{
|
||||
"links": {
|
||||
"cAICollections": "AI Collections"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Datei:** `custom/Espo/Custom/Resources/i18n/de_DE/CAICollections.json`
|
||||
```json
|
||||
{
|
||||
"links": {
|
||||
"cDokumente": "Dokumente",
|
||||
"meetings": "Meetings"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Datei:** `custom/Espo/Custom/Resources/i18n/en_US/CAICollections.json`
|
||||
```json
|
||||
{
|
||||
"links": {
|
||||
"cDokumente": "Documents",
|
||||
"meetings": "Meetings"
|
||||
}
|
||||
}
|
||||
```
|
||||
Aktuelle Validierung läuft sauber über `validate_and_rebuild.py`.
|
||||
Bei neuen Entities auf vollständige i18n (de_DE + en_US) in `fields` und `links` achten.
|
||||
|
||||
---
|
||||
|
||||
@@ -2637,8 +2665,8 @@ Die folgenden i18n-Link-Labels fehlen aktuell (funktional keine Auswirkung):
|
||||
5. **CMietinkasso** - Mietinkasso-Verfahren
|
||||
6. **CVmhRumungsklage** - Räumungsklagen
|
||||
7. **CDokumente** - Dokumente
|
||||
8. **CPuls** - Puls-System (Entwicklungen)
|
||||
9. **CAICollections** - AI Collections
|
||||
8. **CAkten** - Akten (Advoware + AI Sync)
|
||||
9. **CPuls** - Puls-System (Entwicklungen)
|
||||
|
||||
### Entity-Graph
|
||||
|
||||
@@ -2647,14 +2675,20 @@ CMietobjekt
|
||||
├── CVmhMietverhltnis (hasMany)
|
||||
│ ├── CKuendigung (hasMany)
|
||||
│ │ └── CVmhRumungsklage (hasOne)
|
||||
│ │ └── CAkten (belongsTo)
|
||||
│ ├── CMietinkasso (hasMany)
|
||||
│ │ └── CAkten (belongsTo)
|
||||
│ └── CBeteiligte (hasMany)
|
||||
└── Contact (hasMany)
|
||||
|
||||
CDokumente
|
||||
├── parent → [CVmhRumungsklage, CMietinkasso, CKuendigung]
|
||||
└── CAICollections (hasMany via Junction)
|
||||
└── CPuls (hasMany)
|
||||
├── cAkten (belongsTo CAkten) ← direkte n:1 Beziehung
|
||||
└── parent → [CVmhRumungsklage, CMietinkasso, CKuendigung, ...]
|
||||
|
||||
CAkten
|
||||
├── dokumentes (hasMany CDokumente) ← Aggregations-Quelle
|
||||
├── vmhRumungsklage (belongsTo)
|
||||
└── mietinkasso (belongsTo)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user