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

382 lines
14 KiB
PHP

<?php
namespace Espo\Custom\Services;
use Espo\Core\Exceptions\Forbidden;
use Espo\Core\Exceptions\NotFound;
use Espo\Tools\Stream\Service as StreamService;
use Espo\Entities\Note;
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
{
// Delegate to CVmhRumungsklage service
$raeumungsklagenService = $this->serviceFactory->create('CVmhRumungsklage');
return $raeumungsklagenService->createFromSource('CVmhMietverhltnis', $mietverhaeltnisId);
}
/**
* 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. Log to stream
$this->logToStream($mietverhaeltnis, 'CVmhMietverhltnis', $mietinkasso->getId(), 'CMietinkasso', 'Mietinkasso erstellen');
// 13. 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. Log to stream
$this->logToStream($mietverhaeltnis, 'CVmhMietverhltnis', $kuendigung->getId(), 'CKuendigung', 'Kündigung erstellen');
// 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;
}
}
/**
* Log action to source entity stream
*
* @param object $sourceEntity Source entity (Mietverhältnis)
* @param string $sourceEntityType Entity type
* @param string $createdEntityId Created entity ID
* @param string $createdEntityType Created entity type
* @param string $actionLabel Label for the action
*/
private function logToStream($sourceEntity, string $sourceEntityType, string $createdEntityId, string $createdEntityType, string $actionLabel): void
{
// 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' => $createdEntityType,
'relatedId' => $createdEntityId,
'data' => [
'actionLabel' => $actionLabel
]
]);
$this->entityManager->saveEntity($note);
}
}