Merge detached HEAD: Add Kündigung entity with complete layouts and fix all false placeholders in detail.json files for EspoCRM 7.x compatibility

This commit is contained in:
2026-01-25 10:31:03 +01:00
38 changed files with 1021 additions and 138 deletions

View File

@@ -177,50 +177,92 @@ Basierend auf der Analyse von Git-Commits und praktischen Erfahrungen treten bes
#### 2. Layout-Strukturfehler #### 2. Layout-Strukturfehler
**Problem:** Unnötige oder falsche Array-Elemente in Layouts, die zu UI-Problemen führen. **Problem:** Falsche Platzhalter und Strukturen in Layouts führen zu UI-Problemen.
**⚠️ KRITISCH für EspoCRM 7.x:**
In EspoCRM 7.x ist `false` als Platzhalter **NICHT MEHR ERLAUBT**!
**Symptome:** **Symptome:**
- Layout wird nicht geladen, Fehlermeldung in UI
- Felder werden nicht korrekt angeordnet - Felder werden nicht korrekt angeordnet
- Leere Bereiche in Detail-Views - Leere Bereiche in Detail-Views
- Inkonsistente Spaltenbreiten - bottomPanelsDetail funktioniert nicht
**❌ FALSCH:** **❌ FALSCH (EspoCRM 7.x):**
```json ```json
// layouts/Entity/detail.json // layouts/Entity/detail.json
{ {
"rows": [ "rows": [
[ [
{"name": "field1"} {"name": "field1"},
],
[
{"name": "field2"}, {"name": "field2"},
false // ← Unnötiges false-Element! false, // ← DEPRECATED! Funktioniert in 7.x NICHT!
false // ← Verursacht Layout-Fehler!
] ]
] ]
} }
``` ```
**✅ RICHTIG:** **✅ RICHTIG (EspoCRM 7.x):**
```json ```json
{ {
"rows": [ "rows": [
[ [
{"name": "field1"}, {"name": "field1"},
{"name": "field2"} // Beide in einer Row {"name": "field2"},
{}, // ← Leeres Objekt verwenden!
{} // ← Funktioniert in 7.x korrekt
] ]
] ]
} }
``` ```
**❌ FALSCH - bottomPanelsDetail.json als Array:**
```json
// layouts/Entity/bottomPanelsDetail.json
[
{"name": "contacts"},
{"name": "documents"}
]
```
**✅ RICHTIG - bottomPanelsDetail.json als Objekt:**
```json
{
"contacts": {
"index": 0,
"sticked": true,
"style": "warning"
},
"_tabBreak_0": {
"index": 1,
"columnBreak": true
},
"documents": {
"index": 2
},
"activities": {
"disabled": true
},
"history": {
"disabled": true
}
}
```
**Häufige Layout-Fehler:** **Häufige Layout-Fehler:**
-**`false` als Platzhalter** (seit EspoCRM 7.x nicht mehr unterstützt!)
- ❌ Width-Attribute in Detail-Layouts (nur für List-Layouts!) - ❌ Width-Attribute in Detail-Layouts (nur für List-Layouts!)
-Leere Objekte `{}` oder `false` in Rows -bottomPanelsDetail.json als Array statt Objekt
- ❌ Index nicht angepasst nach Entfernung von Panels (bottomPanelsDetail) - ❌ Index nicht angepasst nach Entfernung von Panels
**Best Practice:** **Best Practice:**
- **Immer `{}` statt `false`** für leere Zellen in detail.json verwenden
- Width nur in `list.json` und `listSmall.json` verwenden - Width nur in `list.json` und `listSmall.json` verwenden
- Rows immer vollständig füllen oder Felder kombinieren - bottomPanelsDetail.json **MUSS** Objekt-Format haben
- Rows immer mit 4 Spalten füllen (nutze `{}` zum Auffüllen)
- Nach Panel-Entfernung Indices neu nummerieren - Nach Panel-Entfernung Indices neu nummerieren
- `_tabBreak_{index}` verwenden um Panels auf verschiedene Tabs zu verteilen
--- ---

View File

