Add localization files and layout configurations for CAkten and related entities

- Created localization JSON files for multiple languages (e.g., Danish, German, Greek, English, Spanish, etc.) for CAkten and CAktenCDokumente.
- Added layout configurations for CAkten, including detail views, side panels, and bottom panels.
- Implemented metadata definitions for CAkten, including field definitions, relationship panels, and scopes.
- Introduced new JSON files for managing document relationships and listing configurations.
This commit is contained in:
2026-03-26 01:56:22 +01:00
parent 661943987f
commit 6ac852b42a
85 changed files with 1387 additions and 276 deletions

View File

@@ -59,8 +59,8 @@ class PropagateDocumentsUp implements AfterRelate, AfterUnrelate
->getRelation($raumungsklage, 'advowareAkten')
->findOne();
if ($advowareAkte && !$foreignEntity->get('cAdvowareAktenId')) {
$foreignEntity->set('cAdvowareAktenId', $advowareAkte->getId());
if ($advowareAkte && !$foreignEntity->get('cAktenId')) {
$foreignEntity->set('cAktenId', $advowareAkte->getId());
$foreignEntity->set('syncStatus', 'new');
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}
@@ -81,8 +81,8 @@ class PropagateDocumentsUp implements AfterRelate, AfterUnrelate
->getRelation($mietinkasso, 'advowareAkten')
->findOne();
if ($advowareAkte && !$foreignEntity->get('cAdvowareAktenId')) {
$foreignEntity->set('cAdvowareAktenId', $advowareAkte->getId());
if ($advowareAkte && !$foreignEntity->get('cAktenId')) {
$foreignEntity->set('cAktenId', $advowareAkte->getId());
$foreignEntity->set('syncStatus', 'new');
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}
@@ -134,7 +134,7 @@ class PropagateDocumentsUp implements AfterRelate, AfterUnrelate
$this->unrelateDocument($mietinkasso, 'dokumentesmietinkasso', $foreignEntity);
}
// Note: We don't remove cAdvowareAktenId on unrelate from AIKnowledge
// Note: We don't remove cAktenId on unrelate from AIKnowledge
// because the document might still be linked to Räumungsklage/Mietinkasso
} catch (\Exception $e) {

View File

@@ -1,118 +0,0 @@
<?php
namespace Espo\Custom\Hooks\CAdvowareAkten;
use Espo\ORM\Entity;
use Espo\Core\Hook\Hook\AfterSave;
/**
* Hook: Propagiert Dokumenten-Änderungen von AdvowareAkten nach oben zu Räumungsklage/Mietinkasso
* und auch zu AICollection
*
* Wenn ein Dokument einer AdvowareAkte zugewiesen wird (via cAdvowareAktenId):
* → verknüpfe mit verbundener Räumungsklage/Mietinkasso
* → verknüpfe mit AICollection
*
* Improved logic: Works with direct belongsTo relationship (cAdvowareAktenId)
*/
class PropagateDocumentsUp implements AfterSave
{
private static array $processing = [];
public function __construct(
private \Espo\ORM\EntityManager $entityManager
) {}
public function afterSave(Entity $entity, \Espo\ORM\Repository\Option\SaveOptions $options): void
{
// Only process when cAdvowareAktenId changed
if (!$entity->isAttributeChanged('cAdvowareAktenId')) {
return;
}
$akteId = $entity->get('cAdvowareAktenId');
if (!$akteId) {
return; // Document was unlinked from Akte
}
// Vermeide Loops
$key = $akteId . '-' . $entity->getId() . '-propagate';
if (isset(self::$processing[$key])) {
return;
}
self::$processing[$key] = true;
try {
// Load AdvowareAkte
$akte = $this->entityManager->getEntity('CAdvowareAkten', $akteId);
if (!$akte) {
return;
}
// Prüfe ob Räumungsklage verknüpft ist
$raumungsklage = $this->entityManager
->getRDBRepository('CAdvowareAkten')
->getRelation($akte, 'vmhRumungsklage')
->findOne();
if ($raumungsklage) {
$this->relateDocument($raumungsklage, 'dokumentesvmhraumungsklage', $entity);
}
// Prüfe ob Mietinkasso verknüpft ist
$mietinkasso = $this->entityManager
->getRDBRepository('CAdvowareAkten')
->getRelation($akte, 'mietinkasso')
->findOne();
if ($mietinkasso) {
$this->relateDocument($mietinkasso, 'dokumentesmietinkasso', $entity);
}
// Also propagate to AICollection if Räumungsklage or Mietinkasso has one
if ($raumungsklage) {
$aiKnowledge = $this->entityManager
->getRDBRepository('CVmhRumungsklage')
->getRelation($raumungsklage, 'aIKnowledge')
->findOne();
if ($aiKnowledge) {
$this->relateDocument($aiKnowledge, 'dokumentes', $entity);
}
}
if ($mietinkasso) {
$aiKnowledge = $this->entityManager
->getRDBRepository('CMietinkasso')
->getRelation($mietinkasso, 'aIKnowledge')
->findOne();
if ($aiKnowledge) {
$this->relateDocument($aiKnowledge, 'dokumentes', $entity);
}
}
} catch (\Exception $e) {
$GLOBALS['log']->error('CAdvowareAkten PropagateDocumentsUp Error: ' . $e->getMessage());
} finally {
unset(self::$processing[$key]);
}
}
/**
* Hilfsfunktion: Verknüpfe Dokument (nur wenn nicht bereits verknüpft)
*/
private function relateDocument(Entity $parentEntity, string $relationName, Entity $document): void
{
$repository = $this->entityManager->getRDBRepository($parentEntity->getEntityType());
$relation = $repository->getRelation($parentEntity, $relationName);
// Prüfe ob bereits verknüpft
$isRelated = $relation
->where(['id' => $document->getId()])
->findOne();
if (!$isRelated) {
$relation->relate($document);
}
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Espo\Custom\Hooks\CAkten;
use Espo\ORM\Entity;
use Espo\Core\Hook\Hook\AfterSave;
/**
* Hook: Propagiert Dokumenten-Änderungen von Akten nach oben zu Räumungsklage/Mietinkasso
*
* Wenn ein Dokument einer Akte zugewiesen wird (via cAktenId):
* → verknüpfe mit verbundener Räumungsklage/Mietinkasso
*/
class PropagateDocumentsUp implements AfterSave
{
private static array $processing = [];
public function __construct(
private \Espo\ORM\EntityManager $entityManager
) {}
public function afterSave(Entity $entity, \Espo\ORM\Repository\Option\SaveOptions $options): void
{
// Only process when cAktenId changed
if (!$entity->isAttributeChanged('cAktenId')) {
return;
}
$akteId = $entity->get('cAktenId');
if (!$akteId) {
return;
}
$key = $akteId . '-' . $entity->getId() . '-propagate';
if (isset(self::$processing[$key])) {
return;
}
self::$processing[$key] = true;
try {
$akte = $this->entityManager->getEntity('CAkten', $akteId);
if (!$akte) {
return;
}
$raumungsklage = $this->entityManager
->getRDBRepository('CAkten')
->getRelation($akte, 'vmhRumungsklage')
->findOne();
if ($raumungsklage) {
$this->relateDocument($raumungsklage, 'dokumentesvmhraumungsklage', $entity);
}
$mietinkasso = $this->entityManager
->getRDBRepository('CAkten')
->getRelation($akte, 'mietinkasso')
->findOne();
if ($mietinkasso) {
$this->relateDocument($mietinkasso, 'dokumentesmietinkasso', $entity);
}
} catch (\Exception $e) {
$GLOBALS['log']->error('CAkten PropagateDocumentsUp Error: ' . $e->getMessage());
} finally {
unset(self::$processing[$key]);
}
}
private function relateDocument(Entity $parentEntity, string $relationName, Entity $document): void
{
$repository = $this->entityManager->getRDBRepository($parentEntity->getEntityType());
$relation = $repository->getRelation($parentEntity, $relationName);
$isRelated = $relation
->where(['id' => $document->getId()])
->findOne();
if (!$isRelated) {
$relation->relate($document);
}
}
}

View File

@@ -1,5 +1,5 @@
<?php
namespace Espo\Custom\Hooks\CAdvowareAkten;
namespace Espo\Custom\Hooks\CAkten;
use Espo\ORM\Entity;
use Espo\ORM\Repository\Option\SaveOptions;
@@ -36,7 +36,7 @@ class UpdateLastSyncFromDocuments implements BeforeSave
])
->from('CDokumente')
->where([
'cAdvowareAktenId' => $entity->getId(),
'cAktenId' => $entity->getId(),
'deleted' => false,
'lastSyncTimestamp!=' => null
])
@@ -55,7 +55,7 @@ class UpdateLastSyncFromDocuments implements BeforeSave
} catch (\Exception $e) {
// Fehler loggen, aber nicht werfen (um Save nicht zu blockieren)
$GLOBALS['log']->error('CAdvowareAkten UpdateLastSyncFromDocuments Hook Error: ' . $e->getMessage());
$GLOBALS['log']->error('CAkten UpdateLastSyncFromDocuments Hook Error: ' . $e->getMessage());
}
}
@@ -68,7 +68,7 @@ class UpdateLastSyncFromDocuments implements BeforeSave
->select(['syncStatus'])
->from('CDokumente')
->where([
'cAdvowareAktenId' => $entity->getId(),
'cAktenId' => $entity->getId(),
'deleted' => false
])
->build();

