Refactor document propagation and sync status hooks; deprecate CAkten hooks and implement new logic in CDokumente; update microtime values in config and state files
This commit is contained in:
@@ -5,79 +5,15 @@ use Espo\ORM\Entity;
|
||||
use Espo\Core\Hook\Hook\AfterSave;
|
||||
|
||||
/**
|
||||
* Hook: Propagiert Dokumenten-Änderungen von Akten nach oben zu Räumungsklage/Mietinkasso
|
||||
* DEPRECATED / DEAD CODE — dieser Hook war in der falschen Namespace.
|
||||
*
|
||||
* Wenn ein Dokument einer Akte zugewiesen wird (via cAktenId):
|
||||
* → verknüpfe mit verbundener Räumungsklage/Mietinkasso
|
||||
* CAkten-Hooks feuern bei CAkten-Saves, nicht bei CDokumente-Saves.
|
||||
* Die Logik wurde in Hooks/CDokumente/PropagateDocumentsUp.php verschoben.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
// intentionally empty — see Hooks/CDokumente/PropagateDocumentsUp.php
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,89 +29,61 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
$pdo = $this->entityManager->getPDO();
|
||||
$aktenId = $entity->getId();
|
||||
|
||||
// Einzelne Zeile mit aggregierten Worst-Case-Werten über alle Dokumente.
|
||||
// CASE-Ausdrücke in MAX() vermeiden das GROUP-BY-Problem bei gemischten
|
||||
// Aggregat- und Nicht-Aggregat-Spalten.
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT
|
||||
MAX(last_sync_timestamp) AS maxAdvLastSync,
|
||||
MAX(ai_last_sync) AS maxAiLastSync,
|
||||
sync_status,
|
||||
ai_sync_status
|
||||
MAX(ai_last_sync) AS maxAiLastSync,
|
||||
MAX(CASE
|
||||
WHEN sync_status = 'failed' THEN 2
|
||||
WHEN sync_status IN ('new','unclean')
|
||||
OR sync_status IS NULL OR sync_status = '' THEN 1
|
||||
ELSE 0
|
||||
END) AS advWorstLevel,
|
||||
MAX(CASE
|
||||
WHEN ai_sync_status = 'failed' THEN 2
|
||||
WHEN ai_sync_status IN ('new','unclean')
|
||||
OR ai_sync_status IS NULL OR ai_sync_status = '' THEN 1
|
||||
ELSE 0
|
||||
END) AS aiWorstLevel,
|
||||
COUNT(*) AS docCount
|
||||
FROM c_dokumente
|
||||
WHERE c_akten_id = :aktenId AND deleted = 0"
|
||||
);
|
||||
$stmt->execute([':aktenId' => $aktenId]);
|
||||
$rows = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if (empty($rows)) {
|
||||
if (!$row || (int)$row['docCount'] === 0) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
return;
|
||||
}
|
||||
|
||||
// Timestamps
|
||||
$maxAdvLastSync = null;
|
||||
$maxAiLastSync = null;
|
||||
|
||||
// Status-Tracker
|
||||
$advHasFailed = false;
|
||||
$advHasUnsynced = false;
|
||||
$aiHasFailed = false;
|
||||
$aiHasUnsynced = false;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
// Advoware: neuester Timestamp
|
||||
if (!empty($row['maxAdvLastSync'])) {
|
||||
if ($maxAdvLastSync === null || $row['maxAdvLastSync'] > $maxAdvLastSync) {
|
||||
$maxAdvLastSync = $row['maxAdvLastSync'];
|
||||
}
|
||||
}
|
||||
|
||||
// AI: neuester Timestamp
|
||||
if (!empty($row['maxAiLastSync'])) {
|
||||
if ($maxAiLastSync === null || $row['maxAiLastSync'] > $maxAiLastSync) {
|
||||
$maxAiLastSync = $row['maxAiLastSync'];
|
||||
}
|
||||
}
|
||||
|
||||
// Advoware: schlechtester Status
|
||||
$advStatus = $row['sync_status'] ?? null;
|
||||
if ($advStatus === 'failed') {
|
||||
$advHasFailed = true;
|
||||
} elseif ($advStatus === 'new' || $advStatus === 'unclean' || $advStatus === null || $advStatus === '') {
|
||||
$advHasUnsynced = true;
|
||||
}
|
||||
|
||||
// AI: schlechtester Status
|
||||
$aiStatus = $row['ai_sync_status'] ?? null;
|
||||
if ($aiStatus === 'failed') {
|
||||
$aiHasFailed = true;
|
||||
} elseif ($aiStatus === 'new' || $aiStatus === 'unclean' || $aiStatus === null || $aiStatus === '') {
|
||||
$aiHasUnsynced = true;
|
||||
}
|
||||
// Timestamps setzen
|
||||
if (!empty($row['maxAdvLastSync'])) {
|
||||
$entity->set('lastSync', $row['maxAdvLastSync']);
|
||||
}
|
||||
if (!empty($row['maxAiLastSync'])) {
|
||||
$entity->set('aiLastSync', $row['maxAiLastSync']);
|
||||
}
|
||||
|
||||
// Advoware Timestamp setzen
|
||||
if ($maxAdvLastSync !== null) {
|
||||
$entity->set('lastSync', $maxAdvLastSync);
|
||||
}
|
||||
|
||||
// AI Timestamp setzen
|
||||
if ($maxAiLastSync !== null) {
|
||||
$entity->set('aiLastSync', $maxAiLastSync);
|
||||
}
|
||||
|
||||
// Advoware Status setzen (worst-case)
|
||||
if ($advHasFailed) {
|
||||
// Advoware Status setzen (worst-case über alle Dokumente)
|
||||
$advLevel = (int)($row['advWorstLevel'] ?? 0);
|
||||
if ($advLevel >= 2) {
|
||||
$entity->set('syncStatus', 'failed');
|
||||
} elseif ($advHasUnsynced) {
|
||||
} elseif ($advLevel === 1) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
} else {
|
||||
$entity->set('syncStatus', 'synced');
|
||||
}
|
||||
|
||||
// AI Status setzen (worst-case)
|
||||
if ($aiHasFailed) {
|
||||
// AI Status setzen (worst-case über alle Dokumente)
|
||||
$aiLevel = (int)($row['aiWorstLevel'] ?? 0);
|
||||
if ($aiLevel >= 2) {
|
||||
$entity->set('aiSyncStatus', 'failed');
|
||||
} elseif ($aiHasUnsynced) {
|
||||
} elseif ($aiLevel === 1) {
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
} else {
|
||||
$entity->set('aiSyncStatus', 'synced');
|
||||
|
||||
Reference in New Issue
Block a user