entityManager->getEntity($sourceEntityType, $sourceEntityId); if (!$sourceEntity) { throw new NotFound("$sourceEntityType not found"); } // 2. ACL Checks if (!$this->acl->check($sourceEntity, 'read')) { throw new Forbidden("No read access to $sourceEntityType"); } if (!$this->acl->checkScope('CVmhRumungsklage', 'create')) { throw new Forbidden('No create access to Räumungsklage'); } // 3. Start Transaction $this->entityManager->getTransactionManager()->start(); try { // 4. Collect all related Mietverhältnisse and Kündigungen [$alleMietverhaeltnisse, $alleKuendigungen] = $this->collectRelatedEntities( $sourceEntityType, $sourceEntity ); // 5. Create Räumungsklage from collected entities $result = $this->createFromCollectedEntities($alleMietverhaeltnisse, $alleKuendigungen); // 6. Log to stream $this->logToStream($sourceEntity, $sourceEntityType, $result['id']); // 7. Commit transaction $this->entityManager->getTransactionManager()->commit(); return $result; } catch (\Exception $e) { // Rollback on any error $this->entityManager->getTransactionManager()->rollback(); throw $e; } } /** * Collect all related Mietverhältnisse and Kündigungen from source entity * * @param string $sourceEntityType * @param object $sourceEntity * @return array [alleMietverhaeltnisse, alleKuendigungen] */ private function collectRelatedEntities(string $sourceEntityType, $sourceEntity): array { $alleMietverhaeltnisse = []; $alleKuendigungen = []; if ($sourceEntityType === 'CVmhMietverhltnis') { // Start from Mietverhältnis $alleMietverhaeltnisse = [$sourceEntity]; // Collect all Kündigungen from this Mietverhältnis $kuendigungen = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($sourceEntity, 'kndigungen') ->find(); foreach ($kuendigungen as $kuendigung) { $alleKuendigungen[] = $kuendigung; } } elseif ($sourceEntityType === 'CKuendigung') { // Start from Kündigung $alleKuendigungen = [$sourceEntity]; $alleKuendigungIds = [$sourceEntity->getId()]; // Collect all Mietverhältnisse from this Kündigung $mietverhaeltnisse = $this->entityManager ->getRepository('CKuendigung') ->getRelation($sourceEntity, 'vmhMietverhltnises') ->find(); foreach ($mietverhaeltnisse as $mv) { $alleMietverhaeltnisse[] = $mv; } // Collect any other Kündigungen from these Mietverhältnisse foreach ($alleMietverhaeltnisse as $mv) { $kuendigungen = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'kndigungen') ->find(); foreach ($kuendigungen as $k) { if (!in_array($k->getId(), $alleKuendigungIds)) { $alleKuendigungen[] = $k; $alleKuendigungIds[] = $k->getId(); } } } } else { throw new BadRequest("Unsupported source entity type: $sourceEntityType"); } return [$alleMietverhaeltnisse, $alleKuendigungen]; } /** * Create Räumungsklage from collected Mietverhältnisse and Kündigungen * * @param array $alleMietverhaeltnisse * @param array $alleKuendigungen * @return array */ private function createFromCollectedEntities(array $alleMietverhaeltnisse, array $alleKuendigungen): array { // 1. Get Advoware fields from Kündigungen (first with values) $advowareAktenzeichen = null; $aktennr = null; foreach ($alleKuendigungen as $kuendigung) { if (!$advowareAktenzeichen && $kuendigung->get('advowareAktenzeichen')) { $advowareAktenzeichen = $kuendigung->get('advowareAktenzeichen'); } if (!$aktennr && $kuendigung->get('aktennr')) { $aktennr = $kuendigung->get('aktennr'); } if ($advowareAktenzeichen && $aktennr) { break; // Found both, no need to continue } } // 2. Prepare data for new Räumungsklage $data = new \stdClass(); // Use name from first Mietverhältnis $data->name = 'Räumungsklage - ' . $alleMietverhaeltnisse[0]->get('name'); // Copy Advoware fields if found if ($advowareAktenzeichen) { $data->advowareAktenzeichen = $advowareAktenzeichen; } if ($aktennr) { $data->aktennr = $aktennr; } // Copy assignedUser and teams from first Mietverhältnis if ($alleMietverhaeltnisse[0]->get('assignedUserId')) { $data->assignedUserId = $alleMietverhaeltnisse[0]->get('assignedUserId'); } $teamsIds = $alleMietverhaeltnisse[0]->getLinkMultipleIdList('teams'); if (!empty($teamsIds)) { $data->teamsIds = $teamsIds; } // 3. 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'); // 4. Link all Mietverhältnisse to Räumungsklage foreach ($alleMietverhaeltnisse as $mv) { $raeumungsklagenRepo ->getRelation($raeumungsklage, 'vmhMietverhltnises') ->relate($mv); } // 5. Collect all Mietobjekte from all Mietverhältnisse $alleMietobjekte = []; foreach ($alleMietverhaeltnisse as $mv) { $mietobjekt = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'vmhMietobjekt') ->findOne(); if ($mietobjekt && !in_array($mietobjekt->getId(), array_map(fn($m) => $m->getId(), $alleMietobjekte))) { $alleMietobjekte[] = $mietobjekt; } } // Link all unique Mietobjekte foreach ($alleMietobjekte as $mietobjekt) { $raeumungsklagenRepo ->getRelation($raeumungsklage, 'mietobjekte') ->relate($mietobjekt); } // 6. Collect all Beteiligte from all Mietverhältnisse $alleVermieter = []; $alleMieter = []; $alleSonstigeBewohner = []; foreach ($alleMietverhaeltnisse as $mv) { // Vermieter $vermieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'vmhbeteiligtevermieter') ->find(); foreach ($vermieterBeteiligte as $vermieter) { if (!in_array($vermieter->getId(), array_map(fn($v) => $v->getId(), $alleVermieter))) { $alleVermieter[] = $vermieter; } } // Mieter $mieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'vmhbeteiligtemieter') ->find(); foreach ($mieterBeteiligte as $mieter) { if (!in_array($mieter->getId(), array_map(fn($m) => $m->getId(), $alleMieter))) { $alleMieter[] = $mieter; } } // Sonstige Bewohner $sonstigeBewohner = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'sonstigebesitzervmhmietverhltnis') ->find(); foreach ($sonstigeBewohner as $bewohner) { if (!in_array($bewohner->getId(), array_map(fn($b) => $b->getId(), $alleSonstigeBewohner))) { $alleSonstigeBewohner[] = $bewohner; } } } // Link Vermieter as Kläger foreach ($alleVermieter as $vermieter) { $raeumungsklagenRepo ->getRelation($raeumungsklage, 'klaeger') ->relate($vermieter); } // Link Mieter and Sonstige as Beklagte foreach (array_merge($alleMieter, $alleSonstigeBewohner) as $beklagter) { $raeumungsklagenRepo ->getRelation($raeumungsklage, 'beklagte') ->relate($beklagter); } // 7. Collect all documents from Mietverhältnisse, Kündigungen, Mietobjekte and Beteiligte $alleLinkedDokumente = []; // 7a. Dokumente from all Mietverhältnisse foreach ($alleMietverhaeltnisse as $mv) { $dokumenteMV = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'dokumentesvmhMietverhltnisse') ->find(); foreach ($dokumenteMV as $dokument) { if (!in_array($dokument->getId(), $alleLinkedDokumente)) { $alleLinkedDokumente[] = $dokument->getId(); $raeumungsklagenRepo ->getRelation($raeumungsklage, 'dokumentesvmhraumungsklage') ->relate($dokument); } } } // 7b. Dokumente from all Kündigungen foreach ($alleKuendigungen as $kuendigung) { $dokumenteKuendigung = $this->entityManager ->getRepository('CKuendigung') ->getRelation($kuendigung, 'dokumenteskuendigung') ->find(); foreach ($dokumenteKuendigung as $dokument) { if (!in_array($dokument->getId(), $alleLinkedDokumente)) { $alleLinkedDokumente[] = $dokument->getId(); $raeumungsklagenRepo ->getRelation($raeumungsklage, 'dokumentesvmhraumungsklage') ->relate($dokument); } } } // 7c. Dokumente from all Mietobjekte foreach ($alleMietobjekte as $mietobjekt) { $dokumenteMO = $this->entityManager ->getRepository('CMietobjekt') ->getRelation($mietobjekt, 'dokumentesMietobjekt') ->find(); foreach ($dokumenteMO as $dokument) { if (!in_array($dokument->getId(), $alleLinkedDokumente)) { $alleLinkedDokumente[] = $dokument->getId(); $raeumungsklagenRepo ->getRelation($raeumungsklage, 'dokumentesvmhraumungsklage') ->relate($dokument); } } } // 7d. Dokumente from all Beteiligte $alleBeteiligte = array_merge($alleVermieter, $alleMieter, $alleSonstigeBewohner); foreach ($alleBeteiligte as $beteiligter) { $dokumenteBet = $this->entityManager ->getRepository('CBeteiligte') ->getRelation($beteiligter, 'dokumentesBeteiligte') ->find(); foreach ($dokumenteBet as $dokument) { if (!in_array($dokument->getId(), $alleLinkedDokumente)) { $alleLinkedDokumente[] = $dokument->getId(); $raeumungsklagenRepo ->getRelation($raeumungsklage, 'dokumentesvmhraumungsklage') ->relate($dokument); } } } // 8. Copy portal contacts from all Mietverhältnisse $alleLinkedContacts = []; foreach ($alleMietverhaeltnisse as $mv) { $portalContacts = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mv, 'contactsMietverhltnis') ->find(); foreach ($portalContacts as $contact) { if (!in_array($contact->getId(), $alleLinkedContacts)) { $alleLinkedContacts[] = $contact->getId(); $raeumungsklagenRepo ->getRelation($raeumungsklage, 'contactsRumungsklage') ->relate($contact); } } } return [ 'id' => $raeumungsklage->getId(), 'name' => $raeumungsklage->get('name') ]; } /** * Log Räumungsklage creation to source entity stream * * @param object $sourceEntity Source entity (Mietverhältnis or Kündigung) * @param string $sourceEntityType Entity type * @param string $raeumungsklagenId Created Räumungsklage ID */ private function logToStream($sourceEntity, string $sourceEntityType, string $raeumungsklagenId): void { // Create stream service $streamService = $this->injectableFactory->create(StreamService::class); // Create Note entity manually for custom message $note = $this->entityManager->getEntity('Note'); $note->set([ 'type' => Note::TYPE_CREATE_RELATED, 'parentType' => $sourceEntityType, 'parentId' => $sourceEntity->getId(), 'relatedType' => 'CVmhRumungsklage', 'relatedId' => $raeumungsklagenId, 'data' => [ 'action' => 'initiateEviction', 'actionLabel' => 'Räumungsklage einleiten' ] ]); $this->entityManager->saveEntity($note); } }