@@ -44,7 +44,7 @@ class CVmhMietverhltnis extends \Espo\Core\Templates\Controllers\BasePlus
} }
/** /**
* POST Action: Initiate termination from Mietverhältnis * POST Action: Initiate termination (Kündigung) from Mietverhältnis
*/ */
public function postActionInitiateTermination(Request $request): array public function postActionInitiateTermination(Request $request): array
{ {

View File

@@ -12,8 +12,8 @@
"vmhRumungsklagesBeklagte": "Beklagte", "vmhRumungsklagesBeklagte": "Beklagte",
"mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosKlaeger": "Mietinkasso (Kläger)",
"mietinkassosBeklagte": "Mietinkasso (Beklagte)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)",
"kuendigungenVermieter": "Kündigungen (Vermieter)", "kndigungenKuendiger": "Kündigungen (Kündigende)",
"kuendigungenMieter": "Kündigungen (Mieter)", "kndigungenGekuendigte": "Kündigungen (Gekündigte)",
"adressens": "Adressen", "adressens": "Adressen",
"calls1": "Anrufe", "calls1": "Anrufe",
"contactsBeteiligte": "Freigegebene Nutzer", "contactsBeteiligte": "Freigegebene Nutzer",
@@ -35,8 +35,8 @@
"vmhRumungsklagesBeklagte": "Beklagte", "vmhRumungsklagesBeklagte": "Beklagte",
"mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosKlaeger": "Mietinkasso (Kläger)",
"mietinkassosBeklagte": "Mietinkasso (Beklagte)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)",
"kuendigungenVermieter": "Kündigungen (Vermieter)", "kndigungenKuendiger": "Kündigungen (Kündigende)",
"kuendigungenMieter": "Kündigungen (Mieter)", "kndigungenGekuendigte": "Kündigungen (Gekündigte)",
"adressens": "Adressen", "adressens": "Adressen",
"calls1": "Anrufe", "calls1": "Anrufe",
"contactsBeteiligte": "Freigegebene Nutzer", "contactsBeteiligte": "Freigegebene Nutzer",

View File

@@ -14,7 +14,9 @@
"vmhRumungsklagesdokumente": "Räumungsklagen", "vmhRumungsklagesdokumente": "Räumungsklagen",
"kuendigungDokumente": "Kündigungen", "kuendigungDokumente": "Kündigungen",
"beteiligte2dokumente": "Beteiligte", "beteiligte2dokumente": "Beteiligte",
"mietobjekt2dokumente": "Mietobjekte" "mietobjekt2dokumente": "Mietobjekte",
"mietinkassosdokumente": "Mietinkasso",
"kndigungensdokumente": "Kündigungen"
}, },
"links": { "links": {
"contactsvmhdokumente": "Freigegebene Nutzer", "contactsvmhdokumente": "Freigegebene Nutzer",
@@ -24,7 +26,8 @@
"kuendigungDokumente": "Kündigungen", "kuendigungDokumente": "Kündigungen",
"beteiligte2dokumente": "Beteiligte", "beteiligte2dokumente": "Beteiligte",
"mietobjekt2dokumente": "Mietobjekte", "mietobjekt2dokumente": "Mietobjekte",
"mietinkassosdokumente": "Mietinkasso" "mietinkassosdokumente": "Mietinkasso",
"kndigungensdokumente": "Kündigungen"
}, },
"labels": { "labels": {
"Create CDokumente": "Dokument erstellen" "Create CDokumente": "Dokument erstellen"

View File

@@ -1,9 +1,94 @@
{ {
"links": { "links": {
"meetings": "Termine",
"calls": "Anrufe", "calls": "Anrufe",
"tasks": "Aufgaben" "tasks": "Aufgaben",
"collaborators": "Mitarbeiter",
"vmhMietverhltnises": "Mietverhältnisse",
"mietobjekte": "Mietobjekte",
"kuendiger": "Kündigende (Vermieter)",
"gekuendigte": "Gekündigte (Mieter)",
"dokumenteskuendigung": "Dokumente",
"contactsKuendigung": "Portal-Freigaben"
}, },
"labels": { "labels": {
"Create CKndigung": "Kündigung erstellen" "Create CKndigung": "Kündigung erstellen",
"CKndigung": "Kündigung"
},
"fields": {
"name": "Name",
"description": "Beschreibung",
"assignedUser": "Zugewiesen",
"teams": "Teams",
"createdAt": "Erstellt am",
"modifiedAt": "Geändert am",
"createdBy": "Erstellt von",
"modifiedBy": "Geändert von",
"freigeschalteteNutzer": "Freigeschaltete Nutzer",
"collaborators": "Mitarbeiter",
"advowareAktenzeichen": "Advoware Aktenzeichen",
"betnr": "Betreuernummer",
"advowareLastSync": "Letzter Sync",
"syncStatus": "Sync Status",
"kuendigungsart": "Kündigungsart",
"kuendigungsgrund": "Kündigungsgrund",
"kuendigungsgrundDetails": "Kündigungsgrund Details",
"kuendigungsdatum": "Kündigungsdatum",
"zustelldatum": "Zustelldatum",
"kuendigungsfrist": "Kündigungsfrist",
"beendigungstermin": "Beendigungstermin",
"status": "Status",
"zustellart": "Zustellart",
"reaktionMieter": "Reaktion Mieter",
"notizen": "Notizen",
"rueckstandMiete": "Rückstand Miete",
"rueckstandNebenkosten": "Rückstand Nebenkosten",
"sonstigeForderungen": "Sonstige Forderungen",
"aussergerichtlicheGebuehren13": "Außergerichtliche Gebühren (1,3)"
},
"options": {
"kuendigungsart": {
"Ordentlich": "Ordentlich",
"Ausserordentlich": "Außerordentlich",
"Fristlos": "Fristlos",
"AufgabeerklärungMieter": "Aufgabeerklärung Mieter"
},
"kuendigungsgrund": {
"Zahlungsverzug": "Zahlungsverzug",
"Pflichtverletzung": "Pflichtverletzung",
"Eigenbedarf": "Eigenbedarf",
"Verwertung": "Verwertung",
"VerhaltensbedingteLaermruhestoerung": "Verhaltensbedingte Lärm-/Ruhestörung",
"BeschaedigungSubstanz": "Beschädigung der Substanz",
"UnerlaubteUntervermietung": "Unerlaubte Untervermietung",
"StoerendeGeschaeftsfuehrung": "Störende Geschäftsführung",
"Sonstiges": "Sonstiges"
},
"status": {
"Entwurf": "Entwurf",
"Versendet": "Versendet",
"Zugestellt": "Zugestellt",
"Akzeptiert": "Akzeptiert",
"Bestritten": "Bestritten",
"Abgewickelt": "Abgewickelt",
"Zurückgezogen": "Zurückgezogen"
},
"zustellart": {
"Einschreiben": "Einschreiben",
"Persoenlich": "Persönlich",
"Gerichtsvollzieher": "Gerichtsvollzieher",
"Oeffentlich": "Öffentlich",
"Sonstiges": "Sonstiges"
},
"syncStatus": {
"clean": "Synchronisiert",
"unclean": "Änderungen ausstehend",
"failed": "Fehler"
}
},
"tooltips": {
"advowareAktenzeichen": "Aktenzeichen aus Advoware für die Synchronisation",
"betnr": "Betreuernummer aus Advoware",
"syncStatus": "Status der Synchronisation mit Advoware"
} }
} }

View File

@@ -6,8 +6,7 @@
"vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)", "vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)",
"vmhMietverhltnises": "Mietverhältnisse", "vmhMietverhltnises": "Mietverhältnisse",
"contactsMietobjekt": "Freigegebene Nutzer", "contactsMietobjekt": "Freigegebene Nutzer",
"dokumentesMietobjekt": "Dokumente", "dokumentesMietobjekt": "Dokumente"
"kuendigungen": "Kündigungen"
}, },
"links": { "links": {
"vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)", "vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)",
@@ -15,7 +14,7 @@
"contact2mietobjekt": "Kontakte", "contact2mietobjekt": "Kontakte",
"vmhRumungsklages": "Räumungsklagen", "vmhRumungsklages": "Räumungsklagen",
"mietinkassos": "Mietinkasso", "mietinkassos": "Mietinkasso",
"kuendigungen": "Kündigungen", "kndigungen": "Kündigungen",
"contactsMietobjekt": "Freigegebene Nutzer", "contactsMietobjekt": "Freigegebene Nutzer",
"dokumentesMietobjekt": "Dokumente" "dokumentesMietobjekt": "Dokumente"
}, },

View File

@@ -13,7 +13,7 @@
"warmmiete": "Warmmiete", "warmmiete": "Warmmiete",
"vmhRumungsklages": "Räumungsklagen", "vmhRumungsklages": "Räumungsklagen",
"mietinkassos": "Mietinkasso", "mietinkassos": "Mietinkasso",
"kuendigungen": "Kündigungen", "kndigungen": "Kündigungen",
"vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtevermieter": "Vermieter",
"vmhbeteiligtemieter": "Mieter", "vmhbeteiligtemieter": "Mieter",
"contactsMietverhltnis": "Freigegebene Nutzer", "contactsMietverhltnis": "Freigegebene Nutzer",
@@ -34,7 +34,7 @@
"tasks": "Aufgaben", "tasks": "Aufgaben",
"vmhRumungsklages": "Räumungsklagen", "vmhRumungsklages": "Räumungsklagen",
"mietinkassos": "Mietinkasso", "mietinkassos": "Mietinkasso",
"kuendigungen": "Kündigungen", "kndigungen": "Kündigungen",
"vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtevermieter": "Vermieter",
"vmhbeteiligtemieter": "Mieter", "vmhbeteiligtemieter": "Mieter",
"contactsMietverhltnis": "Freigegebene Nutzer", "contactsMietverhltnis": "Freigegebene Nutzer",
@@ -56,7 +56,7 @@
"confirmRentCollection": "Möchten Sie wirklich ein Mietinkasso aus diesem Mietverhältnis einleiten?", "confirmRentCollection": "Möchten Sie wirklich ein Mietinkasso aus diesem Mietverhältnis einleiten?",
"rentCollectionCreated": "Mietinkasso wurde erfolgreich erstellt", "rentCollectionCreated": "Mietinkasso wurde erfolgreich erstellt",
"rentCollectionError": "Fehler beim Erstellen des Mietinkassos", "rentCollectionError": "Fehler beim Erstellen des Mietinkassos",
"confirmTermination": "Möchten Sie wirklich eine Kündigung für dieses Mietverhältnis erstellen?", "confirmTermination": "Möchten Sie wirklich eine Kündigung aus diesem Mietverhältnis erstellen?",
"terminationCreated": "Kündigung wurde erfolgreich erstellt", "terminationCreated": "Kündigung wurde erfolgreich erstellt",
"terminationError": "Fehler beim Erstellen der Kündigung" "terminationError": "Fehler beim Erstellen der Kündigung"
} }

