Add report integration for BpmnUserTask with filters and panels; update cache timestamps
This commit is contained in:
197
README.md
197
README.md
@@ -590,7 +590,202 @@ sudo find custom/ -type f -name "*.json" -exec chmod 664 {} \;
|
|||||||
sudo find custom/ -type d -exec chmod 775 {} \;
|
sudo find custom/ -type d -exec chmod 775 {} \;
|
||||||
```
|
```
|
||||||
|
|
||||||
## 9. Portal-Freigabe-System
|
## 9. Reports und Report-Panels
|
||||||
|
|
||||||
|
EspoCRM bietet über das Advanced Pack zwei Arten von Report-Integrationen: **Report-Filter** und **Report-Panels**. Diese ermöglichen die dynamische Anzeige von gefilterten Listen in Entity-Views.
|
||||||
|
|
||||||
|
### Report-Filter
|
||||||
|
|
||||||
|
Report-Filter ermöglichen es, vordefinierte Filter auf List-Views anzuwenden, die in Datenbanktabellen gespeichert sind.
|
||||||
|
|
||||||
|
#### Struktur und Dateien:
|
||||||
|
|
||||||
|
1. **entityDefs/{EntityType}.json** - Filter-Definition
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"collection": {
|
||||||
|
"filters": {
|
||||||
|
"reportFilterXXXXXXXXXX": {
|
||||||
|
"isReportFilter": true,
|
||||||
|
"id": "reportFilterIdHere"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **selectDefs/{EntityType}.json** - Filter-Klasse
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"primaryFilterClassNameMap": {
|
||||||
|
"reportFilterXXXXXXXXXX": "Espo\\Modules\\Advanced\\Classes\\Select\\Common\\PrimaryFilters\\ReportFilter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **clientDefs/{EntityType}.json** - Frontend-Integration
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"filterList": [
|
||||||
|
"__APPEND__",
|
||||||
|
{
|
||||||
|
"isReportFilter": true,
|
||||||
|
"name": "reportFilterXXXXXXXXXX",
|
||||||
|
"accessDataList": [
|
||||||
|
{
|
||||||
|
"teamIdList": ["team-id-here"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **i18n/{Language}/{EntityType}.json** - Übersetzungen
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"presetFilters": {
|
||||||
|
"reportFilterXXXXXXXXXX": "Filter-Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Report-Panels
|
||||||
|
|
||||||
|
Report-Panels zeigen Listen von Entitäten in Side-Panels der Detail-View an. Sie können Team-basierte Zugriffskontrolle haben.
|
||||||
|
|
||||||
|
#### Struktur:
|
||||||
|
|
||||||
|
**clientDefs/{EntityType}.json** - Panel-Definition
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sidePanels": {
|
||||||
|
"detail": [
|
||||||
|
"__APPEND__",
|
||||||
|
{
|
||||||
|
"isReportPanel": true,
|
||||||
|
"name": "reportPanelXXXXXXXXXX",
|
||||||
|
"label": "Panel-Titel",
|
||||||
|
"view": "advanced:views/report-panel/record/panels/report-panel-side",
|
||||||
|
"reportPanelId": "reportPanelIdHere",
|
||||||
|
"reportType": "List",
|
||||||
|
"reportEntityType": "EntityType",
|
||||||
|
"displayType": "List",
|
||||||
|
"displayTotal": false,
|
||||||
|
"displayOnlyTotal": false,
|
||||||
|
"useSiMultiplier": true,
|
||||||
|
"accessDataList": [
|
||||||
|
{
|
||||||
|
"scope": "EntityType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"teamIdList": ["team-id-here"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Wichtige Eigenschaften:
|
||||||
|
|
||||||
|
- **`isReportFilter`/`isReportPanel`**: Markiert den Eintrag als Report-Element
|
||||||
|
- **`accessDataList`**: Array von Zugriffsbedingungen (Team-IDs, Scopes)
|
||||||
|
- **`reportType`**: `"List"` für Listen-Reports
|
||||||
|
- **`displayType`**: Anzeige-Typ (`"List"`, `"Chart"`, etc.)
|
||||||
|
- **`view`**: Spezielle Report-Panel-View aus dem Advanced Pack
|
||||||
|
- **`__APPEND__`**: Erweitert bestehende Arrays statt sie zu überschreiben
|
||||||
|
|
||||||
|
### Best Practices:
|
||||||
|
|
||||||
|
1. **Naming Convention**:
|
||||||
|
- Filter: `reportFilter{uniqueId}` (z.B. `reportFilter6972174b6540731c1`)
|
||||||
|
- Panels: `reportPanel{uniqueId}` (z.B. `reportPanel697216784307d43ad`)
|
||||||
|
|
||||||
|
2. **Team-basierte Zugriffskontrolle**:
|
||||||
|
- Definiere `teamIdList` in `accessDataList` für eingeschränkten Zugriff
|
||||||
|
- Mehrere Teams können kombiniert werden
|
||||||
|
|
||||||
|
3. **Mehrsprachigkeit**:
|
||||||
|
- Labels in allen Sprachen definieren (de_DE, en_US)
|
||||||
|
- Fehlerhafte Labels können zu UI-Problemen führen
|
||||||
|
|
||||||
|
4. **Datei-Abhängigkeiten**:
|
||||||
|
- Report-Filter benötigen 4 Dateien: entityDefs, selectDefs, clientDefs, i18n
|
||||||
|
- Report-Panels benötigen 1 Datei: clientDefs
|
||||||
|
- Fehlende Dateien führen zu nicht-funktionalen Filtern
|
||||||
|
|
||||||
|
5. **Placeholder-Dateien**:
|
||||||
|
- `logicDefs/{EntityType}.json` kann als leeres Objekt `{}` angelegt werden
|
||||||
|
- Ermöglicht zukünftige Erweiterungen ohne Struktur-Änderungen
|
||||||
|
|
||||||
|
### Beispiel-Implementation:
|
||||||
|
|
||||||
|
**Szenario**: UserTask-Filter für Team "vermieterhelden"
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# entityDefs/BpmnUserTask.json
|
||||||
|
{
|
||||||
|
"collection": {
|
||||||
|
"filters": {
|
||||||
|
"reportFilter6972174b6540731c1": {
|
||||||
|
"isReportFilter": true,
|
||||||
|
"id": "6972174b6540731c1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# selectDefs/BpmnUserTask.json
|
||||||
|
{
|
||||||
|
"primaryFilterClassNameMap": {
|
||||||
|
"reportFilter6972174b6540731c1": "Espo\\Modules\\Advanced\\Classes\\Select\\Common\\PrimaryFilters\\ReportFilter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# clientDefs/BpmnUserTask.json
|
||||||
|
{
|
||||||
|
"filterList": [
|
||||||
|
"__APPEND__",
|
||||||
|
{
|
||||||
|
"isReportFilter": true,
|
||||||
|
"name": "reportFilter6972174b6540731c1",
|
||||||
|
"accessDataList": [
|
||||||
|
{
|
||||||
|
"teamIdList": ["68da9bdd622c9958a"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# i18n/en_US/BpmnUserTask.json
|
||||||
|
{
|
||||||
|
"presetFilters": {
|
||||||
|
"reportFilter6972174b6540731c1": "UserTask"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting:
|
||||||
|
|
||||||
|
- **Filter erscheint nicht**: Prüfe ob alle 4 Dateien existieren und Rebuild durchgeführt wurde
|
||||||
|
- **Zugriffsfehler**: Überprüfe `teamIdList` und User-Team-Zuordnung
|
||||||
|
- **Leere Liste**: Report-Definition in DB prüfen (Tabelle: `report`)
|
||||||
|
- **Falsches Label**: i18n-Dateien in allen Sprachen prüfen
|
||||||
|
|
||||||
|
### Nach Änderungen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebuild durchführen
|
||||||
|
docker exec espocrm php /var/www/html/command.php Rebuild
|
||||||
|
|
||||||
|
# Oder Check-Script verwenden
|
||||||
|
./custom/scripts/check_and_rebuild.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Portal-Freigabe-System
|
||||||
|
|
||||||
Um Entitäten für Portalnutzer (Contact-Entität) freizugeben, wurde ein konsistentes Freigabe-System implementiert:
|
Um Entitäten für Portalnutzer (Contact-Entität) freizugeben, wurde ein konsistentes Freigabe-System implementiert:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"presetFilters": {
|
||||||
|
"reportFilter6972174b6540731c1": "UserTask"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,6 @@
|
|||||||
"_delimiter_": {
|
"_delimiter_": {
|
||||||
"disabled": true
|
"disabled": true
|
||||||
},
|
},
|
||||||
"tasks": {
|
|
||||||
"disabled": true
|
|
||||||
},
|
|
||||||
"default": {
|
"default": {
|
||||||
"index": 0
|
"index": 0
|
||||||
},
|
},
|
||||||
@@ -13,5 +10,8 @@
|
|||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"index": 2
|
"index": 2
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
"index": 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"sidePanels": {
|
||||||
|
"detail": [
|
||||||
|
"__APPEND__",
|
||||||
|
{
|
||||||
|
"isReportPanel": true,
|
||||||
|
"name": "reportPanel697216784307d43ad",
|
||||||
|
"label": "uSERtASKSs",
|
||||||
|
"view": "advanced:views/report-panel/record/panels/report-panel-side",
|
||||||
|
"reportPanelId": "697216784307d43ad",
|
||||||
|
"reportType": "List",
|
||||||
|
"reportEntityType": "BpmnUserTask",
|
||||||
|
"displayType": "List",
|
||||||
|
"displayTotal": false,
|
||||||
|
"displayOnlyTotal": false,
|
||||||
|
"useSiMultiplier": true,
|
||||||
|
"accessDataList": [
|
||||||
|
{
|
||||||
|
"scope": "BpmnUserTask"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"teamIdList": [
|
||||||
|
"68da9bdd622c9958a"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"filterList": [
|
||||||
|
"__APPEND__",
|
||||||
|
{
|
||||||
|
"isReportFilter": true,
|
||||||
|
"name": "reportFilter6972174b6540731c1",
|
||||||
|
"accessDataList": [
|
||||||
|
{
|
||||||
|
"teamIdList": [
|
||||||
|
"68da9bdd622c9958a"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"collection": {
|
||||||
|
"filters": {
|
||||||
|
"reportFilter6972174b6540731c1": {
|
||||||
|
"isReportFilter": true,
|
||||||
|
"id": "6972174b6540731c1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"primaryFilterClassNameMap": {
|
||||||
|
"reportFilter6972174b6540731c1": "Espo\\Modules\\Advanced\\Classes\\Select\\Common\\PrimaryFilters\\ReportFilter"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -348,8 +348,8 @@ return [
|
|||||||
0 => 'youtube.com',
|
0 => 'youtube.com',
|
||||||
1 => 'google.com'
|
1 => 'google.com'
|
||||||
],
|
],
|
||||||
'cacheTimestamp' => 1768949725,
|
'cacheTimestamp' => 1769084905,
|
||||||
'microtime' => 1768949725.049459,
|
'microtime' => 1769084905.531304,
|
||||||
'siteUrl' => 'https://crm.bitbylaw.com',
|
'siteUrl' => 'https://crm.bitbylaw.com',
|
||||||
'fullTextSearchMinLength' => 4,
|
'fullTextSearchMinLength' => 4,
|
||||||
'appTimestamp' => 1768843902,
|
'appTimestamp' => 1768843902,
|
||||||
|
|||||||
Reference in New Issue
Block a user