Refactor AdvowareAkte ↔ CDokumente relationship from junction table to direct n:1 relationship

- Removed CAdvowareAktenCDokumente junction table and associated service.
- Updated CDokumente entity to include foreign key cAdvowareAktenId and related fields.
- Changed relationship in CDokumente from hasMany to belongsTo.
- Updated CAdvowareAkten to reflect new direct relationship.
- Implemented CDokumente service with duplicateDocument method for document duplication.
- Refactored hooks to support new relationship and document propagation.
- Removed obsolete API routes related to the junction table.
- Added i18n translations for new fields and updated tooltips.
- Document flow and auto-linking logic enhanced for better integration with Advoware.
- Validation checks passed, and no data migration needed.
This commit is contained in:
2026-03-23 20:36:10 +01:00
parent 0b829e9dfe
commit 22665948e4
22 changed files with 689 additions and 773 deletions

View File

@@ -6,8 +6,8 @@ use Espo\ORM\Repository\Option\SaveOptions;
use Espo\Core\Hook\Hook\AfterSave;
/**
* Hook: Bei Änderung eines Dokuments werden alle verknüpften
* AdvowareAkten und AIKnowledge Junction-Table-Einträge auf "unclean" gesetzt
* Hook: Bei Änderung eines Dokuments wird syncStatus auf "unclean" gesetzt
* und alle verknüpften AIKnowledge Junction-Table-Einträge werden aktualisiert
*/
class UpdateJunctionSyncStatus implements AfterSave
{
@@ -28,10 +28,21 @@ class UpdateJunctionSyncStatus implements AfterSave
}
try {
// Update AdvowareAkten Junction-Tables
$this->updateAdvowareAktenJunctions($entity);
// Set syncStatus = 'unclean' directly on CDokumente entity
// (only if it has an AdvowareAkte linked)
if ($entity->get('cAdvowareAktenId')) {
$entity->set('syncStatus', 'unclean');
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
// Also update the parent AdvowareAkte
$akte = $this->entityManager->getEntity('CAdvowareAkten', $entity->get('cAdvowareAktenId'));
if ($akte) {
$akte->set('syncStatus', 'unclean');
$this->entityManager->saveEntity($akte, ['silent' => true, 'skipHooks' => true]);
}
}
// Update AIKnowledge Junction-Tables
// Update AIKnowledge Junction-Tables (unchanged)
$this->updateAIKnowledgeJunctions($entity);
} catch (\Exception $e) {
@@ -65,50 +76,6 @@ class UpdateJunctionSyncStatus implements AfterSave
return false;
}
/**
* Update AdvowareAkten Junction-Tables
*/
private function updateAdvowareAktenJunctions(Entity $entity): void
{
$updateQuery = $this->entityManager->getQueryBuilder()
->update()
->in('CAdvowareAktenDokumente')
->set(['syncstatus' => 'unclean'])
->where([
'cDokumenteId' => $entity->getId(),
'deleted' => false
])
->build();
$this->entityManager->getQueryExecutor()->execute($updateQuery);
// Hole alle betroffenen AdvowareAkten IDs
$selectQuery = $this->entityManager->getQueryBuilder()
->select(['cAdvowareAktenId'])
->from('CAdvowareAktenDokumente')
->where([
'cDokumenteId' => $entity->getId(),
'deleted' => false
])
->build();
$pdoStatement = $this->entityManager->getQueryExecutor()->execute($selectQuery);
$rows = $pdoStatement->fetchAll(\PDO::FETCH_ASSOC);
// Trigger Update auf jeder AdvowareAkte (um CheckGlobalSyncStatus Hook auszulösen)
foreach ($rows as $row) {
$aktenId = $row['cAdvowareAktenId'] ?? null;
if ($aktenId) {
$akte = $this->entityManager->getEntity('CAdvowareAkten', $aktenId);
if ($akte) {
// Force Update ohne Hook-Loop
$akte->set('syncStatus', 'unclean');
$this->entityManager->saveEntity($akte);
}
}
}
}
/**
* Update AIKnowledge Junction-Tables
*/
@@ -147,7 +114,7 @@ class UpdateJunctionSyncStatus implements AfterSave
if ($knowledge) {
// Force Update ohne Hook-Loop
$knowledge->set('syncStatus', 'unclean');
$this->entityManager->saveEntity($knowledge);
$this->entityManager->saveEntity($knowledge, ['silent' => true, 'skipHooks' => true]);
}
}
}