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('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 (just this one) $alleMietverhaeltnisse = [$mietverhaeltnis]; // 5. Collect all related Kündigungen from this Mietverhältnis $alleKuendigungen = []; $kuendigungen = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'kndigungen') ->find(); foreach ($kuendigungen as $kuendigung) { $alleKuendigungen[] = $kuendigung; } // 6. 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 } } // 7. 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 if ($mietverhaeltnis->get('assignedUserId')) { $data->assignedUserId = $mietverhaeltnis->get('assignedUserId'); } $teamsIds = $mietverhaeltnis->getLinkMultipleIdList('teams'); if (!empty($teamsIds)) { $data->teamsIds = $teamsIds; } // 8. 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'); // 9. Link all Mietverhältnisse to Räumungsklage foreach ($alleMietverhaeltnisse as $mv) { $raeumungsklagenRepo ->getRelation($raeumungsklage, 'vmhMietverhltnises') ->relate($mv); } // 10. 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); } // 11. 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); } // 12. Collect all documents from Mietverhältnisse, Kündigungen, Mietobjekte and Beteiligte $alleLinkedDokumente = []; // 12a. 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); } } } // 12b. 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); } } } // 12c. 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); } } } // 12d. 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); } } } // 13. 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); } } } // 14. 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; } } /** * Initiate rent collection (Mietinkasso) from Mietverhältnis * * @param string $mietverhaeltnisId * @return array * @throws NotFound * @throws Forbidden */ public function initiateRentCollection(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('CMietinkasso', 'create')) { throw new Forbidden('No create access to Mietinkasso'); } // 3. Start Transaction $this->entityManager->getTransactionManager()->start(); try { // 4. Prepare data for new Mietinkasso $data = new \stdClass(); $data->name = 'Mietinkasso - ' . $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 Mietinkasso entity $mietinkasso = $this->entityManager->createEntity('CMietinkasso', (array)$data); if (!$mietinkasso) { throw new \RuntimeException('Failed to create Mietinkasso'); } $mietinkassoRepo = $this->entityManager->getRepository('CMietinkasso'); // 6. Link Mietverhältnis to Mietinkasso $mietinkassoRepo ->getRelation($mietinkasso, 'vmhMietverhltnises') ->relate($mietverhaeltnis); // 7. Get and link Mietobjekt $mietobjekt = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhMietobjekt') ->findOne(); if ($mietobjekt) { $mietinkassoRepo ->getRelation($mietinkasso, 'mietobjekte') ->relate($mietobjekt); } // 8. Get Vermieter (Kläger) from Mietverhältnis $vermieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter') ->find(); foreach ($vermieterBeteiligte as $vermieter) { // Link as Kläger $mietinkassoRepo ->getRelation($mietinkasso, 'klaeger') ->relate($vermieter); } // 9. Get Mieter (Beklagte) from Mietverhältnis $mieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter') ->find(); foreach ($mieterBeteiligte as $mieter) { // Link as Beklagte $mietinkassoRepo ->getRelation($mietinkasso, 'beklagte') ->relate($mieter); } // 9b. Get Sonstige Bewohner (auch Beklagte) from Mietverhältnis $sonstigeBewohner = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'sonstigebesitzervmhmietverhltnis') ->find(); foreach ($sonstigeBewohner as $bewohner) { // Link as Beklagte $mietinkassoRepo ->getRelation($mietinkasso, 'beklagte') ->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) { $mietinkassoRepo ->getRelation($mietinkasso, 'dokumentesmietinkasso') ->relate($dokument); } // 10b. Dokumente vom Mietobjekt if ($mietobjekt) { $dokumenteMO = $this->entityManager ->getRepository('CMietobjekt') ->getRelation($mietobjekt, 'dokumentesMietobjekt') ->find(); foreach ($dokumenteMO as $dokument) { $mietinkassoRepo ->getRelation($mietinkasso, 'dokumentesmietinkasso') ->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) { $mietinkassoRepo ->getRelation($mietinkasso, 'dokumentesmietinkasso') ->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) { $mietinkassoRepo ->getRelation($mietinkasso, 'contactsMietinkasso') ->relate($contact); } // 12. Commit transaction $this->entityManager->getTransactionManager()->commit(); return [ 'id' => $mietinkasso->getId(), 'name' => $mietinkasso->get('name') ]; } catch (\Exception $e) { // Rollback on any error $this->entityManager->getTransactionManager()->rollback(); 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('CKuendigung', '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('CKuendigung', (array)$data); if (!$kuendigung) { throw new \RuntimeException('Failed to create Kündigung'); } $kuendigungRepo = $this->entityManager->getRepository('CKuendigung'); // 6. Link Mietverhältnis to Kündigung $kuendigungRepo ->getRelation($kuendigung, 'vmhMietverhltnises') ->relate($mietverhaeltnis); // 7. Get Vermieter from Mietverhältnis $vermieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtevermieter') ->find(); foreach ($vermieterBeteiligte as $vermieter) { // Link as Kuendiger (Vermieter) $kuendigungRepo ->getRelation($kuendigung, 'kuendiger') ->relate($vermieter); } // 8. Get Mieter from Mietverhältnis (NUR Mieter, NICHT sonstige Bewohner!) $mieterBeteiligte = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'vmhbeteiligtemieter') ->find(); foreach ($mieterBeteiligte as $mieter) { // Link as Gekuendigte (Mieter) $kuendigungRepo ->getRelation($kuendigung, 'gekuendigte') ->relate($mieter); } // 9. Copy all documents from Mietverhältnis and Beteiligte // 9a. Dokumente vom Mietverhältnis $dokumenteMV = $this->entityManager ->getRepository('CVmhMietverhltnis') ->getRelation($mietverhaeltnis, 'dokumentesvmhMietverhltnisse') ->find(); foreach ($dokumenteMV as $dokument) { $kuendigungRepo ->getRelation($kuendigung, 'dokumenteskuendigung') ->relate($dokument); } // 9b. Dokumente von allen Beteiligten (Vermieter + Mieter) $alleBeteiligte = array_merge( iterator_to_array($vermieterBeteiligte), iterator_to_array($mieterBeteiligte) ); foreach ($alleBeteiligte as $beteiligter) { $dokumenteBet = $this->entityManager ->getRepository('CBeteiligte') ->getRelation($beteiligter, 'dokumentesBeteiligte') ->find(); foreach ($dokumenteBet as $dokument) { $kuendigungRepo ->getRelation($kuendigung, 'dokumenteskuendigung') ->relate($dokument); } } // 10. 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); } // 11. 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; } } }