View File

@@ -14,8 +14,8 @@
"cMietobjekteContactPortal": "Mietobjekte (Portal)", "cMietobjekteContactPortal": "Mietobjekte (Portal)",
"cAdressenContact": "Adressen", "cAdressenContact": "Adressen",
"cVmhRumungsklageContact": "Räumungsklagen (Portal)", "cVmhRumungsklageContact": "Räumungsklagen (Portal)",
"cMietinkassoContact": "Mietinkasso (Portal)", "cMietinkassoContact": "Mietinkasso",
"cKuendigungContact": "Kündigungen (Portal)", "cKuendigungContact": "Kündigungen",
"cBankverbindungenContact": "Bankverbindungen" "cBankverbindungenContact": "Bankverbindungen"
}, },
"links": { "links": {
@@ -31,7 +31,7 @@
"cAdressenContact": "Adressen", "cAdressenContact": "Adressen",
"cVmhRumungsklageContact": "Räumungsklagen (Portal)", "cVmhRumungsklageContact": "Räumungsklagen (Portal)",
"cMietinkassoContact": "Mietinkasso", "cMietinkassoContact": "Mietinkasso",
"cKuendigungContact": "Kündigungen (Portal)", "cKuendigungContact": "Kündigungen",
"cBankverbindungenContact": "Bankverbindungen" "cBankverbindungenContact": "Bankverbindungen"
}, },
"options": { "options": {

View File

@@ -11,8 +11,8 @@
"vmhRumungsklagesKlaeger": "Plaintiff", "vmhRumungsklagesKlaeger": "Plaintiff",
"mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosKlaeger": "Rent Collection (Plaintiff)",
"mietinkassosBeklagte": "Rent Collection (Defendant)", "mietinkassosBeklagte": "Rent Collection (Defendant)",
"kuendigungenVermieter": "Terminations (Landlord)", "kndigungenKuendiger": "Terminations (Terminating Party)",
"kuendigungenMieter": "Terminations (Tenant)", "kndigungenGekuendigte": "Terminations (Terminated Party)",
"contactsBeteiligte": "Portal Users", "contactsBeteiligte": "Portal Users",
"dokumentesBeteiligte": "Documents" "dokumentesBeteiligte": "Documents"
}, },
@@ -29,8 +29,8 @@
"vmhRumungsklagesKlaeger": "Plaintiff", "vmhRumungsklagesKlaeger": "Plaintiff",
"mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosKlaeger": "Rent Collection (Plaintiff)",
"mietinkassosBeklagte": "Rent Collection (Defendant)", "mietinkassosBeklagte": "Rent Collection (Defendant)",
"kuendigungenVermieter": "Terminations (Landlord)", "kndigungenKuendiger": "Terminations (Terminating Party)",
"kuendigungenMieter": "Terminations (Tenant)", "kndigungenGekuendigte": "Terminations (Terminated Party)",
"contactsBeteiligte": "Portal Users", "contactsBeteiligte": "Portal Users",
"dokumentesBeteiligte": "Documents", "dokumentesBeteiligte": "Documents",
"bankverbindungens": "Bank Accounts" "bankverbindungens": "Bank Accounts"

View File