View File

@@ -30,12 +30,12 @@ class UpdateJunctionSyncStatus implements AfterSave
try {
// Set syncStatus = 'unclean' directly on CDokumente entity
// (only if it has an AdvowareAkte linked)
if ($entity->get('cAdvowareAktenId')) {
if ($entity->get('cAktenId')) {
$entity->set('syncStatus', 'unclean');
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
// Trigger parent AdvowareAkte update (will update syncStatus and lastSync via its own hook)
$akte = $this->entityManager->getEntityById('CAdvowareAkten', $entity->get('cAdvowareAktenId'));
$akte = $this->entityManager->getEntityById('CAkten', $entity->get('cAktenId'));
if ($akte) {
// Just touch the entity to trigger beforeSave hook
$this->entityManager->saveEntity($akte, ['silent' => true]);

View File

@@ -60,7 +60,7 @@ class CreateAdvowareAkte implements AfterSave
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
// Synchronisiere Aktennummer
$akte = $this->entityManager->getEntity('CAdvowareAkten', $rkAkteId);
$akte = $this->entityManager->getEntity('CAkten', $rkAkteId);
if ($akte) {
$this->syncAktennummer($entity, $akte);
}
@@ -103,7 +103,7 @@ class CreateAdvowareAkte implements AfterSave
$akteData['teamsIds'] = $teamsIds;
}
$akte = $this->entityManager->createEntity('CAdvowareAkten', $akteData);
$akte = $this->entityManager->createEntity('CAkten', $akteData);
if ($akte) {
// Verknüpfe mit Kündigung

View File

@@ -47,7 +47,7 @@ class SyncAdvowareAkte implements AfterRelate
$advowareAkteId = $foreignEntity->get('advowareAktenId');
if ($advowareAkteId) {
$advowareAkte = $this->entityManager->getEntity('CAdvowareAkten', $advowareAkteId);
$advowareAkte = $this->entityManager->getEntity('CAkten', $advowareAkteId);
if ($advowareAkte) {
$GLOBALS['log']->info("CKuendigung SyncAdvowareAkte: Found AdvowareAkte {$advowareAkte->getId()} on Räumungsklage {$foreignEntity->getId()}");

View File

@@ -47,7 +47,7 @@ class PropagateDocuments implements AfterRelate, AfterUnrelate
// Set direct belongsTo relationship on document
if ($advowareAkten) {
$foreignEntity->set('cAdvowareAktenId', $advowareAkten->getId());
$foreignEntity->set('cAktenId', $advowareAkten->getId());
$foreignEntity->set('syncStatus', 'new'); // Mark as new for Advoware sync
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}
@@ -96,8 +96,8 @@ class PropagateDocuments implements AfterRelate, AfterUnrelate
->findOne();
// Remove direct belongsTo relationship from document
if ($advowareAkten && $foreignEntity->get('cAdvowareAktenId') === $advowareAkten->getId()) {
$foreignEntity->set('cAdvowareAktenId', null);
if ($advowareAkten && $foreignEntity->get('cAktenId') === $advowareAkten->getId()) {
$foreignEntity->set('cAktenId', null);
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}

View File

@@ -47,7 +47,7 @@ class PropagateDocuments implements AfterRelate, AfterUnrelate
// Set direct belongsTo relationship on document
if ($advowareAkten) {
$foreignEntity->set('cAdvowareAktenId', $advowareAkten->getId());
$foreignEntity->set('cAktenId', $advowareAkten->getId());
$foreignEntity->set('syncStatus', 'new'); // Mark as new for Advoware sync
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}
@@ -96,8 +96,8 @@ class PropagateDocuments implements AfterRelate, AfterUnrelate
->findOne();
// Remove direct belongsTo relationship from document
if ($advowareAkten && $foreignEntity->get('cAdvowareAktenId') === $advowareAkten->getId()) {
$foreignEntity->set('cAdvowareAktenId', null);
if ($advowareAkten && $foreignEntity->get('cAktenId') === $advowareAkten->getId()) {
$foreignEntity->set('cAktenId', null);
$this->entityManager->saveEntity($foreignEntity, ['silent' => true, 'skipHooks' => true]);
}