Add AI parsing and graph parsing status; update related hooks and localization; modify microtime values in config and state files
This commit is contained in:
@@ -29,9 +29,7 @@ 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.
|
||||
// Single aggregation row — CASE inside MAX() avoids the mixed-aggregate bug.
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT
|
||||
MAX(last_sync_timestamp) AS maxAdvLastSync,
|
||||
@@ -48,6 +46,12 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
OR ai_sync_status IS NULL OR ai_sync_status = '' THEN 1
|
||||
ELSE 0
|
||||
END) AS aiWorstLevel,
|
||||
-- ai_sync_status = unclean triggers graphParsingStatus
|
||||
SUM(CASE WHEN ai_sync_status = 'unclean' THEN 1 ELSE 0 END) AS aiUncleanCount,
|
||||
-- aiParsingStatus buckets
|
||||
SUM(CASE WHEN ai_parsing_status = 'parsing' THEN 1 ELSE 0 END) AS parseParsingCount,
|
||||
SUM(CASE WHEN ai_parsing_status = 'complete' THEN 1 ELSE 0 END) AS parseCompleteCount,
|
||||
SUM(CASE WHEN ai_parsing_status = 'failed' THEN 1 ELSE 0 END) AS parseFailedCount,
|
||||
COUNT(*) AS docCount
|
||||
FROM c_dokumente
|
||||
WHERE c_akten_id = :aktenId AND deleted = 0"
|
||||
@@ -58,10 +62,13 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
if (!$row || (int)$row['docCount'] === 0) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
return;
|
||||
}
|
||||
|
||||
// Timestamps setzen
|
||||
$docCount = (int)$row['docCount'];
|
||||
|
||||
// ── Timestamps ─────────────────────────────────────────────────
|
||||
if (!empty($row['maxAdvLastSync'])) {
|
||||
$entity->set('lastSync', $row['maxAdvLastSync']);
|
||||
}
|
||||
@@ -69,7 +76,7 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
$entity->set('aiLastSync', $row['maxAiLastSync']);
|
||||
}
|
||||
|
||||
// Advoware Status setzen (worst-case über alle Dokumente)
|
||||
// ── Advoware Sync Status (worst-case) ──────────────────────────
|
||||
$advLevel = (int)($row['advWorstLevel'] ?? 0);
|
||||
if ($advLevel >= 2) {
|
||||
$entity->set('syncStatus', 'failed');
|
||||
@@ -79,7 +86,7 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
$entity->set('syncStatus', 'synced');
|
||||
}
|
||||
|
||||
// AI Status setzen (worst-case über alle Dokumente)
|
||||
// ── AI Sync Status (worst-case) ────────────────────────────────
|
||||
$aiLevel = (int)($row['aiWorstLevel'] ?? 0);
|
||||
if ($aiLevel >= 2) {
|
||||
$entity->set('aiSyncStatus', 'failed');
|
||||
@@ -89,6 +96,31 @@ class UpdateLastSyncFromDocuments implements BeforeSave
|
||||
$entity->set('aiSyncStatus', 'synced');
|
||||
}
|
||||
|
||||
// ── AI Parsing Status (aggregated across all documents) ─────────
|
||||
// Priority: parsing > unknown > complete_with_failures > complete
|
||||
$parseParsing = (int)($row['parseParsingCount'] ?? 0);
|
||||
$parseComplete = (int)($row['parseCompleteCount'] ?? 0);
|
||||
$parseFailed = (int)($row['parseFailedCount'] ?? 0);
|
||||
$parseUnknown = $docCount - $parseParsing - $parseComplete - $parseFailed;
|
||||
|
||||
if ($parseParsing > 0) {
|
||||
$entity->set('aiParsingStatus', 'parsing');
|
||||
} elseif ($parseUnknown > 0) {
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
} elseif ($parseFailed > 0) {
|
||||
// No unknown/parsing left, but some failures
|
||||
$entity->set('aiParsingStatus', 'complete_with_failures');
|
||||
} else {
|
||||
$entity->set('aiParsingStatus', 'complete');
|
||||
}
|
||||
|
||||
// ── Graph Parsing Status (only auto-set to unclean, never reset) ─
|
||||
// If any document's AI sync status is currently unclean → graph is stale.
|
||||
// Any other transition (back to complete, etc.) must be done manually.
|
||||
if ((int)($row['aiUncleanCount'] ?? 0) > 0) {
|
||||
$entity->set('graphParsingStatus', 'unclean');
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('CAkten UpdateLastSyncFromDocuments Hook Error: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ class SyncStatusOnRelate implements AfterRelate, AfterUnrelate
|
||||
$entity->set('cAktenId', $advowareAkten->getId());
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
|
||||
|
||||
$this->triggerAkteUpdate($advowareAkten->getId());
|
||||
@@ -75,6 +76,7 @@ class SyncStatusOnRelate implements AfterRelate, AfterUnrelate
|
||||
// Kein Akte-Link — trotzdem Sync-Status auf unclean setzen
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ class UpdateJunctionSyncStatus implements AfterSave, AfterRemove
|
||||
if ($newAktenId) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
|
||||
$this->triggerAkteUpdate($newAktenId);
|
||||
}
|
||||
@@ -70,6 +71,7 @@ class UpdateJunctionSyncStatus implements AfterSave, AfterRemove
|
||||
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
$entity->set('aiSyncStatus', 'unclean');
|
||||
$entity->set('aiParsingStatus', 'unknown');
|
||||
$this->entityManager->saveEntity($entity, ['silent' => true, 'skipHooks' => true]);
|
||||
$this->triggerAkteUpdate($entity->get('cAktenId'));
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
"globalLastSync": "Globaler letzter Sync",
|
||||
"syncSchalter": "Sync aktiv",
|
||||
"dokumentes": "Dokumente",
|
||||
"rubrum": "Rubrum"
|
||||
"rubrum": "Rubrum",
|
||||
"aiParsingStatus": "AI Parsing-Status",
|
||||
"graphParsingStatus": "Graph Parsing-Status"
|
||||
},
|
||||
"options": {
|
||||
"syncStatus": {
|
||||
@@ -65,6 +67,18 @@
|
||||
"unclean": "Nicht synchronisiert",
|
||||
"pending_sync": "Synchronisierung ausstehend",
|
||||
"failed": "Fehlgeschlagen"
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"unknown": "Unbekannt",
|
||||
"parsing": "In Verarbeitung",
|
||||
"complete": "Abgeschlossen",
|
||||
"complete_with_failures": "Abgeschlossen mit Fehlern"
|
||||
},
|
||||
"graphParsingStatus": {
|
||||
"no_graph": "Kein Graph",
|
||||
"parsing": "In Verarbeitung",
|
||||
"complete": "Abgeschlossen",
|
||||
"unclean": "Veraltet"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"aiSyncHash": "AI Sync-Hash",
|
||||
"aiSyncStatus": "AI Sync-Status",
|
||||
"aiLastSync": "AI Letzter Sync",
|
||||
"aiFileId": "AI File-ID"
|
||||
"aiFileId": "AI File-ID",
|
||||
"aiParsingStatus": "AI Parsing-Status"
|
||||
},
|
||||
"links": {
|
||||
"contactsvmhdokumente": "Freigegebene Nutzer",
|
||||
@@ -77,6 +78,12 @@
|
||||
"synced": "Synchronisiert",
|
||||
"failed": "Fehler",
|
||||
"unsupported": "Nicht unterstützt"
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"unknown": "Unbekannt",
|
||||
"parsing": "In Verarbeitung",
|
||||
"complete": "Abgeschlossen",
|
||||
"failed": "Fehlgeschlagen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,9 @@
|
||||
"globalLastSync": "Global Last Sync",
|
||||
"syncSchalter": "Sync Active",
|
||||
"dokumentes": "Documents",
|
||||
"rubrum": "Rubrum"
|
||||
"rubrum": "Rubrum",
|
||||
"aiParsingStatus": "AI Parsing Status",
|
||||
"graphParsingStatus": "Graph Parsing Status"
|
||||
},
|
||||
"options": {
|
||||
"syncStatus": {
|
||||
@@ -66,6 +68,18 @@
|
||||
"unclean": "Not Synchronized",
|
||||
"pending_sync": "Synchronization Pending",
|
||||
"failed": "Failed"
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"unknown": "Unknown",
|
||||
"parsing": "Parsing",
|
||||
"complete": "Complete",
|
||||
"complete_with_failures": "Complete with Failures"
|
||||
},
|
||||
"graphParsingStatus": {
|
||||
"no_graph": "No Graph",
|
||||
"parsing": "Parsing",
|
||||
"complete": "Complete",
|
||||
"unclean": "Stale"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"aiSyncHash": "AI Sync Hash",
|
||||
"aiSyncStatus": "AI Sync Status",
|
||||
"aiLastSync": "AI Last Sync",
|
||||
"aiFileId": "AI File ID"
|
||||
"aiFileId": "AI File ID",
|
||||
"aiParsingStatus": "AI Parsing Status"
|
||||
},
|
||||
"links": {
|
||||
"contactsvmhdokumente": "Portal Users",
|
||||
@@ -83,6 +84,12 @@
|
||||
"synced": "Synchronized",
|
||||
"failed": "Failed",
|
||||
"unsupported": "Unsupported"
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"unknown": "Unknown",
|
||||
"parsing": "Parsing",
|
||||
"complete": "Complete",
|
||||
"failed": "Failed"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,14 @@
|
||||
"name": "aiProvider"
|
||||
},
|
||||
{}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "aiParsingStatus"
|
||||
},
|
||||
{
|
||||
"name": "graphParsingStatus"
|
||||
}
|
||||
]
|
||||
],
|
||||
"style": "default",
|
||||
|
||||
@@ -122,7 +122,9 @@
|
||||
{
|
||||
"name": "aiSyncHash"
|
||||
},
|
||||
{"isFull": false}
|
||||
{
|
||||
"name": "aiParsingStatus"
|
||||
}
|
||||
]
|
||||
],
|
||||
"dynamicLogicVisible": null,
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
"name": "aiSyncStatus",
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"name": "aiParsingStatus",
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"name": "aiLastSync",
|
||||
"align": "left"
|
||||
|
||||
@@ -216,6 +216,45 @@
|
||||
"maxLength": 500,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"type": "enum",
|
||||
"required": false,
|
||||
"options": [
|
||||
"unknown",
|
||||
"parsing",
|
||||
"complete",
|
||||
"complete_with_failures"
|
||||
],
|
||||
"style": {
|
||||
"unknown": "default",
|
||||
"parsing": "info",
|
||||
"complete": "success",
|
||||
"complete_with_failures": "warning"
|
||||
},
|
||||
"default": "unknown",
|
||||
"readOnly": true,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"graphParsingStatus": {
|
||||
"type": "enum",
|
||||
"required": false,
|
||||
"options": [
|
||||
"no_graph",
|
||||
"parsing",
|
||||
"complete",
|
||||
"unclean"
|
||||
],
|
||||
"style": {
|
||||
"no_graph": "default",
|
||||
"parsing": "info",
|
||||
"complete": "success",
|
||||
"unclean": "warning"
|
||||
},
|
||||
"default": "no_graph",
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -213,6 +213,24 @@
|
||||
"maxLength": 255,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"aiParsingStatus": {
|
||||
"type": "enum",
|
||||
"options": [
|
||||
"unknown",
|
||||
"parsing",
|
||||
"complete",
|
||||
"failed"
|
||||
],
|
||||
"style": {
|
||||
"unknown": "default",
|
||||
"parsing": "info",
|
||||
"complete": "success",
|
||||
"failed": "danger"
|
||||
},
|
||||
"default": "unknown",
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -359,7 +359,7 @@ return [
|
||||
0 => 'youtube.com',
|
||||
1 => 'google.com'
|
||||
],
|
||||
'microtime' => 1774603769.791242,
|
||||
'microtime' => 1774604561.068253,
|
||||
'siteUrl' => 'https://crm.bitbylaw.com',
|
||||
'fullTextSearchMinLength' => 4,
|
||||
'webSocketUrl' => 'ws://api.bitbylaw.com:5000/espocrm/ws',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'cacheTimestamp' => 1774603769,
|
||||
'microtimeState' => 1774603769.963245,
|
||||
'cacheTimestamp' => 1774604771,
|
||||
'microtimeState' => 1774604771.465835,
|
||||
'currencyRates' => [
|
||||
'EUR' => 1.0
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user