@@ -11,7 +11,9 @@
"md5sum": "MD5 Checksum", "md5sum": "MD5 Checksum",
"sha256": "SHA256 Checksum", "sha256": "SHA256 Checksum",
"beteiligte2dokumente": "Parties", "beteiligte2dokumente": "Parties",
"mietobjekt2dokumente": "Properties" "mietobjekt2dokumente": "Properties",
"mietinkassosdokumente": "Rent Collection",
"kndigungensdokumente": "Terminations"
}, },
"links": { "links": {
"contactsvmhdokumente": "Portal Users", "contactsvmhdokumente": "Portal Users",
@@ -21,7 +23,8 @@
"kuendigungDokumente": "Terminations", "kuendigungDokumente": "Terminations",
"beteiligte2dokumente": "Parties", "beteiligte2dokumente": "Parties",
"mietobjekt2dokumente": "Properties", "mietobjekt2dokumente": "Properties",
"mietinkassosdokumente": "Rent Collection" "mietinkassosdokumente": "Rent Collection",
"kndigungensdokumente": "Terminations"
}, },
"labels": { "labels": {
"Create CDokumente": "Create Dokument" "Create CDokumente": "Create Dokument"

View File

@@ -1,12 +1,94 @@
{ {
"fields": { "fields": {
"name": "Name",
"description": "Description",
"assignedUser": "Assigned User",
"teams": "Teams",
"createdAt": "Created At",
"modifiedAt": "Modified At",
"createdBy": "Created By",
"modifiedBy": "Modified By",
"freigeschalteteNutzer": "Authorized Users",
"collaborators": "Collaborators",
"advowareAktenzeichen": "Advoware File Number",
"betnr": "Case Number",
"advowareLastSync": "Last Sync",
"syncStatus": "Sync Status",
"kuendigungsart": "Termination Type",
"kuendigungsgrund": "Termination Reason",
"kuendigungsgrundDetails": "Termination Reason Details",
"kuendigungsdatum": "Termination Date",
"zustelldatum": "Delivery Date",
"kuendigungsfrist": "Notice Period",
"beendigungstermin": "End Date",
"status": "Status",
"zustellart": "Delivery Method",
"reaktionMieter": "Tenant Response",
"notizen": "Notes",
"rueckstandMiete": "Rent Arrears",
"rueckstandNebenkosten": "Utility Arrears",
"sonstigeForderungen": "Other Claims",
"aussergerichtlicheGebuehren13": "Extrajudicial Fees (1.3)"
}, },
"links": { "links": {
"meetings": "Meetings", "meetings": "Meetings",
"calls": "Calls", "calls": "Calls",
"tasks": "Tasks" "tasks": "Tasks",
"collaborators": "Collaborators",
"vmhMietverhltnises": "Tenancies",
"mietobjekte": "Properties",
"kuendiger": "Terminating Party (Landlord)",
"gekuendigte": "Terminated Party (Tenant)",
"dokumenteskuendigung": "Documents",
"contactsKuendigung": "Portal Access"
}, },
"labels": { "labels": {
"Create CKndigung": "Create Kündigung" "Create CKndigung": "Create Termination",
"CKndigung": "Termination"
},
"options": {
"kuendigungsart": {
"Ordentlich": "Regular",
"Ausserordentlich": "Extraordinary",
"Fristlos": "Immediate",
"AufgabeerklärungMieter": "Tenant Surrender"
},
"kuendigungsgrund": {
"Zahlungsverzug": "Payment Default",
"Pflichtverletzung": "Breach of Contract",
"Eigenbedarf": "Owner's Need",
"Verwertung": "Exploitation",
"VerhaltensbedingteLaermruhestoerung": "Behavioral - Noise/Disturbance",
"BeschaedigungSubstanz": "Property Damage",
"UnerlaubteUntervermietung": "Unauthorized Subletting",
"StoerendeGeschaeftsfuehrung": "Disruptive Business Operations",
"Sonstiges": "Other"
},
"status": {
"Entwurf": "Draft",
"Versendet": "Sent",
"Zugestellt": "Delivered",
"Akzeptiert": "Accepted",
"Bestritten": "Disputed",
"Abgewickelt": "Settled",
"Zurückgezogen": "Withdrawn"
},
"zustellart": {
"Einschreiben": "Registered Mail",
"Persoenlich": "Personal Delivery",
"Gerichtsvollzieher": "Bailiff",
"Oeffentlich": "Public Notice",
"Sonstiges": "Other"
},
"syncStatus": {
"clean": "Synchronized",
"unclean": "Changes Pending",
"failed": "Failed"
}
},
"tooltips": {
"advowareAktenzeichen": "File number from Advoware for synchronization",
"betnr": "Case number from Advoware",
"syncStatus": "Synchronization status with Advoware"
} }
} }

View File

@@ -20,7 +20,7 @@
"contact2mietobjekt": "Contacts", "contact2mietobjekt": "Contacts",
"vmhRumungsklages": "Eviction Lawsuits", "vmhRumungsklages": "Eviction Lawsuits",
"mietinkassos": "Rent Collection", "mietinkassos": "Rent Collection",
"kuendigungen": "Terminations", "kndigungen": "Terminations",
"contactsMietobjekt": "Portal Users", "contactsMietobjekt": "Portal Users",
"dokumentesMietobjekt": "Documents" "dokumentesMietobjekt": "Documents"
}, },

View File

@@ -3,6 +3,7 @@
"status": "Status", "status": "Status",
"vmhRumungsklages": "Eviction Lawsuits", "vmhRumungsklages": "Eviction Lawsuits",
"mietinkassos": "Rent Collection", "mietinkassos": "Rent Collection",
"kndigungen": "Terminations",
"nutzungsart": "Type of Use", "nutzungsart": "Type of Use",
"kndigungsgrundWohnraum": "Reason for Termination", "kndigungsgrundWohnraum": "Reason for Termination",
"auszugsfrist": "Move-out Deadline", "auszugsfrist": "Move-out Deadline",
@@ -36,7 +37,7 @@
"tasks": "Tasks", "tasks": "Tasks",
"vmhRumungsklages": "Eviction Lawsuits", "vmhRumungsklages": "Eviction Lawsuits",
"mietinkassos": "Rent Collection", "mietinkassos": "Rent Collection",
"kuendigungen": "Terminations", "kndigungen": "Terminations",
"vmhbeteiligtevermieter": "Landlords", "vmhbeteiligtevermieter": "Landlords",
"vmhbeteiligtemieter": "Tenants", "vmhbeteiligtemieter": "Tenants",
"contactsMietverhltnis": "Portal Users", "contactsMietverhltnis": "Portal Users",
@@ -48,7 +49,8 @@
"labels": { "labels": {
"Create CVmhMietverhltnis": "Create Mietverhältnis", "Create CVmhMietverhltnis": "Create Mietverhältnis",
"Initiate Eviction": "Initiate Eviction Lawsuit", "Initiate Eviction": "Initiate Eviction Lawsuit",
"Initiate Rent Collection": "Initiate Rent Collection" "Initiate Rent Collection": "Initiate Rent Collection",
"Initiate Termination": "Create Termination"
}, },
"messages": { "messages": {
"confirmEviction": "Do you really want to initiate an eviction lawsuit from this tenancy?", "confirmEviction": "Do you really want to initiate an eviction lawsuit from this tenancy?",
@@ -56,7 +58,10 @@
"evictionError": "Error creating eviction lawsuit", "evictionError": "Error creating eviction lawsuit",
"confirmRentCollection": "Do you really want to initiate rent collection from this tenancy?", "confirmRentCollection": "Do you really want to initiate rent collection from this tenancy?",
"rentCollectionCreated": "Rent collection has been created successfully", "rentCollectionCreated": "Rent collection has been created successfully",
"rentCollectionError": "Error creating rent collection" "rentCollectionError": "Error creating rent collection",
"confirmTermination": "Do you really want to create a termination notice from this tenancy?",
"terminationCreated": "Termination notice has been created successfully",
"terminationError": "Error creating termination notice"
}, },
"options": { "options": {
"status": { "status": {

View File

@@ -8,7 +8,9 @@
"cVmhVermietersKontaktpersonen": "Vermieter", "cVmhVermietersKontaktpersonen": "Vermieter",
"cVmhMietverhltnisesContact": "Mietverhältnisse", "cVmhMietverhltnisesContact": "Mietverhältnisse",
"cDokumentesvmhcontact": "Dokumente", "cDokumentesvmhcontact": "Dokumente",
"cVmhmietobjekt2contact": "Mietobjekts" "cVmhmietobjekt2contact": "Mietobjekts",
"cMietinkassoContact": "Rent Collection",
"cKuendigungContact": "Terminations"
}, },
"links": { "links": {
"cVmhRumungsklages": "Räumungsklagen", "cVmhRumungsklages": "Räumungsklagen",
@@ -23,7 +25,7 @@
"cAdressenContact": "Addresses", "cAdressenContact": "Addresses",
"cVmhRumungsklageContact": "Eviction Lawsuits (Portal)", "cVmhRumungsklageContact": "Eviction Lawsuits (Portal)",
"cMietinkassoContact": "Rent Collection", "cMietinkassoContact": "Rent Collection",
"cKuendigungContact": "Terminations (Portal)", "cKuendigungContact": "Terminations",
"cBankverbindungenContact": "Bank Accounts" "cBankverbindungenContact": "Bank Accounts"
}, },
"options": { "options": {

View File

@@ -5,7 +5,7 @@
{ {
"name": "rechtsform" "name": "rechtsform"
}, },
false {}
], ],
[ [
{ {
@@ -19,13 +19,13 @@
{ {
"name": "disgTyp" "name": "disgTyp"
}, },
false {}
], ],
[ [
{ {
"name": "firmenname" "name": "firmenname"
}, },
false {}
], ],
[ [
{ {

View File

@@ -5,7 +5,7 @@
{ {
"name": "name" "name": "name"
}, },
false {}
] ]
], ],
"dynamicLogicVisible": null, "dynamicLogicVisible": null,
@@ -42,7 +42,7 @@
{ {
"name": "ydocumentuuid" "name": "ydocumentuuid"
}, },
false {}
] ]
], ],
"dynamicLogicVisible": null, "dynamicLogicVisible": null,

