Files
espocrm/custom/Espo/Custom/Services/CVmhMietverhltnis.php

610 lines
24 KiB
PHP

<?php
namespace Espo\Custom\Services;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\NotFound;
class CVmhMietverhltnis extends \Espo\Services\Record
{
/**
* Initiate eviction lawsuit (Räumungsklage) from Mietverhältnis
*
* @param string $mietverhaeltnisId
* @return array
* @throws NotFound
* @throws Forbidden
*/
public function initiateEviction(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('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();
$data->name = 'Räumungsklage - ' . $mietverhaeltnis->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;
}
}
}