Refactor UpdateLastSyncFromDocuments hook to use PDO for database queries; add AI Sync fields to CDokumente layout; update microtime values in config and state files; create check_role_permissions script for role validation
This commit is contained in:
@@ -14,97 +14,78 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
public function __construct(
|
||||
private \Espo\ORM\EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$pdo = $this->entityManager->getPDO();
|
||||
$aktenId = $entity->getId();
|
||||
|
||||
// Hole das neueste lastSyncTimestamp aller verknüpften Dokumente
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select([
|
||||
'MAX:lastSyncTimestamp' => 'maxLastSync',
|
||||
'COUNT:id' => 'dokumentCount'
|
||||
])
|
||||
->from('CDokumente')
|
||||
->where([
|
||||
'cAktenId' => $entity->getId(),
|
||||
'deleted' => false,
|
||||
'lastSyncTimestamp!=' => null
|
||||
])
|
||||
->build();
|
||||
|
||||
$pdoStatement = $this->entityManager->getQueryExecutor()->execute($query);
|
||||
$result = $pdoStatement->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT MAX(last_sync_timestamp) AS maxLastSync
|
||||
FROM c_dokumente
|
||||
WHERE c_akten_id = :aktenId AND deleted = 0 AND last_sync_timestamp IS NOT NULL"
|
||||
);
|
||||
$stmt->execute([':aktenId' => $aktenId]);
|
||||
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if ($result && $result['maxLastSync']) {
|
||||
// Setze lastSync auf den neuesten Sync-Timestamp
|
||||
$entity->set('lastSync', $result['maxLastSync']);
|
||||
}
|
||||
|
||||
// Berechne auch syncStatus basierend auf verknüpften Dokumenten
|
||||
$this->updateSyncStatus($entity);
|
||||
|
||||
|
||||
// Berechne syncStatus basierend auf verknüpften Dokumenten
|
||||
$this->updateSyncStatus($entity, $pdo, $aktenId);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Fehler loggen, aber nicht werfen (um Save nicht zu blockieren)
|
||||
$GLOBALS['log']->error('CAkten UpdateLastSyncFromDocuments Hook Error: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualisiert syncStatus basierend auf den Status der verknüpften Dokumente
|
||||
*/
|
||||
private function updateSyncStatus(Entity $entity): void
|
||||
|
||||
private function updateSyncStatus(Entity $entity, \PDO $pdo, string $aktenId): void
|
||||
{
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select(['syncStatus'])
|
||||
->from('CDokumente')
|
||||
->where([
|
||||
'cAktenId' => $entity->getId(),
|
||||
'deleted' => false
|
||||
])
|
||||
->build();
|
||||
|
||||
$pdoStatement = $this->entityManager->getQueryExecutor()->execute($query);
|
||||
$rows = $pdoStatement->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
// Wenn keine Dokumente verknüpft, setze auf "unclean"
|
||||
$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;
|
||||
}
|
||||
|
||||
// Prüfe, ob irgendein Dokument "new" oder "unclean" ist
|
||||
|
||||
$hasUnsynced = false;
|
||||
$hasFailed = false;
|
||||
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$status = $row['syncStatus'] ?? null;
|
||||
|
||||
$status = $row['sync_status'] ?? null;
|
||||
|
||||
if ($status === 'failed') {
|
||||
$hasFailed = true;
|
||||
}
|
||||
|
||||
|
||||
if ($status === 'new' || $status === 'unclean' || $status === null || $status === '') {
|
||||
$hasUnsynced = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Setze globalen Status
|
||||
|
||||
if ($hasFailed) {
|
||||
$entity->set('syncStatus', 'failed');
|
||||
} elseif ($hasUnsynced) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
} else {
|
||||
// Alle Dokumente sind "synced"
|
||||
$entity->set('syncStatus', 'synced');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,5 +99,38 @@
|
||||
"noteText": null,
|
||||
"noteStyle": "info",
|
||||
"customLabel": "Advoware Sync"
|
||||
},
|
||||
{
|
||||
"rows": [
|
||||
[
|
||||
{
|
||||
"name": "aiSyncStatus"
|
||||
},
|
||||
{
|
||||
"name": "aiLastSync"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "aiCollectionId"
|
||||
},
|
||||
{
|
||||
"name": "aiFileId"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "aiSyncHash"
|
||||
},
|
||||
{"isFull": false}
|
||||
]
|
||||
],
|
||||
"dynamicLogicVisible": null,
|
||||
"style": "default",
|
||||
"tabBreak": false,
|
||||
"hidden": false,
|
||||
"noteText": null,
|
||||
"noteStyle": "info",
|
||||
"customLabel": "AI Sync"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user