View File

@@ -0,0 +1,63 @@
{
"_delimiter_": {
"disabled": true
},
"activities": {
"disabled": true
},
"history": {
"disabled": true
},
"_tabBreak_0": {
"index": 0,
"tabBreak": true,
"tabLabel": "Freigegebene Nutzer"
},
"contactsKuendigung": {
"dynamicLogicVisible": null,
"style": "warning",
"dynamicLogicStyled": null,
"sticked": true,
"index": 1
},
"_tabBreak_1": {
"index": 2,
"tabBreak": true,
"tabLabel": "Kündigende"
},
"kuendiger": {
"index": 3
},
"_tabBreak_2": {
"index": 4,
"tabBreak": true,
"tabLabel": "Gekündigte"
},
"gekuendigte": {
"index": 5
},
"_tabBreak_3": {
"index": 6,
"tabBreak": true,
"tabLabel": "Mietverhältnisse"
},
"vmhMietverhltnises": {
"index": 7
},
"_tabBreak_4": {
"index": 8,
"tabBreak": true,
"tabLabel": "Dokumente"
},
"dokumenteskuendigung": {
"index": 9
},
"_tabBreak_5": {
"index": 10,
"tabBreak": true,
"tabLabel": "Mietobjekte"
},
"mietobjekte": {
"index": 11
}
}

View File

@@ -0,0 +1,11 @@
[
{
"name": ":assignedUser"
},
{
"name": "teams"
},
{
"name": "freigeschalteteNutzer"
}
]

View File

@@ -0,0 +1,114 @@
[
{
"label": "Kündigungsdetails",
"style": "default",
"tabBreak": false,
"rows": [
[
{
"name": "name"
},
{
"name": "kuendigungsart"
},
{
"name": "status"
},
{
"name": "advowareAktenzeichen"
}
],
[
{
"name": "kuendigungsgrund"
},
{
"name": "kuendigungsdatum"
},
{
"name": "zustelldatum"
},
{
"name": "zustellart"
}
],
[
{
"name": "kuendigungsfrist"
},
{
"name": "beendigungstermin"
},
{},
{}
],
[
{
"name": "kuendigungsgrundDetails"
}
]
]
},
{
"label": "Finanzielle Forderungen",
"style": "default",
"tabBreak": false,
"rows": [
[
{
"name": "rueckstandMiete"
},
{
"name": "rueckstandNebenkosten"
},
{
"name": "sonstigeForderungen"
},
{
"name": "aussergerichtlicheGebuehren13"
}
]
]
},
{
"label": "Notizen & Reaktion",
"style": "default",
"tabBreak": false,
"rows": [
[
{
"name": "reaktionMieter"
}
],
[
{
"name": "notizen"
}
],
[
{
"name": "description"
}
]
]
},
{
"label": "Advoware Sync",
"style": "default",
"tabBreak": true,
"tabLabel": "Erweitert",
"rows": [
[
{
"name": "betnr"
},
{
"name": "syncStatus"
},
{
"name": "advowareLastSync"
}
]
]
}
]

View File

@@ -0,0 +1,33 @@
[
{
"rows": [
[
{
"name": "name",
"noLabel": true
}
],
[
{
"name": "kuendigungsart"
},
{
"name": "status"
}
],
[
{
"name": "kuendigungsdatum"
},
{
"name": "beendigungstermin"
}
],
[
{
"name": "assignedUser"
}
]
]
}
]

View File

@@ -0,0 +1,31 @@
[
{
"name": "name",
"link": true,
"width": 20
},
{
"name": "kuendigungsart",
"width": 12
},
{
"name": "status",
"width": 12
},
{
"name": "kuendigungsdatum",
"width": 12
},
{
"name": "beendigungstermin",
"width": 12
},
{
"name": "assignedUser",
"width": 16
},
{
"name": "modifiedAt",
"width": 16
}
]

View File

@@ -0,0 +1,15 @@
[
{
"name": "name",
"link": true
},
{
"name": "kuendigungsart"
},
{
"name": "status"
},
{
"name": "kuendigungsdatum"
}
]

View File

@@ -19,7 +19,7 @@
{ {
"name": "kuendigungsservice" "name": "kuendigungsservice"
}, },
false {}
], ],
[ [
{ {

View File

@@ -13,7 +13,7 @@
{ {
"name": "lage" "name": "lage"
}, },
false {}
], ],
[ [
{ {

View File

@@ -44,9 +44,9 @@
{ {
"name": "besorgnisNichtRechtzeitigerAuszug" "name": "besorgnisNichtRechtzeitigerAuszug"
}, },
false, {},
false, {},
false {}
] ]
], ],
"dynamicLogicVisible": null, "dynamicLogicVisible": null,

View File

@@ -19,7 +19,7 @@
{ {
"name": "kuendigungsservice" "name": "kuendigungsservice"
}, },
false {}
], ],
[ [
{ {

View File

@@ -46,7 +46,7 @@
{ {
"name": "advowareBetnr" "name": "advowareBetnr"
}, },
false {}
] ]
], ],
"dynamicLogicVisible": null, "dynamicLogicVisible": null,

View File

@@ -13,7 +13,7 @@
{ {
"name": "anruferIst" "name": "anruferIst"
}, },
false {}
], ],
[ [
{ {
@@ -35,7 +35,7 @@
{ {
"name": "address" "name": "address"
}, },
false {}
], ],
[ [
{ {

View File

@@ -5,7 +5,7 @@
{ {
"name": "userName" "name": "userName"
}, },
false {}
], ],
[ [
{ {

View File

@@ -33,5 +33,31 @@
} }
] ]
}, },
"iconClass": "fas fa-circle-stop" "iconClass": "fas fa-file-contract",
"relationshipPanels": {
"vmhMietverhltnises": {
"layout": null,
"selectPrimaryFilterName": null
},
"mietobjekte": {
"layout": null,
"selectPrimaryFilterName": null
},
"kuendiger": {
"layout": null,
"selectPrimaryFilterName": null
},
"gekuendigte": {
"layout": null,
"selectPrimaryFilterName": null
},
"dokumenteskuendigung": {
"layout": null,
"selectPrimaryFilterName": null
},
"contactsKuendigung": {
"layout": null,
"selectPrimaryFilterName": "portalUsers"
}
}
} }

