Implement eviction lawsuit initiation feature for Mietobjekt; add related UI and backend logic; update localization and configuration

This commit is contained in:
2026-01-24 11:51:16 +01:00
parent 3da6d140c7
commit ec612318c3
8 changed files with 250 additions and 4 deletions

View File

@@ -2,6 +2,27 @@
namespace Espo\Custom\Controllers;
use Espo\Core\Exceptions\BadRequest;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Api\Request;
class CMietobjekt extends \Espo\Core\Templates\Controllers\Base
{
/**
* POST Action: Initiate eviction lawsuit from Mietobjekt
*/
public function postActionInitiateEviction(Request $request): array
{
$data = $request->getParsedBody();
$id = $data->id ?? null;
if (!$id) {
throw new BadRequest('No Mietobjekt ID provided');
}
$service = $this->getRecordService();
$result = $service->initiateEviction($id);
return $result;
}
}

View File

@@ -18,9 +18,15 @@
"dokumentesMietobjekt": "Dokumente"
},
"labels": {
"Create CMietobjekt": "Mietobjekt erstellen"
"Create CMietobjekt": "Mietobjekt erstellen",
"Räumungsklage einleiten": "Räumungsklage einleiten"
},
"tooltips": {
"lage": "Lage innerhalb des Objekts (z.B. EG links, 1. OG rechts)"
},
"messages": {
"initiateEvictionConfirmation": "Möchten Sie für dieses Mietobjekt eine Räumungsklage einleiten? Es werden automatisch alle zugehörigen Mietverhältnisse, Vermieter (als Kläger) und Mieter (als Beklagte) verknüpft.",
"evictionCreatedSuccess": "Räumungsklage wurde erfolgreich erstellt",
"evictionCreatedError": "Fehler beim Erstellen der Räumungsklage"
}
}

View File

@@ -24,7 +24,8 @@
"dokumentesMietobjekt": "Documents"
},
"labels": {
"Create CMietobjekt": "Create Mietobjekt"
"Create CMietobjekt": "Create Mietobjekt",
"Räumungsklage einleiten": "Initiate Eviction Lawsuit"
},
"options": {
"objekttyp": {
@@ -42,5 +43,10 @@
},
"tooltips": {
"lage": "Location within the property (e.g. ground floor left, 1st floor right)"
},
"messages": {
"initiateEvictionConfirmation": "Do you want to initiate an eviction lawsuit for this property? All associated rental agreements, landlords (as plaintiffs) and tenants (as defendants) will be automatically linked.",
"evictionCreatedSuccess": "Eviction lawsuit created successfully",
"evictionCreatedError": "Error creating eviction lawsuit"
}
}

View File

@@ -5,6 +5,22 @@
],
"color": "#dea185",
"iconClass": "fas fa-house",
"menu": {
"detail": {
"buttons": [
{
"label": "Räumungsklage einleiten",
"name": "initiateEviction",
"iconHtml": "<span class=\"fas fa-gavel fa-sm\"></span>",
"style": "danger",
"acl": "edit",
"handler": "custom:handlers/mietobjekt/eviction-action",
"initFunction": "initEvictionAction",
"actionFunction": "initiateEviction"
}
]
}
},
"relationshipPanels": {
"vmhMietverhltnises2Mietobjekt": {
"layout": null,

View File

@@ -0,0 +1,132 @@
<?php
namespace Espo\Custom\Services;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\NotFound;
use Espo\ORM\Entity;
class CMietobjekt extends \Espo\Services\Record
{
/**
* Initiate eviction lawsuit (Räumungsklage) from Mietobjekt
*
* @param string $mietobjektId
* @return array
* @throws NotFound
* @throws Forbidden
*/
public function initiateEviction(string $mietobjektId): array
{
// Load Mietobjekt
$mietobjekt = $this->entityManager->getEntity('CMietobjekt', $mietobjektId);
if (!$mietobjekt) {
throw new NotFound('Mietobjekt not found');
}
// Check ACL - Read and Create permissions
if (!$this->acl->check($mietobjekt, 'read')) {
throw new Forbidden('No read access to Mietobjekt');
}
if (!$this->acl->checkScope('CVmhRumungsklage', 'create')) {
throw new Forbidden('No create access to Räumungsklage');
}
// Start transaction to ensure atomicity
$this->entityManager->getTransactionManager()->start();
try {
// Prepare data for new Räumungsklage
$data = new \stdClass();
$data->name = 'Räumungsklage - ' . $mietobjekt->get('name');
// Copy assignedUser and teams
if ($mietobjekt->get('assignedUserId')) {
$data->assignedUserId = $mietobjekt->get('assignedUserId');
}
$teamsIds = $mietobjekt->getLinkMultipleIdList('teams');
if (!empty($teamsIds)) {
$data->teamsIds = $teamsIds;
}
// Create Räumungsklage entity
$raeumungsklage = $this->entityManager->createEntity('CVmhRumungsklage', (array)$data);
if (!$raeumungsklage) {
throw new \RuntimeException('Failed to create Räumungsklage');
}
$raeumungsklagenRepo = $this->entityManager->getRepository('CVmhRumungsklage');
// Link Mietobjekt to Räumungsklage
$raeumungsklagenRepo
->getRelation($raeumungsklage, 'mietobjekte')
->relate($mietobjekt);
// Get and link Mietverhältnisse
$mietverhaeltnisse = $this->entityManager
->getRepository('CMietobjekt')
->getRelation($mietobjekt, 'vmhMietverhltnises')
->find();
foreach ($mietverhaeltnisse as $mietverhaeltnis) {
// Link Mietverhältnis to Räumungsklage
$raeumungsklagenRepo
->getRelation($raeumungsklage, 'vmhMietverhltnises')
->relate($mietverhaeltnis);
// Get Vermieter (Kläger) from Mietverhältnis
$vermieterBeteiligte = $this->entityManager
->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter')
->find();
foreach ($vermieterBeteiligte as $vermieter) {
// Link as Kläger
$raeumungsklagenRepo
->getRelation($raeumungsklage, 'klaeger')
->relate($vermieter);
}
// Get Mieter (Beklagte) from Mietverhältnis
$mieterBeteiligte = $this->entityManager
->getRepository('CVmhMietverhltnis')
->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter')
->find();
foreach ($mieterBeteiligte as $mieter) {
// Link as Beklagte
$raeumungsklagenRepo
->getRelation($raeumungsklage, 'beklagte')
->relate($mieter);
}
}
// Copy portal contacts from Mietobjekt
$portalContacts = $this->entityManager
->getRepository('CMietobjekt')
->getRelation($mietobjekt, 'contactsMietobjekt')
->find();
foreach ($portalContacts as $contact) {
$raeumungsklagenRepo
->getRelation($raeumungsklage, 'contactsRumungsklage')
->relate($contact);
}
// Commit transaction
$this->entityManager->getTransactionManager()->commit();
return [
'id' => $raeumungsklage->getId(),
'name' => $raeumungsklage->get('name')
];
} catch (\Exception $e) {
// Rollback on any error
$this->entityManager->getTransactionManager()->rollback();
throw $e;
}
}
}