diff --git a/custom/Espo/Custom/Hooks/CAkten/UpdateLastSyncFromDocuments.php b/custom/Espo/Custom/Hooks/CAkten/UpdateLastSyncFromDocuments.php index e6410835..a3d1c64d 100644 --- a/custom/Espo/Custom/Hooks/CAkten/UpdateLastSyncFromDocuments.php +++ b/custom/Espo/Custom/Hooks/CAkten/UpdateLastSyncFromDocuments.php @@ -6,8 +6,8 @@ use Espo\ORM\Repository\Option\SaveOptions; use Espo\Core\Hook\Hook\BeforeSave; /** - * Hook: Aktualisiert lastSync basierend auf dem neuesten lastSyncTimestamp - * der verknüpften Dokumente + * Hook: Aktualisiert lastSync + syncStatus (Advoware) und aiLastSync + aiSyncStatus (AI) + * basierend auf dem neuesten Timestamp und schlechtesten Status der verknüpften Dokumente. */ class UpdateLastSyncFromDocuments implements BeforeSave { @@ -17,12 +17,10 @@ class UpdateLastSyncFromDocuments implements BeforeSave public function beforeSave(Entity $entity, SaveOptions $options): void { - // Überspringe, wenn skipHooks gesetzt ist (verhindert Loops) if ($options->get('skipHooks')) { return; } - // Nur wenn Entity bereits existiert (nicht bei Create) if ($entity->isNew()) { return; } @@ -31,62 +29,96 @@ class UpdateLastSyncFromDocuments implements BeforeSave $pdo = $this->entityManager->getPDO(); $aktenId = $entity->getId(); - // Hole das neueste lastSyncTimestamp aller verknüpften Dokumente $stmt = $pdo->prepare( - "SELECT MAX(last_sync_timestamp) AS maxLastSync + "SELECT + MAX(last_sync_timestamp) AS maxAdvLastSync, + MAX(ai_last_sync) AS maxAiLastSync, + sync_status, + ai_sync_status FROM c_dokumente - WHERE c_akten_id = :aktenId AND deleted = 0 AND last_sync_timestamp IS NOT NULL" + WHERE c_akten_id = :aktenId AND deleted = 0" ); $stmt->execute([':aktenId' => $aktenId]); - $result = $stmt->fetch(\PDO::FETCH_ASSOC); + $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC); - if ($result && $result['maxLastSync']) { - $entity->set('lastSync', $result['maxLastSync']); + if (empty($rows)) { + $entity->set('syncStatus', 'unclean'); + $entity->set('aiSyncStatus', 'unclean'); + return; } - // Berechne syncStatus basierend auf verknüpften Dokumenten - $this->updateSyncStatus($entity, $pdo, $aktenId); + // 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; + } + } + + // 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) { + $entity->set('syncStatus', 'failed'); + } elseif ($advHasUnsynced) { + $entity->set('syncStatus', 'unclean'); + } else { + $entity->set('syncStatus', 'synced'); + } + + // AI Status setzen (worst-case) + if ($aiHasFailed) { + $entity->set('aiSyncStatus', 'failed'); + } elseif ($aiHasUnsynced) { + $entity->set('aiSyncStatus', 'unclean'); + } else { + $entity->set('aiSyncStatus', 'synced'); + } } catch (\Exception $e) { $GLOBALS['log']->error('CAkten UpdateLastSyncFromDocuments Hook Error: ' . $e->getMessage()); } } - - private function updateSyncStatus(Entity $entity, \PDO $pdo, string $aktenId): void - { - $stmt = $pdo->prepare( - "SELECT sync_status FROM c_dokumente - WHERE c_akten_id = :aktenId AND deleted = 0" - ); - $stmt->execute([':aktenId' => $aktenId]); - $rows = $stmt->fetchAll(\PDO::FETCH_ASSOC); - - if (empty($rows)) { - $entity->set('syncStatus', 'unclean'); - return; - } - - $hasUnsynced = false; - $hasFailed = false; - - foreach ($rows as $row) { - $status = $row['sync_status'] ?? null; - - if ($status === 'failed') { - $hasFailed = true; - } - - if ($status === 'new' || $status === 'unclean' || $status === null || $status === '') { - $hasUnsynced = true; - } - } - - if ($hasFailed) { - $entity->set('syncStatus', 'failed'); - } elseif ($hasUnsynced) { - $entity->set('syncStatus', 'unclean'); - } else { - $entity->set('syncStatus', 'synced'); - } - } } diff --git a/data/state.php b/data/state.php index 2003120b..fecbe14e 100644 --- a/data/state.php +++ b/data/state.php @@ -1,7 +1,7 @@ 1774530224, - 'microtimeState' => 1774530224.017606, + 'cacheTimestamp' => 1774530556, + 'microtimeState' => 1774530556.202809, 'currencyRates' => [ 'EUR' => 1.0 ],