View File

@@ -294,19 +294,19 @@
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },
"kuendigungenVermieter": { "kndigungenKuendiger": {
"type": "hasMany", "type": "hasMany",
"relationName": "cBeteiligteKuendigungVermieter", "relationName": "cBeteiligteKuendigungKuendiger",
"foreign": "vermieter", "foreign": "kuendiger",
"entity": "CKuendigung", "entity": "CKndigung",
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },
"kuendigungenMieter": { "kndigungenGekuendigte": {
"type": "hasMany", "type": "hasMany",
"relationName": "cBeteiligteKuendigungMieter", "relationName": "cBeteiligteKuendigungGekuendigte",
"foreign": "mieter", "foreign": "gekuendigte",
"entity": "CKuendigung", "entity": "CKndigung",
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },

View File

@@ -176,11 +176,11 @@
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },
"kuendigungDokumente": { "kndigungensdokumente": {
"type": "hasMany", "type": "hasMany",
"relationName": "cDokumenteKuendigung", "relationName": "cDokumenteKuendigung",
"foreign": "dokumenteKuendigung", "foreign": "dokumenteskuendigung",
"entity": "CKuendigung", "entity": "CKndigung",
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },

View File

@@ -34,6 +34,176 @@
"teams": { "teams": {
"type": "linkMultiple", "type": "linkMultiple",
"view": "views/fields/teams" "view": "views/fields/teams"
},
"freigeschalteteNutzer": {
"type": "link"
},
"collaborators": {
"type": "linkMultiple",
"view": "views/fields/collaborators",
"maxCount": 30,
"fieldManagerParamList": [
"readOnly",
"readOnlyAfterCreate",
"audited",
"autocompleteOnEmpty",
"maxCount",
"inlineEditDisabled",
"tooltipText"
]
},
"advowareAktenzeichen": {
"type": "varchar",
"required": false,
"maxLength": 100,
"tooltip": true,
"isCustom": true,
"copyToClipboard": true
},
"betnr": {
"type": "int",
"required": false,
"tooltip": true,
"isCustom": true
},
"advowareLastSync": {
"type": "datetime",
"required": false,
"readOnly": true,
"tooltip": true,
"isCustom": true
},
"syncStatus": {
"type": "enum",
"required": false,
"options": [
"clean",
"unclean",
"failed"
],
"style": {
"clean": "success",
"unclean": "warning",
"failed": "danger"
},
"default": "clean",
"tooltip": true,
"isCustom": true
},
"kuendigungsart": {
"type": "enum",
"required": false,
"options": [
"Ordentlich",
"Ausserordentlich",
"Fristlos",
"AufgabeerklärungMieter"
],
"default": "Ordentlich",
"isCustom": true
},
"kuendigungsgrund": {
"type": "enum",
"required": false,
"options": [
"Zahlungsverzug",
"Pflichtverletzung",
"Eigenbedarf",
"Verwertung",
"VerhaltensbedingteLaermruhestoerung",
"BeschaedigungSubstanz",
"UnerlaubteUntervermietung",
"StoerendeGeschaeftsfuehrung",
"Sonstiges"
],
"isCustom": true
},
"kuendigungsgrundDetails": {
"type": "text",
"required": false,
"isCustom": true
},
"kuendigungsdatum": {
"type": "date",
"required": false,
"isCustom": true
},
"zustelldatum": {
"type": "date",
"required": false,
"isCustom": true
},
"kuendigungsfrist": {
"type": "varchar",
"required": false,
"maxLength": 50,
"isCustom": true
},
"beendigungstermin": {
"type": "date",
"required": false,
"isCustom": true
},
"status": {
"type": "enum",
"required": false,
"options": [
"Entwurf",
"Versendet",
"Zugestellt",
"Akzeptiert",
"Bestritten",
"Abgewickelt",
"Zurückgezogen"
],
"default": "Entwurf",
"isCustom": true
},
"zustellart": {
"type": "enum",
"required": false,
"options": [
"Einschreiben",
"Persoenlich",
"Gerichtsvollzieher",
"Oeffentlich",
"Sonstiges"
],
"isCustom": true
},
"reaktionMieter": {
"type": "text",
"required": false,
"isCustom": true
},
"notizen": {
"type": "text",
"required": false,
"isCustom": true
},
"rueckstandMiete": {
"type": "currency",
"required": false,
"default": 0,
"isCustom": true
},
"rueckstandNebenkosten": {
"type": "currency",
"required": false,
"default": 0,
"isCustom": true
},
"sonstigeForderungen": {
"type": "currency",
"required": false,
"default": 0,
"isCustom": true
},
"aussergerichtlicheGebuehren13": {
"type": "currency",
"required": false,
"default": 0,
"isCustom": true
} }
}, },
"links": { "links": {
@@ -75,11 +245,77 @@
"entity": "Email", "entity": "Email",
"foreign": "parent", "foreign": "parent",
"layoutRelationshipsDisabled": true "layoutRelationshipsDisabled": true
},
"vmhMietverhltnises": {
"type": "hasMany",
"relationName": "cKuendigungVmhMietverhltnis",
"foreign": "kndigungen",
"entity": "CVmhMietverhltnis",
"audited": false,
"isCustom": true
},
"mietobjekte": {
"type": "hasMany",
"relationName": "cMietobjektKuendigung",
"foreign": "kndigungen",
"entity": "CMietobjekt",
"audited": false,
"isCustom": true
},
"freigeschalteteNutzer": {
"type": "belongsTo",
"foreign": "cKndigungen",
"entity": "Contact",
"audited": false,
"isCustom": true
},
"collaborators": {
"type": "hasMany",
"entity": "User",
"relationName": "entityCollaborator",
"layoutRelationshipsDisabled": true
},
"dokumenteskuendigung": {
"type": "hasMany",
"relationName": "cDokumenteKuendigung",
"foreign": "kndigungensdokumente",
"entity": "CDokumente",
"audited": false,
"isCustom": true
},
"contactsKuendigung": {
"type": "hasMany",
"relationName": "cKuendigungContact",
"foreign": "cKuendigungContact",
"entity": "Contact",
"audited": false,
"isCustom": true
},
"kuendiger": {
"type": "hasMany",
"relationName": "cBeteiligteKuendigungKuendiger",
"foreign": "kndigungenKuendiger",
"entity": "CBeteiligte",
"audited": false,
"isCustom": true
},
"gekuendigte": {
"type": "hasMany",
"relationName": "cBeteiligteKuendigungGekuendigte",
"foreign": "kndigungenGekuendigte",
"entity": "CBeteiligte",
"audited": false,
"isCustom": true
} }
}, },
"collection": { "collection": {
"orderBy": "createdAt", "orderBy": "createdAt",
"order": "desc" "order": "desc",
"textFilterFields": [
"name"
],
"fullTextSearch": false,
"countDisabled": false
}, },
"indexes": { "indexes": {
"name": { "name": {
@@ -105,6 +341,39 @@
"createdAt", "createdAt",
"id" "id"
] ]
},
"betnr": {
"columns": [
"betnr"
]
},
"advowareAktenzeichen": {
"columns": [
"advowareAktenzeichen"
]
},
"status": {
"columns": [
"status",
"deleted"
]
},
"kuendigungsdatum": {
"columns": [
"kuendigungsdatum"
]
},
"beendigungstermin": {
"columns": [
"beendigungstermin"
]
},
"syncStatus": {
"columns": [
"syncStatus",
"deleted"
]
} }
} },
"optimisticConcurrencyControl": false
} }

