From 07ff3c5c54315cbe61b1bcaece64ba058457352e Mon Sep 17 00:00:00 2001 From: bsiggel Date: Sat, 24 Jan 2026 13:01:04 +0100 Subject: [PATCH 1/5] Add CKndigung entity and related resources - Created CKndigung controller extending BasePlus. - Added internationalization support for CKndigung in multiple languages (ar_AR, bg_BG, cs_CZ, da_DK, de_DE, en_GB, en_US, es_ES, es_MX, fa_IR, fr_FR, hr_HR, hu_HU, id_ID, it_IT, ja_JP, lt_LT, lv_LV, nb_NO, nl_NL, pl_PL, pt_BR, pt_PT, ro_RO, ru_RU, sk_SK, sl_SI, sr_RS, sv_SE, th_TH, tr_TR, uk_UA, vi_VN, zh_CN, zh_TW). - Defined CKndigung metadata including entity definitions, record definitions, and scopes. - Updated global configuration to include CKndigung in relevant lists. --- custom/Espo/Custom/Controllers/CKndigung.php | 7 ++ .../Resources/i18n/ar_AR/CKndigung.json | 10 ++ .../Resources/i18n/bg_BG/CKndigung.json | 10 ++ .../Resources/i18n/cs_CZ/CKndigung.json | 5 + .../Resources/i18n/da_DK/CKndigung.json | 10 ++ .../Resources/i18n/de_DE/CKndigung.json | 9 ++ .../Resources/i18n/en_GB/CKndigung.json | 1 + .../Resources/i18n/en_US/CKndigung.json | 12 ++ .../Custom/Resources/i18n/en_US/Global.json | 6 +- .../Resources/i18n/es_ES/CKndigung.json | 10 ++ .../Resources/i18n/es_MX/CKndigung.json | 10 ++ .../Resources/i18n/fa_IR/CKndigung.json | 10 ++ .../Resources/i18n/fr_FR/CKndigung.json | 5 + .../Resources/i18n/hr_HR/CKndigung.json | 10 ++ .../Resources/i18n/hu_HU/CKndigung.json | 10 ++ .../Resources/i18n/id_ID/CKndigung.json | 5 + .../Resources/i18n/it_IT/CKndigung.json | 10 ++ .../Resources/i18n/ja_JP/CKndigung.json | 10 ++ .../Resources/i18n/lt_LT/CKndigung.json | 10 ++ .../Resources/i18n/lv_LV/CKndigung.json | 10 ++ .../Resources/i18n/nb_NO/CKndigung.json | 10 ++ .../Resources/i18n/nl_NL/CKndigung.json | 10 ++ .../Resources/i18n/pl_PL/CKndigung.json | 10 ++ .../Resources/i18n/pt_BR/CKndigung.json | 10 ++ .../Resources/i18n/pt_PT/CKndigung.json | 10 ++ .../Resources/i18n/ro_RO/CKndigung.json | 5 + .../Resources/i18n/ru_RU/CKndigung.json | 10 ++ .../Resources/i18n/sk_SK/CKndigung.json | 10 ++ .../Resources/i18n/sl_SI/CKndigung.json | 10 ++ .../Resources/i18n/sr_RS/CKndigung.json | 10 ++ .../Resources/i18n/sv_SE/CKndigung.json | 10 ++ .../Resources/i18n/th_TH/CKndigung.json | 10 ++ .../Resources/i18n/tr_TR/CKndigung.json | 10 ++ .../Resources/i18n/uk_UA/CKndigung.json | 10 ++ .../Resources/i18n/vi_VN/CKndigung.json | 10 ++ .../Resources/i18n/zh_CN/CKndigung.json | 10 ++ .../Resources/i18n/zh_TW/CKndigung.json | 10 ++ .../metadata/clientDefs/CKndigung.json | 37 ++++++ .../metadata/entityDefs/CKndigung.json | 110 ++++++++++++++++++ .../Resources/metadata/entityDefs/Call.json | 3 +- .../Resources/metadata/entityDefs/Email.json | 3 +- .../metadata/entityDefs/Meeting.json | 3 +- .../Resources/metadata/entityDefs/Task.json | 3 +- .../metadata/recordDefs/CKndigung.json | 3 + .../Resources/metadata/scopes/CKndigung.json | 23 ++++ data/config.php | 7 +- 46 files changed, 518 insertions(+), 9 deletions(-) create mode 100644 custom/Espo/Custom/Controllers/CKndigung.php create mode 100644 custom/Espo/Custom/Resources/i18n/ar_AR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/bg_BG/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/cs_CZ/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/da_DK/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/de_DE/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/en_GB/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/en_US/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/es_ES/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/es_MX/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/fa_IR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/fr_FR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/hr_HR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/hu_HU/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/id_ID/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/it_IT/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/ja_JP/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/lt_LT/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/lv_LV/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/nb_NO/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/nl_NL/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/pl_PL/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/pt_BR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/pt_PT/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/ro_RO/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/ru_RU/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/sk_SK/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/sl_SI/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/sr_RS/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/sv_SE/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/th_TH/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/tr_TR/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/uk_UA/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/vi_VN/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/zh_CN/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/i18n/zh_TW/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/metadata/clientDefs/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/metadata/entityDefs/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/metadata/recordDefs/CKndigung.json create mode 100644 custom/Espo/Custom/Resources/metadata/scopes/CKndigung.json diff --git a/custom/Espo/Custom/Controllers/CKndigung.php b/custom/Espo/Custom/Controllers/CKndigung.php new file mode 100644 index 00000000..ae9c7f0c --- /dev/null +++ b/custom/Espo/Custom/Controllers/CKndigung.php @@ -0,0 +1,7 @@ + 'Import', 32 => 'GlobalStream', 33 => 'Report', - 34 => 'CCallQueues' + 34 => 'CCallQueues', + 35 => 'CKndigung' ], 'quickCreateList' => [ 0 => 'Account', @@ -359,8 +360,8 @@ return [ 0 => 'youtube.com', 1 => 'google.com' ], - 'cacheTimestamp' => 1769253751, - 'microtime' => 1769253751.94842, + 'cacheTimestamp' => 1769256001, + 'microtime' => 1769256001.008295, 'siteUrl' => 'https://crm.bitbylaw.com', 'fullTextSearchMinLength' => 4, 'appTimestamp' => 1768843902, From 30326da8c6fe66188a84762d7f156f72875bc591 Mon Sep 17 00:00:00 2001 From: bsiggel Date: Sun, 25 Jan 2026 10:06:02 +0100 Subject: [PATCH 2/5] =?UTF-8?q?Add=20termination=20(K=C3=BCndigung)=20func?= =?UTF-8?q?tionality=20and=20related=20translations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implemented the ability to initiate terminations from Mietverhältnisse. - Added new fields and options for terminations in both German and English language files. - Updated metadata definitions to include relationships for terminations with Mietobjekte and Beteiligte. - Enhanced the service layer to handle termination creation, including linking relevant entities and copying documents. - Updated configuration timestamps for deployment. --- .../Custom/Controllers/CVmhMietverhltnis.php | 18 ++ .../Resources/i18n/de_DE/CBeteiligte.json | 4 + .../Resources/i18n/de_DE/CDokumente.json | 7 +- .../Resources/i18n/de_DE/CKndigung.json | 89 +++++- .../Resources/i18n/de_DE/CMietobjekt.json | 1 + .../i18n/de_DE/CVmhMietverhltnis.json | 10 +- .../Custom/Resources/i18n/de_DE/Contact.json | 3 + .../Resources/i18n/en_US/CBeteiligte.json | 4 + .../Resources/i18n/en_US/CDokumente.json | 7 +- .../Resources/i18n/en_US/CKndigung.json | 86 +++++- .../Resources/i18n/en_US/CMietobjekt.json | 1 + .../i18n/en_US/CVmhMietverhltnis.json | 10 +- .../Custom/Resources/i18n/en_US/Contact.json | 5 +- .../metadata/clientDefs/CKndigung.json | 28 +- .../clientDefs/CVmhMietverhltnis.json | 10 + .../metadata/entityDefs/CBeteiligte.json | 16 + .../metadata/entityDefs/CDokumente.json | 8 + .../metadata/entityDefs/CKndigung.json | 273 +++++++++++++++++- .../metadata/entityDefs/CMietobjekt.json | 8 + .../entityDefs/CVmhMietverhltnis.json | 8 + .../metadata/entityDefs/Contact.json | 8 + .../Custom/Services/CVmhMietverhltnis.php | 181 ++++++++++++ data/config.php | 4 +- 23 files changed, 771 insertions(+), 18 deletions(-) diff --git a/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php b/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php index 78b1a241..36adbe88 100644 --- a/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php +++ b/custom/Espo/Custom/Controllers/CVmhMietverhltnis.php @@ -42,4 +42,22 @@ class CVmhMietverhltnis extends \Espo\Core\Templates\Controllers\BasePlus return $result; } + + /** + * POST Action: Initiate termination (Kündigung) from Mietverhältnis + */ + public function postActionInitiateTermination(Request $request): array + { + $data = $request->getParsedBody(); + + $id = $data->id ?? null; + if (!$id) { + throw new BadRequest('No Mietverhältnis ID provided'); + } + + $service = $this->getRecordService(); + $result = $service->initiateTermination($id); + + return $result; + } } diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json b/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json index 559d2481..ed853e77 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CBeteiligte.json @@ -12,6 +12,8 @@ "vmhRumungsklagesBeklagte": "Beklagte", "mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)", + "kndigungenKuendiger": "Kündigungen (Kündigende)", + "kndigungenGekuendigte": "Kündigungen (Gekündigte)", "adressens": "Adressen", "calls1": "Anrufe", "contactsBeteiligte": "Freigegebene Nutzer", @@ -33,6 +35,8 @@ "vmhRumungsklagesBeklagte": "Beklagte", "mietinkassosKlaeger": "Mietinkasso (Kläger)", "mietinkassosBeklagte": "Mietinkasso (Beklagte)", + "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 8484ef7a..3650c189 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CDokumente.json @@ -13,7 +13,9 @@ "vmhErstgespraechsdokumente": "Erstgespräche", "vmhRumungsklagesdokumente": "Räumungsklagen", "beteiligte2dokumente": "Beteiligte", - "mietobjekt2dokumente": "Mietobjekte" + "mietobjekt2dokumente": "Mietobjekte", + "mietinkassosdokumente": "Mietinkasso", + "kndigungensdokumente": "Kündigungen" }, "links": { "contactsvmhdokumente": "Freigegebene Nutzer", @@ -22,7 +24,8 @@ "vmhRumungsklagesdokumente": "Räumungsklagen", "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 9638c128..b9d58133 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CMietobjekt.json @@ -14,6 +14,7 @@ "contact2mietobjekt": "Kontakte", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", + "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 b95acc7a..b4eccee8 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/CVmhMietverhltnis.json @@ -13,6 +13,7 @@ "warmmiete": "Warmmiete", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", + "kndigungen": "Kündigungen", "vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtemieter": "Mieter", "contactsMietverhltnis": "Freigegebene Nutzer", @@ -33,6 +34,7 @@ "tasks": "Aufgaben", "vmhRumungsklages": "Räumungsklagen", "mietinkassos": "Mietinkasso", + "kndigungen": "Kündigungen", "vmhbeteiligtevermieter": "Vermieter", "vmhbeteiligtemieter": "Mieter", "contactsMietverhltnis": "Freigegebene Nutzer", @@ -44,7 +46,8 @@ "labels": { "Create CVmhMietverhltnis": "Mietverhältnis erstellen", "Initiate Eviction": "Räumungsklage einleiten", - "Initiate Rent Collection": "Mietinkasso einleiten" + "Initiate Rent Collection": "Mietinkasso einleiten", + "Initiate Termination": "Kündigung erstellen" }, "messages": { "confirmEviction": "Möchten Sie wirklich eine Räumungsklage aus diesem Mietverhältnis einleiten?", @@ -52,6 +55,9 @@ "evictionError": "Fehler beim Erstellen der Räumungsklage", "confirmRentCollection": "Möchten Sie wirklich ein Mietinkasso aus diesem Mietverhältnis einleiten?", "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 aus diesem Mietverhältnis erstellen?", + "terminationCreated": "Kündigung wurde erfolgreich erstellt", + "terminationError": "Fehler beim Erstellen der Kündigung" } } \ No newline at end of file diff --git a/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json b/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json index ca681698..f0e22e86 100644 --- a/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json +++ b/custom/Espo/Custom/Resources/i18n/de_DE/Contact.json @@ -14,6 +14,8 @@ "cMietobjekteContactPortal": "Mietobjekte (Portal)", "cAdressenContact": "Adressen", "cVmhRumungsklageContact": "Räumungsklagen (Portal)", + "cMietinkassoContact": "Mietinkasso", + "cKuendigungContact": "Kündigungen", "cBankverbindungenContact": "Bankverbindungen" }, "links": { @@ -29,6 +31,7 @@ "cAdressenContact": "Adressen", "cVmhRumungsklageContact": "Räumungsklagen (Portal)", "cMietinkassoContact": "Mietinkasso", + "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 64018d9c..857943bd 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CBeteiligte.json @@ -11,6 +11,8 @@ "vmhRumungsklagesKlaeger": "Plaintiff", "mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosBeklagte": "Rent Collection (Defendant)", + "kndigungenKuendiger": "Terminations (Terminating Party)", + "kndigungenGekuendigte": "Terminations (Terminated Party)", "contactsBeteiligte": "Portal Users", "dokumentesBeteiligte": "Documents" }, @@ -27,6 +29,8 @@ "vmhRumungsklagesKlaeger": "Plaintiff", "mietinkassosKlaeger": "Rent Collection (Plaintiff)", "mietinkassosBeklagte": "Rent Collection (Defendant)", + "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 03d224db..db20161c 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CDokumente.json @@ -10,7 +10,9 @@ "md5sum": "MD5 Checksum", "sha256": "SHA256 Checksum", "beteiligte2dokumente": "Parties", - "mietobjekt2dokumente": "Properties" + "mietobjekt2dokumente": "Properties", + "mietinkassosdokumente": "Rent Collection", + "kndigungensdokumente": "Terminations" }, "links": { "contactsvmhdokumente": "Portal Users", @@ -19,7 +21,8 @@ "vmhRumungsklagesdokumente": "Eviction Lawsuits", "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 fc630b1c..33210f1a 100644 --- a/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/i18n/en_US/CMietobjekt.json @@ -20,6 +20,7 @@ "contact2mietobjekt": "Contacts", "vmhRumungsklages": "Eviction Lawsuits", "mietinkassos": "Rent Collection", + "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 9b4b1962..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,6 +37,7 @@ "tasks": "Tasks", "vmhRumungsklages": "Eviction Lawsuits", "mietinkassos": "Rent Collection", + "kndigungen": "Terminations", "vmhbeteiligtevermieter": "Landlords", "vmhbeteiligtemieter": "Tenants", "contactsMietverhltnis": "Portal Users", @@ -47,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?", @@ -55,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 f4ac5932..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,6 +25,7 @@ "cAdressenContact": "Addresses", "cVmhRumungsklageContact": "Eviction Lawsuits (Portal)", "cMietinkassoContact": "Rent Collection", + "cKuendigungContact": "Terminations", "cBankverbindungenContact": "Bank Accounts" }, "options": { 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/clientDefs/CVmhMietverhltnis.json b/custom/Espo/Custom/Resources/metadata/clientDefs/CVmhMietverhltnis.json index d23a758e..07e82eca 100644 --- a/custom/Espo/Custom/Resources/metadata/clientDefs/CVmhMietverhltnis.json +++ b/custom/Espo/Custom/Resources/metadata/clientDefs/CVmhMietverhltnis.json @@ -25,6 +25,16 @@ "iconHtml": "", "style": "warning", "acl": "edit" + }, + { + "name": "initiateTermination", + "label": "Initiate Termination", + "handler": "custom:handlers/mietverhaeltnis/termination-action", + "initFunction": "initInitiateTermination", + "actionFunction": "actionInitiateTermination", + "iconHtml": "", + "style": "primary", + "acl": "edit" } ] } diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json index 9eb14219..78120690 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CBeteiligte.json @@ -294,6 +294,22 @@ "audited": false, "isCustom": true }, + "kndigungenKuendiger": { + "type": "hasMany", + "relationName": "cBeteiligteKuendigungKuendiger", + "foreign": "kuendiger", + "entity": "CKndigung", + "audited": false, + "isCustom": true + }, + "kndigungenGekuendigte": { + "type": "hasMany", + "relationName": "cBeteiligteKuendigungGekuendigte", + "foreign": "gekuendigte", + "entity": "CKndigung", + "audited": false, + "isCustom": true + }, "dokumentesBeteiligte": { "type": "hasMany", "relationName": "cBeteiligteDokumente", diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json index ba5ce257..8517b980 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CDokumente.json @@ -176,6 +176,14 @@ "audited": false, "isCustom": true }, + "kndigungensdokumente": { + "type": "hasMany", + "relationName": "cDokumenteKuendigung", + "foreign": "dokumenteskuendigung", + "entity": "CKndigung", + "audited": false, + "isCustom": true + }, "beteiligte2dokumente": { "type": "hasMany", "relationName": "cBeteiligteDokumente", 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 c653ac24..b54e7cd8 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/CMietobjekt.json @@ -157,6 +157,14 @@ "entity": "CMietinkasso", "audited": false, "isCustom": true + }, + "kndigungen": { + "type": "hasMany", + "relationName": "cMietobjektKuendigung", + "foreign": "mietobjekte", + "entity": "CKndigung", + "audited": false, + "isCustom": true } }, "collection": { diff --git a/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json b/custom/Espo/Custom/Resources/metadata/entityDefs/CVmhMietverhltnis.json index 45b642d2..e6ba3874 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 1e8fca88..a1f5a00d 100644 --- a/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json +++ b/custom/Espo/Custom/Resources/metadata/entityDefs/Contact.json @@ -94,6 +94,14 @@ "audited": false, "isCustom": true }, + "cKuendigungContact": { + "type": "hasMany", + "relationName": "cKuendigungContact", + "foreign": "contactsKuendigung", + "entity": "CKndigung", + "audited": false, + "isCustom": true + }, "cBankverbindungenContact": { "type": "hasMany", "relationName": "cBankverbindungContact", diff --git a/custom/Espo/Custom/Services/CVmhMietverhltnis.php b/custom/Espo/Custom/Services/CVmhMietverhltnis.php index b28c3081..e23fcc0b 100644 --- a/custom/Espo/Custom/Services/CVmhMietverhltnis.php +++ b/custom/Espo/Custom/Services/CVmhMietverhltnis.php @@ -368,4 +368,185 @@ class CVmhMietverhltnis extends \Espo\Services\Record throw $e; } } + + /** + * Initiate termination (Kündigung) from Mietverhältnis + * + * @param string $mietverhaeltnisId + * @return array + * @throws NotFound + * @throws Forbidden + */ + public function initiateTermination(string $mietverhaeltnisId): array + { + // 1. Load Mietverhältnis + $mietverhaeltnis = $this->entityManager->getEntity('CVmhMietverhltnis', $mietverhaeltnisId); + if (!$mietverhaeltnis) { + throw new NotFound('Mietverhältnis not found'); + } + + // 2. ACL Checks + if (!$this->acl->check($mietverhaeltnis, 'read')) { + throw new Forbidden('No read access to Mietverhältnis'); + } + + if (!$this->acl->checkScope('CKndigung', 'create')) { + throw new Forbidden('No create access to Kündigung'); + } + + // 3. Start Transaction + $this->entityManager->getTransactionManager()->start(); + + try { + // 4. Prepare data for new Kündigung + $data = new \stdClass(); + $data->name = 'Kündigung - ' . $mietverhaeltnis->get('name'); + + // Copy assignedUser and teams + if ($mietverhaeltnis->get('assignedUserId')) { + $data->assignedUserId = $mietverhaeltnis->get('assignedUserId'); + } + + $teamsIds = $mietverhaeltnis->getLinkMultipleIdList('teams'); + if (!empty($teamsIds)) { + $data->teamsIds = $teamsIds; + } + + // 5. Create Kündigung entity + $kuendigung = $this->entityManager->createEntity('CKndigung', (array)$data); + + if (!$kuendigung) { + throw new \RuntimeException('Failed to create Kündigung'); + } + + $kuendigungRepo = $this->entityManager->getRepository('CKndigung'); + + // 6. Link Mietverhältnis to Kündigung + $kuendigungRepo + ->getRelation($kuendigung, 'vmhMietverhltnises') + ->relate($mietverhaeltnis); + + // 7. Get and link Mietobjekt + $mietobjekt = $this->entityManager + ->getRepository('CVmhMietverhltnis') + ->getRelation($mietverhaeltnis, 'vmhMietobjekt') + ->findOne(); + + if ($mietobjekt) { + $kuendigungRepo + ->getRelation($kuendigung, 'mietobjekte') + ->relate($mietobjekt); + } + + // 8. Get Vermieter (Kündigende) from Mietverhältnis + $vermieterBeteiligte = $this->entityManager + ->getRepository('CVmhMietverhltnis') + ->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter') + ->find(); + + foreach ($vermieterBeteiligte as $vermieter) { + // Link as Kündigende + $kuendigungRepo + ->getRelation($kuendigung, 'kuendiger') + ->relate($vermieter); + } + + // 9. Get Mieter (Gekündigte) from Mietverhältnis + $mieterBeteiligte = $this->entityManager + ->getRepository('CVmhMietverhltnis') + ->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter') + ->find(); + + foreach ($mieterBeteiligte as $mieter) { + // Link as Gekündigte + $kuendigungRepo + ->getRelation($kuendigung, 'gekuendigte') + ->relate($mieter); + } + + // 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') + ->find(); + + foreach ($portalContacts as $contact) { + $kuendigungRepo + ->getRelation($kuendigung, 'contactsKuendigung') + ->relate($contact); + } + + // 12. Commit transaction + $this->entityManager->getTransactionManager()->commit(); + + return [ + 'id' => $kuendigung->getId(), + 'name' => $kuendigung->get('name') + ]; + } catch (\Exception $e) { + // Rollback on any error + $this->entityManager->getTransactionManager()->rollback(); + throw $e; + } + } } diff --git a/data/config.php b/data/config.php index b5e1d35a..d325c9d3 100644 --- a/data/config.php +++ b/data/config.php @@ -360,8 +360,8 @@ return [ 0 => 'youtube.com', 1 => 'google.com' ], - 'cacheTimestamp' => 1769256001, - 'microtime' => 1769256001.008295, + 'cacheTimestamp' => 1769331937, + 'microtime' => 1769331937.84435, 'siteUrl' => 'https://crm.bitbylaw.com', 'fullTextSearchMinLength' => 4, 'appTimestamp' => 1768843902, From eaeba65487e530ff2689a4c84ba2506eba46a122 Mon Sep 17 00:00:00 2001 From: bsiggel Date: Sun, 25 Jan 2026 10:26:44 +0100 Subject: [PATCH 3/5] Add CKndigung layout files and update cache timestamps; improve UI structure and error handling --- README.md | 66 ++++++++-- .../layouts/CKndigung/bottomPanelsDetail.json | 63 ++++++++++ .../layouts/CKndigung/defaultSidePanel.json | 11 ++ .../Resources/layouts/CKndigung/detail.json | 114 ++++++++++++++++++ .../layouts/CKndigung/detailSmall.json | 33 +++++ .../Resources/layouts/CKndigung/list.json | 31 +++++ .../layouts/CKndigung/listSmall.json | 15 +++ data/config.php | 4 +- 8 files changed, 323 insertions(+), 14 deletions(-) create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/bottomPanelsDetail.json create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/defaultSidePanel.json create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/detail.json create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/detailSmall.json create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/list.json create mode 100644 custom/Espo/Custom/Resources/layouts/CKndigung/listSmall.json 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/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/data/config.php b/data/config.php index d325c9d3..ce2db9c3 100644 --- a/data/config.php +++ b/data/config.php @@ -360,8 +360,8 @@ return [ 0 => 'youtube.com', 1 => 'google.com' ], - 'cacheTimestamp' => 1769331937, - 'microtime' => 1769331937.84435, + 'cacheTimestamp' => 1769332527, + 'microtime' => 1769332527.595512, 'siteUrl' => 'https://crm.bitbylaw.com', 'fullTextSearchMinLength' => 4, 'appTimestamp' => 1768843902, From fb6ef2b9600c991736498082cfdafc114fbba496 Mon Sep 17 00:00:00 2001 From: bsiggel Date: Sun, 25 Jan 2026 10:28:19 +0100 Subject: [PATCH 4/5] Enhance layout validation in EntityValidator; add critical checks for bottomPanelsDetail.json and detail.json files, and improve error/warning reporting --- custom/scripts/validate_and_rebuild.py | 111 ++++++++++++++++++------- 1 file changed, 79 insertions(+), 32 deletions(-) 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 From 3a987547b3dbbd407be8878840598d29524d9a2a Mon Sep 17 00:00:00 2001 From: bsiggel Date: Sun, 25 Jan 2026 10:29:46 +0100 Subject: [PATCH 5/5] Refactor layout configurations in multiple detail.json files; replace 'false' with empty objects for improved structure and consistency --- .../Espo/Custom/Resources/layouts/CBeteiligte/detail.json | 6 +++--- custom/Espo/Custom/Resources/layouts/CDokumente/detail.json | 4 ++-- .../Espo/Custom/Resources/layouts/CMietinkasso/detail.json | 2 +- .../Espo/Custom/Resources/layouts/CMietobjekt/detail.json | 2 +- .../Custom/Resources/layouts/CVmhMietverhltnis/detail.json | 6 +++--- .../Custom/Resources/layouts/CVmhRumungsklage/detail.json | 2 +- .../Espo/Custom/Resources/layouts/CVmhVermieter/detail.json | 2 +- custom/Espo/Custom/Resources/layouts/Contact/detail.json | 4 ++-- custom/Espo/Custom/Resources/layouts/User/detail.json | 2 +- data/config.php | 4 ++-- 10 files changed, 17 insertions(+), 17 deletions(-) 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/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/data/config.php b/data/config.php index ce2db9c3..27623420 100644 --- a/data/config.php +++ b/data/config.php @@ -360,8 +360,8 @@ return [ 0 => 'youtube.com', 1 => 'google.com' ], - 'cacheTimestamp' => 1769332527, - 'microtime' => 1769332527.595512, + 'cacheTimestamp' => 1769333341, + 'microtime' => 1769333341.168211, 'siteUrl' => 'https://crm.bitbylaw.com', 'fullTextSearchMinLength' => 4, 'appTimestamp' => 1768843902,