diff --git a/README.md b/README.md index 71aee8ef..c189ab16 100644 --- a/README.md +++ b/README.md @@ -177,50 +177,92 @@ Basierend auf der Analyse von Git-Commits und praktischen Erfahrungen treten bes #### 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:** +- Layout wird nicht geladen, Fehlermeldung in UI - Felder werden nicht korrekt angeordnet - Leere Bereiche in Detail-Views -- Inkonsistente Spaltenbreiten +- bottomPanelsDetail funktioniert nicht -**❌ FALSCH:** +**❌ FALSCH (EspoCRM 7.x):** ```json // layouts/Entity/detail.json { "rows": [ [ - {"name": "field1"} - ], - [ + {"name": "field1"}, {"name": "field2"}, - false // ← Unnötiges false-Element! + false, // ← DEPRECATED! Funktioniert in 7.x NICHT! + false // ← Verursacht Layout-Fehler! ] ] } ``` -**✅ RICHTIG:** +**✅ RICHTIG (EspoCRM 7.x):** ```json { "rows": [ [ {"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:** +- ❌ **`false` als Platzhalter** (seit EspoCRM 7.x nicht mehr unterstützt!) - ❌ Width-Attribute in Detail-Layouts (nur für List-Layouts!) -- ❌ Leere Objekte `{}` oder `false` in Rows -- ❌ Index nicht angepasst nach Entfernung von Panels (bottomPanelsDetail) +- ❌ bottomPanelsDetail.json als Array statt Objekt +- ❌ Index nicht angepasst nach Entfernung von Panels **Best Practice:** +- **Immer `{}` statt `false`** für leere Zellen in detail.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 +- `_tabBreak_{index}` verwenden um Panels auf verschiedene Tabs zu verteilen --- diff --git a/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php b/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php index 2d491d2c..36adbe88 100644 --- a/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php +++ b/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php @@ -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 { diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json b/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json index e455369a..ed853e77 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json @@ -12,8 +12,8 @@ "vmhRumungsklagesBeklagte": "Beklagte", "mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)", - "kuendigungenVermieter": "Kündigungen (Vermieter)", - "kuendigungenMieter": "Kündigungen (Mieter)", + "kndigungenKuendiger": "Kündigungen (Kündigende)", + "kndigungenGekuendigte": "Kündigungen (Gekündigte)", "adressens": "Adressen", "calls1": "Anrufe", "contactsBeteiligte": "Freigegebene Nutzer", @@ -35,8 +35,8 @@ "vmhRumungsklagesBeklagte": "Beklagte", "mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)", - "kuendigungenVermieter": "Kündigungen (Vermieter)", - "kuendigungenMieter": "Kündigungen (Mieter)", + "kndigungenKuendiger": "Kündigungen (Kündigende)", + "kndigungenGekuendigte": "Kündigungen (Gekündigte)", "adressens": "Adressen", "calls1": "Anrufe", "contactsBeteiligte": "Freigegebene Nutzer", diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json b/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json index 459be10a..2a49b103 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json @@ -14,7 +14,9 @@ "vmhRumungsklagesdokumente": "Räumungsklagen", "kuendigungDokumente": "Kündigungen", "beteiligte2dokumente": "Beteiligte", - "mietobjekt2dokumente": "Mietobjekte" + "mietobjekt2dokumente": "Mietobjekte", + "mietinkassosdokumente": "Mietinkasso", + "kndigungensdokumente": "Kündigungen" }, "links": { "contactsvmhdokumente": "Freigegebene Nutzer", @@ -24,7 +26,8 @@ "kuendigungDokumente": "Kündigungen", "beteiligte2dokumente": "Beteiligte", "mietobjekt2dokumente": "Mietobjekte", - "mietinkassosdokumente": "Mietinkasso" + "mietinkassosdokumente": "Mietinkasso", + "kndigungensdokumente": "Kündigungen" }, "labels": { "Create CDokumente": "Dokument erstellen" diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CKndigung.json b/custom/Espo/Custom/Resources/i18n/de_DE/CKndigung.json index 01a25372..adca8af6 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CKndigung.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CKndigung.json @@ -1,9 +1,94 @@ { "links": { + "meetings": "Termine", "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": { - "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" } } \ No newline at end of file diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json b/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json index e105f066..b9d58133 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json @@ -6,8 +6,7 @@ "vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)", "vmhMietverhltnises": "Mietverhältnisse", "contactsMietobjekt": "Freigegebene Nutzer", - "dokumentesMietobjekt": "Dokumente", - "kuendigungen": "Kündigungen" + "dokumentesMietobjekt": "Dokumente" }, "links": { "vmhMietverhltnises2Mietobjekt": "Mietverhältnisse (veraltet)", @@ -15,7 +14,7 @@ "contact2mietobjekt": "Kontakte", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", - "kuendigungen": "Kündigungen", + "kndigungen": "Kündigungen", "contactsMietobjekt": "Freigegebene Nutzer", "dokumentesMietobjekt": "Dokumente" }, diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json b/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json index da001597..b4eccee8 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json @@ -13,7 +13,7 @@ "warmmiete": "Warmmiete", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", - "kuendigungen": "Kündigungen", + "kndigungen": "Kündigungen", "vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtemieter": "Mieter", "contactsMietverhltnis": "Freigegebene Nutzer", @@ -34,7 +34,7 @@ "tasks": "Aufgaben", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", - "kuendigungen": "Kündigungen", + "kndigungen": "Kündigungen", "vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtemieter": "Mieter", "contactsMietverhltnis": "Freigegebene Nutzer", @@ -56,7 +56,7 @@ "confirmRentCollection": "Möchten Sie wirklich ein Mietinkasso aus diesem Mietverhältnis einleiten?", "rentCollectionCreated": "Mietinkasso wurde erfolgreich erstellt", "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", "terminationError": "Fehler beim Erstellen der Kündigung" } diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json b/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json index cbc1baae..f0e22e86 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json @@ -14,8 +14,8 @@ "cMietobjekteContactPortal": "Mietobjekte (Portal)", "cAdressenContact": "Adressen", "cVmhRumungsklageContact": "Räumungsklagen (Portal)", - "cMietinkassoContact": "Mietinkasso (Portal)", - "cKuendigungContact": "Kündigungen (Portal)", + "cMietinkassoContact": "Mietinkasso", + "cKuendigungContact": "Kündigungen", "cBankverbindungenContact": "Bankverbindungen" }, "links": { @@ -31,7 +31,7 @@ "cAdressenContact": "Adressen", "cVmhRumungsklageContact": "Räumungsklagen (Portal)", "cMietinkassoContact": "Mietinkasso", - "cKuendigungContact": "Kündigungen (Portal)", + "cKuendigungContact": "Kündigungen", "cBankverbindungenContact": "Bankverbindungen" }, "options": { diff --git a/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json b/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json index fc2f92b7..857943bd 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json @@ -11,8 +11,8 @@ "vmhRumungsklagesKlaeger": "Plaintiff", "mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosBeklagte": "Rent Collection (Defendant)", - "kuendigungenVermieter": "Terminations (Landlord)", - "kuendigungenMieter": "Terminations (Tenant)", + "kndigungenKuendiger": "Terminations (Terminating Party)", + "kndigungenGekuendigte": "Terminations (Terminated Party)", "contactsBeteiligte": "Portal Users", "dokumentesBeteiligte": "Documents" }, @@ -29,8 +29,8 @@ "vmhRumungsklagesKlaeger": "Plaintiff", "mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosBeklagte": "Rent Collection (Defendant)", - "kuendigungenVermieter": "Terminations (Landlord)", - "kuendigungenMieter": "Terminations (Tenant)", + "kndigungenKuendiger": "Terminations (Terminating Party)", + "kndigungenGekuendigte": "Terminations (Terminated Party)", "contactsBeteiligte": "Portal Users", "dokumentesBeteiligte": "Documents", "bankverbindungens": "Bank Accounts" diff --git a/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json b/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json index accad2a5..253fc5d6 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json @@ -11,7 +11,9 @@ "md5sum": "MD5 Checksum", "sha256": "SHA256 Checksum", "beteiligte2dokumente": "Parties", - "mietobjekt2dokumente": "Properties" + "mietobjekt2dokumente": "Properties", + "mietinkassosdokumente": "Rent Collection", + "kndigungensdokumente": "Terminations" }, "links": { "contactsvmhdokumente": "Portal Users", @@ -21,7 +23,8 @@ "kuendigungDokumente": "Terminations", "beteiligte2dokumente": "Parties", "mietobjekt2dokumente": "Properties", - "mietinkassosdokumente": "Rent Collection" + "mietinkassosdokumente": "Rent Collection", + "kndigungensdokumente": "Terminations" }, "labels": { "Create CDokumente": "Create Dokument" diff --git a/custom/Espo/Custom/Resources/i18n/en_US/CKndigung.json b/custom/Espo/Custom/Resources/i18n/en_US/CKndigung.json index 9f9079f3..f34c66b9 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CKndigung.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CKndigung.json @@ -1,12 +1,94 @@ { "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": { "meetings": "Meetings", "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": { - "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" } } diff --git a/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json b/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json index f0482da7..33210f1a 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json @@ -20,7 +20,7 @@ "contact2mietobjekt": "Contacts", "vmhRumungsklages": "Eviction Lawsuits", "mietinkassos": "Rent Collection", - "kuendigungen": "Terminations", + "kndigungen": "Terminations", "contactsMietobjekt": "Portal Users", "dokumentesMietobjekt": "Documents" }, diff --git a/custom/Espo/Custom/Resources/i18n/en_US/CVmhMietverhltnis.json b/custom/Espo/Custom/Resources/i18n/en_US/CVmhMietverhltnis.json index 40153de8..dffabb6e 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CVmhMietverhltnis.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CVmhMietverhltnis.json @@ -3,6 +3,7 @@ "status": "Status", "vmhRumungsklages": "Eviction Lawsuits", "mietinkassos": "Rent Collection", + "kndigungen": "Terminations", "nutzungsart": "Type of Use", "kndigungsgrundWohnraum": "Reason for Termination", "auszugsfrist": "Move-out Deadline", @@ -36,7 +37,7 @@ "tasks": "Tasks", "vmhRumungsklages": "Eviction Lawsuits", "mietinkassos": "Rent Collection", - "kuendigungen": "Terminations", + "kndigungen": "Terminations", "vmhbeteiligtevermieter": "Landlords", "vmhbeteiligtemieter": "Tenants", "contactsMietverhltnis": "Portal Users", @@ -48,7 +49,8 @@ "labels": { "Create CVmhMietverhltnis": "Create Mietverhältnis", "Initiate Eviction": "Initiate Eviction Lawsuit", - "Initiate Rent Collection": "Initiate Rent Collection" + "Initiate Rent Collection": "Initiate Rent Collection", + "Initiate Termination": "Create Termination" }, "messages": { "confirmEviction": "Do you really want to initiate an eviction lawsuit from this tenancy?", @@ -56,7 +58,10 @@ "evictionError": "Error creating eviction lawsuit", "confirmRentCollection": "Do you really want to initiate rent collection from this tenancy?", "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": { "status": { diff --git a/custom/Espo/Custom/Resources/i18n/en_US/Contact.json b/custom/Espo/Custom/Resources/i18n/en_US/Contact.json index 66ee8879..83229c6f 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/Contact.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/Contact.json @@ -8,7 +8,9 @@ "cVmhVermietersKontaktpersonen": "Vermieter", "cVmhMietverhltnisesContact": "Mietverhältnisse", "cDokumentesvmhcontact": "Dokumente", - "cVmhmietobjekt2contact": "Mietobjekts" + "cVmhmietobjekt2contact": "Mietobjekts", + "cMietinkassoContact": "Rent Collection", + "cKuendigungContact": "Terminations" }, "links": { "cVmhRumungsklages": "Räumungsklagen", @@ -23,7 +25,7 @@ "cAdressenContact": "Addresses", "cVmhRumungsklageContact": "Eviction Lawsuits (Portal)", "cMietinkassoContact": "Rent Collection", - "cKuendigungContact": "Terminations (Portal)", + "cKuendigungContact": "Terminations", "cBankverbindungenContact": "Bank Accounts" }, "options": { diff --git a/custom/Espo/Custom/Resources/layouts/CBeteiligte/detail.json b/custom/Espo/Custom/Resources/layouts/CBeteiligte/detail.json index cb1b621b..1fca01c4 100644 --- a/custom/Espo/Custom/Resources/layouts/CBeteiligte/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CBeteiligte/detail.json @@ -5,7 +5,7 @@ { "name": "rechtsform" }, - false + {} ], [ { @@ -19,13 +19,13 @@ { "name": "disgTyp" }, - false + {} ], [ { "name": "firmenname" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/layouts/CDokumente/detail.json b/custom/Espo/Custom/Resources/layouts/CDokumente/detail.json index 954ca7c0..2619f526 100644 --- a/custom/Espo/Custom/Resources/layouts/CDokumente/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CDokumente/detail.json @@ -5,7 +5,7 @@ { "name": "name" }, - false + {} ] ], "dynamicLogicVisible": null, @@ -42,7 +42,7 @@ { "name": "ydocumentuuid" }, - false + {} ] ], "dynamicLogicVisible": null, diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/bottomPanelsDetail.json b/custom/Espo/Custom/Resources/layouts/CKndigung/bottomPanelsDetail.json new file mode 100644 index 00000000..811e3850 --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/bottomPanelsDetail.json @@ -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 + } +} diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/defaultSidePanel.json b/custom/Espo/Custom/Resources/layouts/CKndigung/defaultSidePanel.json new file mode 100644 index 00000000..b7980619 --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/defaultSidePanel.json @@ -0,0 +1,11 @@ +[ + { + "name": ":assignedUser" + }, + { + "name": "teams" + }, + { + "name": "freigeschalteteNutzer" + } +] diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/detail.json b/custom/Espo/Custom/Resources/layouts/CKndigung/detail.json new file mode 100644 index 00000000..b836cf98 --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/detail.json @@ -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" + } + ] + ] + } +] diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/detailSmall.json b/custom/Espo/Custom/Resources/layouts/CKndigung/detailSmall.json new file mode 100644 index 00000000..26f5402e --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/detailSmall.json @@ -0,0 +1,33 @@ +[ + { + "rows": [ + [ + { + "name": "name", + "noLabel": true + } + ], + [ + { + "name": "kuendigungsart" + }, + { + "name": "status" + } + ], + [ + { + "name": "kuendigungsdatum" + }, + { + "name": "beendigungstermin" + } + ], + [ + { + "name": "assignedUser" + } + ] + ] + } +] diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/list.json b/custom/Espo/Custom/Resources/layouts/CKndigung/list.json new file mode 100644 index 00000000..2bc4fd9f --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/list.json @@ -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 + } +] diff --git a/custom/Espo/Custom/Resources/layouts/CKndigung/listSmall.json b/custom/Espo/Custom/Resources/layouts/CKndigung/listSmall.json new file mode 100644 index 00000000..f27c2501 --- /dev/null +++ b/custom/Espo/Custom/Resources/layouts/CKndigung/listSmall.json @@ -0,0 +1,15 @@ +[ + { + "name": "name", + "link": true + }, + { + "name": "kuendigungsart" + }, + { + "name": "status" + }, + { + "name": "kuendigungsdatum" + } +] diff --git a/custom/Espo/Custom/Resources/layouts/CMietinkasso/detail.json b/custom/Espo/Custom/Resources/layouts/CMietinkasso/detail.json index cab8acf9..c70f2a2a 100644 --- a/custom/Espo/Custom/Resources/layouts/CMietinkasso/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CMietinkasso/detail.json @@ -19,7 +19,7 @@ { "name": "kuendigungsservice" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/layouts/CMietobjekt/detail.json b/custom/Espo/Custom/Resources/layouts/CMietobjekt/detail.json index bffbdb3d..3ac4bbd6 100644 --- a/custom/Espo/Custom/Resources/layouts/CMietobjekt/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CMietobjekt/detail.json @@ -13,7 +13,7 @@ { "name": "lage" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/layouts/CVmhMietverhltnis/detail.json b/custom/Espo/Custom/Resources/layouts/CVmhMietverhltnis/detail.json index c66c8a11..24576680 100644 --- a/custom/Espo/Custom/Resources/layouts/CVmhMietverhltnis/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CVmhMietverhltnis/detail.json @@ -44,9 +44,9 @@ { "name": "besorgnisNichtRechtzeitigerAuszug" }, - false, - false, - false + {}, + {}, + {} ] ], "dynamicLogicVisible": null, diff --git a/custom/Espo/Custom/Resources/layouts/CVmhRumungsklage/detail.json b/custom/Espo/Custom/Resources/layouts/CVmhRumungsklage/detail.json index 4fb05cc3..c8d21e78 100644 --- a/custom/Espo/Custom/Resources/layouts/CVmhRumungsklage/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CVmhRumungsklage/detail.json @@ -19,7 +19,7 @@ { "name": "kuendigungsservice" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/layouts/CVmhVermieter/detail.json b/custom/Espo/Custom/Resources/layouts/CVmhVermieter/detail.json index e277cf97..968b512f 100644 --- a/custom/Espo/Custom/Resources/layouts/CVmhVermieter/detail.json +++ b/custom/Espo/Custom/Resources/layouts/CVmhVermieter/detail.json @@ -46,7 +46,7 @@ { "name": "advowareBetnr" }, - false + {} ] ], "dynamicLogicVisible": null, diff --git a/custom/Espo/Custom/Resources/layouts/Contact/detail.json b/custom/Espo/Custom/Resources/layouts/Contact/detail.json index 296285be..5a255e92 100644 --- a/custom/Espo/Custom/Resources/layouts/Contact/detail.json +++ b/custom/Espo/Custom/Resources/layouts/Contact/detail.json @@ -13,7 +13,7 @@ { "name": "anruferIst" }, - false + {} ], [ { @@ -35,7 +35,7 @@ { "name": "address" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/layouts/User/detail.json b/custom/Espo/Custom/Resources/layouts/User/detail.json index 979eb0f2..fdb61767 100644 --- a/custom/Espo/Custom/Resources/layouts/User/detail.json +++ b/custom/Espo/Custom/Resources/layouts/User/detail.json @@ -5,7 +5,7 @@ { "name": "userName" }, - false + {} ], [ { diff --git a/custom/Espo/Custom/Resources/metadata/clientDefs/CKndigung.json b/custom/Espo/Custom/Resources/metadata/clientDefs/CKndigung.json index 0115fec8..4a1513ab 100644 --- a/custom/Espo/Custom/Resources/metadata/clientDefs/CKndigung.json +++ b/custom/Espo/Custom/Resources/metadata/clientDefs/CKndigung.json @@ -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" + } + } } \ No newline at end of file diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json index d83a6939..78120690 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json @@ -294,19 +294,19 @@ "audited": false, "isCustom": true }, - "kuendigungenVermieter": { + "kndigungenKuendiger": { "type": "hasMany", - "relationName": "cBeteiligteKuendigungVermieter", - "foreign": "vermieter", - "entity": "CKuendigung", + "relationName": "cBeteiligteKuendigungKuendiger", + "foreign": "kuendiger", + "entity": "CKndigung", "audited": false, "isCustom": true }, - "kuendigungenMieter": { + "kndigungenGekuendigte": { "type": "hasMany", - "relationName": "cBeteiligteKuendigungMieter", - "foreign": "mieter", - "entity": "CKuendigung", + "relationName": "cBeteiligteKuendigungGekuendigte", + "foreign": "gekuendigte", + "entity": "CKndigung", "audited": false, "isCustom": true }, diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json index 81794929..8517b980 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json @@ -176,11 +176,11 @@ "audited": false, "isCustom": true }, - "kuendigungDokumente": { + "kndigungensdokumente": { "type": "hasMany", "relationName": "cDokumenteKuendigung", - "foreign": "dokumenteKuendigung", - "entity": "CKuendigung", + "foreign": "dokumenteskuendigung", + "entity": "CKndigung", "audited": false, "isCustom": true }, diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CKndigung.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CKndigung.json index d521dd6a..c95347c5 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CKndigung.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CKndigung.json @@ -34,6 +34,176 @@ "teams": { "type": "linkMultiple", "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": { @@ -75,11 +245,77 @@ "entity": "Email", "foreign": "parent", "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": { "orderBy": "createdAt", - "order": "desc" + "order": "desc", + "textFilterFields": [ + "name" + ], + "fullTextSearch": false, + "countDisabled": false }, "indexes": { "name": { @@ -105,6 +341,39 @@ "createdAt", "id" ] + }, + "betnr": { + "columns": [ + "betnr" + ] + }, + "advowareAktenzeichen": { + "columns": [ + "advowareAktenzeichen" + ] + }, + "status": { + "columns": [ + "status", + "deleted" + ] + }, + "kuendigungsdatum": { + "columns": [ + "kuendigungsdatum" + ] + }, + "beendigungstermin": { + "columns": [ + "beendigungstermin" + ] + }, + "syncStatus": { + "columns": [ + "syncStatus", + "deleted" + ] } - } + }, + "optimisticConcurrencyControl": false } \ No newline at end of file diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json index 4d21c5d3..b54e7cd8 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json @@ -158,11 +158,11 @@ "audited": false, "isCustom": true }, - "kuendigungen": { + "kndigungen": { "type": "hasMany", - "relationName": "cKuendigungMietobjekt", - "foreign": "mietobjekt", - "entity": "CKuendigung", + "relationName": "cMietobjektKuendigung", + "foreign": "mietobjekte", + "entity": "CKndigung", "audited": false, "isCustom": true } diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json index cbb32325..7894b005 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json @@ -234,6 +234,14 @@ "audited": false, "isCustom": true }, + "kndigungen": { + "type": "hasMany", + "relationName": "cKuendigungVmhMietverhltnis", + "foreign": "vmhMietverhltnises", + "entity": "CKndigung", + "audited": false, + "isCustom": true + }, "vmhbeteiligtevermieter": { "type": "hasMany", "relationName": "cBeteiligteVmhMietverhltnis", diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json b/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json index 7c66e2f4..a1f5a00d 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json @@ -98,7 +98,7 @@ "type": "hasMany", "relationName": "cKuendigungContact", "foreign": "contactsKuendigung", - "entity": "CKuendigung", + "entity": "CKndigung", "audited": false, "isCustom": true }, diff --git a/custom/Espo/Custom/Services/CVmhMietverhltnis.php b/custom/Espo/Custom/Services/CVmhMietverhltnis.php index 420c0f65..e23fcc0b 100644 --- a/custom/Espo/Custom/Services/CVmhMietverhltnis.php +++ b/custom/Espo/Custom/Services/CVmhMietverhltnis.php @@ -390,7 +390,7 @@ class CVmhMietverhltnis extends \Espo\Services\Record 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'); } @@ -412,33 +412,18 @@ class CVmhMietverhltnis extends \Espo\Services\Record $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 - $kuendigung = $this->entityManager->createEntity('CKuendigung', (array)$data); + $kuendigung = $this->entityManager->createEntity('CKndigung', (array)$data); if (!$kuendigung) { 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 $kuendigungRepo - ->getRelation($kuendigung, 'vmhMietverhltnis') + ->getRelation($kuendigung, 'vmhMietverhltnises') ->relate($mietverhaeltnis); // 7. Get and link Mietobjekt @@ -449,37 +434,97 @@ class CVmhMietverhltnis extends \Espo\Services\Record if ($mietobjekt) { $kuendigungRepo - ->getRelation($kuendigung, 'mietobjekt') + ->getRelation($kuendigung, 'mietobjekte') ->relate($mietobjekt); } - // 8. Get Vermieter from Mietverhältnis + // 8. Get Vermieter (Kündigende) from Mietverhältnis $vermieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter') ->find(); foreach ($vermieterBeteiligte as $vermieter) { - // Link as Vermieter + // Link as Kündigende $kuendigungRepo - ->getRelation($kuendigung, 'vermieter') + ->getRelation($kuendigung, 'kuendiger') ->relate($vermieter); } - // 9. Get Mieter from Mietverhältnis + // 9. Get Mieter (Gekündigte) from Mietverhältnis $mieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter') ->find(); foreach ($mieterBeteiligte as $mieter) { - // Link as Mieter + // Link as Gekündigte $kuendigungRepo - ->getRelation($kuendigung, 'mieter') + ->getRelation($kuendigung, 'gekuendigte') ->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 ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'contactsMietverhltnis') @@ -491,7 +536,7 @@ class CVmhMietverhltnis extends \Espo\Services\Record ->relate($contact); } - // 11. Commit transaction + // 12. Commit transaction $this->entityManager->getTransactionManager()->commit(); return [ diff --git a/custom/scripts/validate_and_rebuild.py b/custom/scripts/validate_and_rebuild.py index 4726622d..12d004d3 100755 --- a/custom/scripts/validate_and_rebuild.py +++ b/custom/scripts/validate_and_rebuild.py @@ -293,44 +293,91 @@ class EntityValidator: """Prüfe Layout-Dateien auf häufige Fehler.""" print_header("5. LAYOUT-STRUKTUR VALIDIERUNG") - layouts_path = self.metadata_path / "clientDefs" - if not layouts_path.exists(): - print_warning("Keine clientDefs gefunden") - return True - + layouts_base = self.custom_path / "layouts" layout_errors = [] + layout_warnings = [] checked_layouts = 0 - for client_def_file in layouts_path.glob("*.json"): - try: - with open(client_def_file, 'r', encoding='utf-8') as f: - client_def = 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 + # 1. Prüfe bottomPanelsDetail.json Dateien (KRITISCH: Muss Objekt sein, kein Array!) + if layouts_base.exists(): + for bottom_panel_file in layouts_base.rglob("bottomPanelsDetail.json"): + try: + with open(bottom_panel_file, 'r', encoding='utf-8') as f: + content = json.load(f) - # Prüfe auf unnötige false-Elemente - if isinstance(panel_def, dict): - for key, value in panel_def.items(): - if value is False and key not in ['disabled', 'sticked']: - layout_errors.append( - f"{client_def_file.stem}: bottomPanelsDetail.{panel_key}.{key} " - f"sollte nicht 'false' sein" - ) - except Exception: - pass # JSON-Fehler bereits gemeldet + checked_layouts += 1 + entity_name = bottom_panel_file.parent.name + + # KRITISCHER CHECK: bottomPanelsDetail.json MUSS Objekt sein (nicht Array)! + if isinstance(content, list): + layout_errors.append( + f"{entity_name}/bottomPanelsDetail.json: FEHLER - Ist Array statt Objekt! " + f"EspoCRM 7.x erfordert Objekt-Format mit Keys wie 'contacts', '_tabBreak_0', etc." + ) + elif isinstance(content, dict): + # Prüfe auf false-Werte in falschen Kontexten + for key, value in content.items(): + 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: - print_warning(f"{len(layout_errors)} Layout-Strukturprobleme:") - for err in layout_errors[:5]: - print(f" {Colors.YELLOW}•{Colors.END} {err}") - if len(layout_errors) > 5: - print(f" {Colors.YELLOW}...{Colors.END} und {len(layout_errors) - 5} weitere") - self.warnings.extend(layout_errors) - else: - print_success(f"{checked_layouts} Layout-Definitionen geprüft") + print_error(f"{len(layout_errors)} KRITISCHE Layout-Fehler gefunden:") + for err in layout_errors: + print(f" {Colors.RED}✗{Colors.END} {err}") + self.errors.extend(layout_errors) + return False + + if layout_warnings: + 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