View File

@@ -158,11 +158,11 @@
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },
"kuendigungen": { "kndigungen": {
"type": "hasMany", "type": "hasMany",
"relationName": "cKuendigungMietobjekt", "relationName": "cMietobjektKuendigung",
"foreign": "mietobjekt", "foreign": "mietobjekte",
"entity": "CKuendigung", "entity": "CKndigung",
"audited": false, "audited": false,
"isCustom": true "isCustom": true
} }

View File

@@ -234,6 +234,14 @@
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },
"kndigungen": {
"type": "hasMany",
"relationName": "cKuendigungVmhMietverhltnis",
"foreign": "vmhMietverhltnises",
"entity": "CKndigung",
"audited": false,
"isCustom": true
},
"vmhbeteiligtevermieter": { "vmhbeteiligtevermieter": {
"type": "hasMany", "type": "hasMany",
"relationName": "cBeteiligteVmhMietverhltnis", "relationName": "cBeteiligteVmhMietverhltnis",

View File

@@ -98,7 +98,7 @@
"type": "hasMany", "type": "hasMany",
"relationName": "cKuendigungContact", "relationName": "cKuendigungContact",
"foreign": "contactsKuendigung", "foreign": "contactsKuendigung",
"entity": "CKuendigung", "entity": "CKndigung",
"audited": false, "audited": false,
"isCustom": true "isCustom": true
}, },

View File

