Update CSS for 'vorzusch1Instanz' highlighting and adjust cache timestamps in config
This commit is contained in:
164
README.md
164
README.md
@@ -1117,4 +1117,166 @@ Um Entitäten für Portalnutzer (Contact-Entität) freizugeben, wurde ein konsis
|
||||
- `selectPrimaryFilterName: "portalUsers"` filtert automatisch auf Portal-User
|
||||
- Tab "Freigabe für" sollte immer der erste Tab im Bottom-Panel sein (index: 0)
|
||||
- Style "warning" hebt das Panel visuell hervor
|
||||
- Nach Änderungen immer Rebuild durchführen und beide Seiten der Relationship definieren
|
||||
- Nach Änderungen immer Rebuild durchführen und beide Seiten der Relationship definieren
|
||||
|
||||
---
|
||||
|
||||
## Custom JavaScript & CSS Integration
|
||||
|
||||
### JavaScript-Module einbinden
|
||||
|
||||
EspoCRM verwendet AMD/RequireJS für JavaScript-Module. Custom JavaScript-Dateien werden in `client/custom/src/` abgelegt.
|
||||
|
||||
**Beispiel: RVG-Gebührenrechner für CVmhErstgespraech**
|
||||
|
||||
**1. Modul erstellen** (`client/custom/src/modules/rvg-calculator.js`):
|
||||
```javascript
|
||||
define('custom:modules/rvg-calculator', [], function () {
|
||||
return {
|
||||
kalkuliereKosten: function(streitwert, anzahlKlaeger, anzahlBeklagte, ustProzent) {
|
||||
// Berechnungslogik
|
||||
return { /* Ergebnisobjekt */ };
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
**2. Custom Field View erstellen** (`client/custom/src/views/{entity}/fields/{fieldname}.js`):
|
||||
```javascript
|
||||
define('custom:views/c-vmh-erstgespraech/fields/rvg-calculated', [
|
||||
'views/fields/currency',
|
||||
'custom:modules/rvg-calculator'
|
||||
], function (Dep, RvgCalculator) {
|
||||
return Dep.extend({
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
this.listenTo(this.model, 'change:streitwert change:anzahlVermieter', this.calculate);
|
||||
this.listenTo(this.model, 'sync', this.calculate); // Initial load
|
||||
},
|
||||
calculate: function () {
|
||||
var result = RvgCalculator.kalkuliereKosten(/*...*/);
|
||||
this.model.set('kostenRaeumungsantrag', result.kostenRaeumungsantrag);
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**3. In entityDefs registrieren**:
|
||||
```json
|
||||
{
|
||||
"fields": {
|
||||
"vergleich1InstanzGk": {
|
||||
"type": "currency",
|
||||
"readOnly": true,
|
||||
"view": "custom:views/c-vmh-erstgespraech/fields/rvg-calculated"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Wichtige Patterns:**
|
||||
- `listenTo(model, 'sync', callback)` - Für initiale Berechnung beim Laden
|
||||
- `listenTo(model, 'change:field1 change:field2', callback)` - Für Reaktivität
|
||||
- `calculating` Flag verhindert Rekursion bei `model.set()`
|
||||
- Browser-Cache: Hard Refresh (Ctrl+Shift+R) nach JS-Änderungen erforderlich
|
||||
|
||||
### CSS-Manipulation & Feld-Hervorhebung
|
||||
|
||||
EspoCRM erlaubt Custom CSS über Metadata-Registrierung.
|
||||
|
||||
**1. CSS-Datei erstellen** (`client/custom/css/erstgespraech-highlight.css`):
|
||||
```css
|
||||
/* Feld-Selektor über data-name Attribut */
|
||||
.detail .cell[data-name="vorzusch1Instanz"] {
|
||||
background-color: #d4edda;
|
||||
padding: 10px;
|
||||
border-bottom: 4px solid #28a745;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.detail .cell[data-name="vorzusch1Instanz"] .numeric-text {
|
||||
font-weight: bold;
|
||||
color: #155724;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
```
|
||||
|
||||
**2. CSS in Metadata registrieren** (`custom/Espo/Custom/Resources/metadata/app/client.json`):
|
||||
```json
|
||||
{
|
||||
"cssList": [
|
||||
"__APPEND__",
|
||||
"client/custom/css/erstgespraech-highlight.css"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**3. Rebuild durchführen** - CSS wird in gecachtes Bundle integriert
|
||||
|
||||
**CSS-Targeting-Strategien:**
|
||||
- **Feld-spezifisch:** `.cell[data-name="fieldName"]`
|
||||
- **Entity-spezifisch:** `body[data-controller="CVmhErstgespraech"]`
|
||||
- **View-spezifisch:** `.detail` (Detail-View), `.edit` (Edit-View), `.list` (List-View)
|
||||
- **Label vs. Value:**
|
||||
- `.label-text` - Feldlabel
|
||||
- `.numeric-text` / `.text-default` - Feldwert
|
||||
- `.field[data-name="..."]` - Field-Container
|
||||
|
||||
**HTML-Struktur (Referenz):**
|
||||
```html
|
||||
<div class="cell col-sm-4 form-group" data-name="vorzusch1Instanz">
|
||||
<label class="control-label">
|
||||
<span class="label-text">Vorauszuschießende Kosten I. Inst.</span>
|
||||
</label>
|
||||
<div class="field" data-name="vorzusch1Instanz">
|
||||
<span class="numeric-text">3.067,63</span> €
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Best Practices:**
|
||||
- CSS-Dateien in `client/custom/css/` oder `client/custom/modules/{module}/css/` ablegen
|
||||
- `__APPEND__` verwendet um Core-CSS zu erweitern, nicht zu überschreiben
|
||||
- Spezifische Selektoren verwenden um Kollisionen zu vermeiden
|
||||
- Nach CSS-Änderungen: Rebuild + Hard Refresh (Browser Cache löschen)
|
||||
|
||||
### RVG-Gebührenrechner (CVmhErstgespraech)
|
||||
|
||||
**Implementierung:** Automatische Berechnung von Anwalts- und Gerichtskosten nach RVG 2025 / GKG
|
||||
|
||||
**Komponenten:**
|
||||
1. **Calculator-Modul** (`client/custom/src/modules/rvg-calculator.js`):
|
||||
- `getWertgebuehr()`: RVG 2025 Tabelle (65 Stufen, €500-€2M)
|
||||
- `getGerichtsgebuehr()`: GKG progressive Berechnung
|
||||
- `getZuschlag()`: §7 RVG Personenzuschlag (+0.3 pro Person, max +2.0)
|
||||
- `kalkuliereKosten()`: Hauptfunktion für alle Szenarien
|
||||
|
||||
2. **Custom Field Views**:
|
||||
- `rvg-calculated.js`: Trigger für alle Berechnungen
|
||||
- `beruecksichtigte-personen.js`: Live-Text-Anzeige "X Vermieter, Y Mieter, Z Dritte"
|
||||
- `warmmiete.js`: Kaltmiete + BK-Vorauszahlung + BK-Pauschale
|
||||
- `streitwert.js`: (Kaltmiete + BK-Pauschale) × 12
|
||||
|
||||
3. **Berechnete Felder** (readOnly currency fields):
|
||||
- Außergerichtliche Gebühren: 1.3 + Zuschlag + Pauschale 20% (max 20€)
|
||||
- Kosten Räumungsantrag: 0.3 + 0.3/Person + Pauschale
|
||||
- 1. Instanz: 3.0 GK + RA-Kosten (1.3 Verf + 1.2 Term + Pauschale)
|
||||
- Säumnisszenario: 3.0 GK + reduzierte RA (0.5 Term statt 1.2)
|
||||
- Vergleichsszenario: 1.0 GK + RA (1.3 Verf + 1.2 Term + 1.0 Vergl)
|
||||
|
||||
4. **USt-Satz Handling**:
|
||||
- Enum Field: "0" / "19" (String, nicht Integer!)
|
||||
- Konvertierung: `parseInt(ustSatz)` → dann `/100` im Calculator
|
||||
- **Wichtig:** Expliziter Null-Check nötig, `0` ist falsy in `|| 19`
|
||||
|
||||
5. **Reaktivität**:
|
||||
- Listener auf: streitwert, anzahlVermieter, anzahlMieter, anzahlSonstigeVolljhrigeBewohner, ustSatz
|
||||
- Initial berechnen mit `'sync'` Event
|
||||
- `calculating` Flag verhindert Rekursion
|
||||
|
||||
**Layout-Panels:**
|
||||
- **Gebührenberechnung** (primary, info-note): Standard 1. Instanz Kosten
|
||||
- **Säumnisszenario I. Inst.** (primary, success-note): Beklagte erscheint nicht
|
||||
- **Vergleichsszenario I. Inst.** (primary, success-note): Einigung vor Urteil
|
||||
|
||||
**Hervorhebung:** "Vorauszuschießende Kosten I. Inst." wird via CSS hervorgehoben (grüner Hintergrund, fetter Wert)
|
||||
Reference in New Issue
Block a user