@@ -390,7 +390,7 @@ class CVmhMietverhltnis extends \Espo\Services\Record
throw new Forbidden('No read access to Mietverhältnis'); throw new Forbidden('No read access to Mietverhältnis');
} }
if (!$this->acl->checkScope('CKuendigung', 'create')) { if (!$this->acl->checkScope('CKndigung', 'create')) {
throw new Forbidden('No create access to Kündigung'); throw new Forbidden('No create access to Kündigung');
} }
@@ -412,33 +412,18 @@ class CVmhMietverhltnis extends \Espo\Services\Record
$data->teamsIds = $teamsIds; $data->teamsIds = $teamsIds;
} }
// Pre-fill dates from Mietverhältnis
if ($mietverhaeltnis->get('auszugsfrist')) {
$data->kuendigungsfrist = $mietverhaeltnis->get('auszugsfrist');
}
// Pre-fill Kündigungsgrund from Mietverhältnis
if ($mietverhaeltnis->get('kndigungsgrundWohnraum')) {
$data->kuendigungsgrund = $mietverhaeltnis->get('kndigungsgrundWohnraum');
}
// Pre-fill Besorgnis nicht rechtzeitiger Auszug
if ($mietverhaeltnis->get('besorgnisNichtRechtzeitigerAuszug')) {
$data->besorgnisNichtRechtzeitigerAuszug = $mietverhaeltnis->get('besorgnisNichtRechtzeitigerAuszug');
}
// 5. Create Kündigung entity // 5. Create Kündigung entity
$kuendigung = $this->entityManager->createEntity('CKuendigung', (array)$data); $kuendigung = $this->entityManager->createEntity('CKndigung', (array)$data);
if (!$kuendigung) { if (!$kuendigung) {
throw new \RuntimeException('Failed to create Kündigung'); throw new \RuntimeException('Failed to create Kündigung');
} }
$kuendigungRepo = $this->entityManager->getRepository('CKuendigung'); $kuendigungRepo = $this->entityManager->getRepository('CKndigung');
// 6. Link Mietverhältnis to Kündigung // 6. Link Mietverhältnis to Kündigung
$kuendigungRepo $kuendigungRepo
->getRelation($kuendigung, 'vmhMietverhltnis') ->getRelation($kuendigung, 'vmhMietverhltnises')
->relate($mietverhaeltnis); ->relate($mietverhaeltnis);
// 7. Get and link Mietobjekt // 7. Get and link Mietobjekt
@@ -449,37 +434,97 @@ class CVmhMietverhltnis extends \Espo\Services\Record
if ($mietobjekt) { if ($mietobjekt) {
$kuendigungRepo $kuendigungRepo
->getRelation($kuendigung, 'mietobjekt') ->getRelation($kuendigung, 'mietobjekte')
->relate($mietobjekt); ->relate($mietobjekt);
} }
// 8. Get Vermieter from Mietverhältnis // 8. Get Vermieter (Kündigende) from Mietverhältnis
$vermieterBeteiligte = $this->entityManager $vermieterBeteiligte = $this->entityManager
->getRepository('CVmhMietverhltnis') ->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter') ->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter')
->find(); ->find();
foreach ($vermieterBeteiligte as $vermieter) { foreach ($vermieterBeteiligte as $vermieter) {
// Link as Vermieter // Link as Kündigende
$kuendigungRepo $kuendigungRepo
->getRelation($kuendigung, 'vermieter') ->getRelation($kuendigung, 'kuendiger')
->relate($vermieter); ->relate($vermieter);
} }
// 9. Get Mieter from Mietverhältnis // 9. Get Mieter (Gekündigte) from Mietverhältnis
$mieterBeteiligte = $this->entityManager $mieterBeteiligte = $this->entityManager
->getRepository('CVmhMietverhltnis') ->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter') ->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter')
->find(); ->find();
foreach ($mieterBeteiligte as $mieter) { foreach ($mieterBeteiligte as $mieter) {
// Link as Mieter // Link as Gekündigte
$kuendigungRepo $kuendigungRepo
->getRelation($kuendigung, 'mieter') ->getRelation($kuendigung, 'gekuendigte')
->relate($mieter); ->relate($mieter);
} }
// 10. Link Portal Contacts // 9b. Get Sonstige Bewohner (auch Gekündigte) from Mietverhältnis
$sonstigeBewohner = $this->entityManager
->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'sonstigebesitzervmhmietverhltnis')
->find();
foreach ($sonstigeBewohner as $bewohner) {
// Link as Gekündigte
$kuendigungRepo
->getRelation($kuendigung, 'gekuendigte')
->relate($bewohner);
}
// 10. Copy all documents from Mietverhältnis, Mietobjekt and Beteiligte
// 10a. Dokumente vom Mietverhältnis
$dokumenteMV = $this->entityManager
->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'dokumentesvmhMietverhltnisse')
->find();
foreach ($dokumenteMV as $dokument) {
$kuendigungRepo
->getRelation($kuendigung, 'dokumenteskuendigung')
->relate($dokument);
}
// 10b. Dokumente vom Mietobjekt
if ($mietobjekt) {
$dokumenteMO = $this->entityManager
->getRepository('CMietobjekt')
->getRelation($mietobjekt, 'dokumentesMietobjekt')
->find();
foreach ($dokumenteMO as $dokument) {
$kuendigungRepo
->getRelation($kuendigung, 'dokumenteskuendigung')
->relate($dokument);
}
}
// 10c. Dokumente von allen Beteiligten (Vermieter + Mieter + Sonstige)
$alleBeteiligte = array_merge(
iterator_to_array($vermieterBeteiligte),
iterator_to_array($mieterBeteiligte),
iterator_to_array($sonstigeBewohner)
);
foreach ($alleBeteiligte as $beteiligter) {
$dokumenteBet = $this->entityManager
->getRepository('CBeteiligte')
->getRelation($beteiligter, 'dokumentesBeteiligte')
->find();
foreach ($dokumenteBet as $dokument) {
$kuendigungRepo
->getRelation($kuendigung, 'dokumenteskuendigung')
->relate($dokument);
}
}
// 11. Copy portal contacts from Mietverhältnis (nur vom Mietverhältnis!)
$portalContacts = $this->entityManager $portalContacts = $this->entityManager
->getRepository('CVmhMietverhltnis') ->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'contactsMietverhltnis') ->getRelation($mietverhaeltnis, 'contactsMietverhltnis')
@@ -491,7 +536,7 @@ class CVmhMietverhltnis extends \Espo\Services\Record
->relate($contact); ->relate($contact);
} }
// 11. Commit transaction // 12. Commit transaction
$this->entityManager->getTransactionManager()->commit(); $this->entityManager->getTransactionManager()->commit();
return [ return [

View File

@@ -293,44 +293,91 @@ class EntityValidator:
"""Prüfe Layout-Dateien auf häufige Fehler.""" """Prüfe Layout-Dateien auf häufige Fehler."""
print_header("5. LAYOUT-STRUKTUR VALIDIERUNG") print_header("5. LAYOUT-STRUKTUR VALIDIERUNG")
layouts_path = self.metadata_path / "clientDefs" layouts_base = self.custom_path / "layouts"
if not layouts_path.exists():
print_warning("Keine clientDefs gefunden")
return True
layout_errors = [] layout_errors = []
layout_warnings = []
checked_layouts = 0 checked_layouts = 0
for client_def_file in layouts_path.glob("*.json"): # 1. Prüfe bottomPanelsDetail.json Dateien (KRITISCH: Muss Objekt sein, kein Array!)
try: if layouts_base.exists():
with open(client_def_file, 'r', encoding='utf-8') as f: for bottom_panel_file in layouts_base.rglob("bottomPanelsDetail.json"):
client_def = json.load(f) try:
with open(bottom_panel_file, 'r', encoding='utf-8') as f:
content = json.load(f)
# Prüfe auf häufige Layout-Fehler in bottomPanels
bottom_panels = client_def.get('bottomPanelsDetail', {})
for panel_key, panel_def in bottom_panels.items():
checked_layouts += 1 checked_layouts += 1
entity_name = bottom_panel_file.parent.name
# Prüfe auf unnötige false-Elemente # KRITISCHER CHECK: bottomPanelsDetail.json MUSS Objekt sein (nicht Array)!
if isinstance(panel_def, dict): if isinstance(content, list):
for key, value in panel_def.items(): layout_errors.append(
if value is False and key not in ['disabled', 'sticked']: f"{entity_name}/bottomPanelsDetail.json: FEHLER - Ist Array statt Objekt! "
layout_errors.append( f"EspoCRM 7.x erfordert Objekt-Format mit Keys wie 'contacts', '_tabBreak_0', etc."
f"{client_def_file.stem}: bottomPanelsDetail.{panel_key}.{key} " )
f"sollte nicht 'false' sein" elif isinstance(content, dict):
) # Prüfe auf false-Werte in falschen Kontexten
except Exception: for key, value in content.items():
pass # JSON-Fehler bereits gemeldet if isinstance(value, dict):
for subkey, subvalue in value.items():
if subvalue is False and subkey not in ['disabled', 'sticked']:
layout_warnings.append(
f"{entity_name}/bottomPanelsDetail.json: {key}.{subkey} "
f"sollte nicht 'false' sein"
)
except Exception:
pass # JSON-Fehler bereits in validate_json_syntax gemeldet
# 2. Prüfe detail.json Dateien auf deprecated false-Platzhalter
if layouts_base.exists():
for detail_file in layouts_base.rglob("detail.json"):
try:
with open(detail_file, 'r', encoding='utf-8') as f:
content = json.load(f)
entity_name = detail_file.parent.name
# Prüfe ob content ein Array von Panels ist
if isinstance(content, list):
for panel_idx, panel in enumerate(content):
if not isinstance(panel, dict):
continue
rows = panel.get('rows', [])
for row_idx, row in enumerate(rows):
if not isinstance(row, list):
continue
for cell_idx, cell in enumerate(row):
# KRITISCH: false als Platzhalter ist deprecated in EspoCRM 7.x!
if cell is False:
layout_errors.append(
f"{entity_name}/detail.json: Panel {panel_idx}, Row {row_idx}, "
f"Cell {cell_idx} verwendet 'false' als Platzhalter. "
f"In EspoCRM 7.x muss '{{}}' (leeres Objekt) verwendet werden!"
)
except Exception:
pass # JSON-Fehler bereits gemeldet
# Ergebnisse ausgeben
if layout_errors: if layout_errors:
print_warning(f"{len(layout_errors)} Layout-Strukturprobleme:") print_error(f"{len(layout_errors)} KRITISCHE Layout-Fehler gefunden:")
for err in layout_errors[:5]: for err in layout_errors:
print(f" {Colors.YELLOW}{Colors.END} {err}") print(f" {Colors.RED}{Colors.END} {err}")
if len(layout_errors) > 5: self.errors.extend(layout_errors)
print(f" {Colors.YELLOW}...{Colors.END} und {len(layout_errors) - 5} weitere") return False
self.warnings.extend(layout_errors)
else: if layout_warnings:
print_success(f"{checked_layouts} Layout-Definitionen geprüft") print_warning(f"{len(layout_warnings)} Layout-Warnungen:")
for warn in layout_warnings[:5]:
print(f" {Colors.YELLOW}{Colors.END} {warn}")
if len(layout_warnings) > 5:
print(f" {Colors.YELLOW}...{Colors.END} und {len(layout_warnings) - 5} weitere")
self.warnings.extend(layout_warnings)
if not layout_errors and not layout_warnings:
print_success(f"{checked_layouts} Layout-Dateien geprüft, keine Fehler")
elif not layout_errors:
print_success(f"{checked_layouts} Layout-Dateien geprüft, keine kritischen Fehler")
return True return True