Refactor CAdvowareAkten and CDokumente hooks; update localization and metadata; adjust microtime values in config and state files
This commit is contained in:
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
namespace Espo\Custom\Hooks\CAdvowareAkten;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\Repository\Option\SaveOptions;
|
||||
use Espo\Core\Hook\Hook\BeforeSave;
|
||||
|
||||
/**
|
||||
* Hook: Prüft Junction-Table und aktualisiert globalen syncStatus
|
||||
* basierend auf den syncstatus-Werten der verknüpften Dokumente
|
||||
*/
|
||||
class CheckGlobalSyncStatus 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 {
|
||||
// Hole alle verknüpften Dokumente mit ihren syncstatus-Werten aus der Junction-Tabelle
|
||||
$query = $this->entityManager->getQueryBuilder()
|
||||
->select(['syncstatus'])
|
||||
->from('CAdvowareAktenDokumente')
|
||||
->where([
|
||||
'cAdvowareAktenId' => $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"
|
||||
if (empty($rows)) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
return;
|
||||
}
|
||||
|
||||
// Prüfe, ob irgendein Dokument "new" oder "unclean" ist
|
||||
$hasUnsynced = false;
|
||||
foreach ($rows as $row) {
|
||||
$status = $row['syncstatus'] ?? null;
|
||||
if ($status === 'new' || $status === 'unclean' || $status === null || $status === '') {
|
||||
$hasUnsynced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Setze globalen Status
|
||||
if ($hasUnsynced) {
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
} else {
|
||||
// Alle Dokumente sind "synced"
|
||||
$entity->set('syncStatus', 'synced');
|
||||
$entity->set('lastSync', date('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// Bei Fehler loggen und Status auf "unclean" setzen
|
||||
$GLOBALS['log']->error('CAdvowareAkten CheckGlobalSyncStatus Hook Error: ' . $e->getMessage());
|
||||
$entity->set('syncStatus', 'unclean');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,21 @@
|
||||
namespace Espo\Custom\Hooks\CDokumente;
|
||||
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\Repository\Option\SaveOptions;
|
||||
use Espo\Core\Hook\Hook\BeforeSave;
|
||||
|
||||
class CDokumente extends \Espo\Core\Hooks\Base
|
||||
/**
|
||||
* Hook: Berechnet Dokumenten-Hashes und setzt fileStatus
|
||||
*
|
||||
* Verwendet Blake3 als Hash-Algorithmus für optimale Performance
|
||||
*/
|
||||
class CDokumente implements BeforeSave
|
||||
{
|
||||
public function beforeSave(Entity $entity, array $options = [])
|
||||
public function __construct(
|
||||
private \Espo\ORM\EntityManager $entityManager
|
||||
) {}
|
||||
|
||||
public function beforeSave(Entity $entity, SaveOptions $options): void
|
||||
{
|
||||
// Problem: isAttributeChanged('dokument') erkennt Datei-Änderungen nicht,
|
||||
// da EspoCRM Datei-Uploads nicht als Feld-Änderung markiert.
|
||||
@@ -14,23 +25,20 @@ class CDokumente extends \Espo\Core\Hooks\Base
|
||||
// um sicherzustellen, dass Hashes bei Datei-Änderungen berechnet werden.
|
||||
// Optimierung wäre wünschenswert, aber nicht möglich mit aktueller API.
|
||||
|
||||
$dokument = $entity->get('dokument');
|
||||
$dokumentId = $entity->get('dokumentId');
|
||||
|
||||
if (!$dokument) {
|
||||
if (!$dokumentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_object($dokument)) {
|
||||
$attachment = $dokument;
|
||||
} else {
|
||||
$attachment = $this->getEntityManager()->getEntity('Attachment', $dokument);
|
||||
}
|
||||
// Verwende EntityManager zur korrekten Relation-Verwaltung
|
||||
$attachment = $this->entityManager->getEntityById('Attachment', $dokumentId);
|
||||
|
||||
if (!$attachment) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filePath = 'data/upload/' . $attachment->get('id');
|
||||
$filePath = 'data/upload/' . $attachment->getId();
|
||||
if (!file_exists($filePath)) {
|
||||
return;
|
||||
}
|
||||
@@ -41,7 +49,8 @@ class CDokumente extends \Espo\Core\Hooks\Base
|
||||
return;
|
||||
}
|
||||
|
||||
$newBlake3 = \blake3($fileContent);
|
||||
// Blake3 Hashing - schneller als SHA3 und kryptographisch sicher
|
||||
$newBlake3 = blake3($fileContent);
|
||||
|
||||
// Setze Hash
|
||||
$entity->set('blake3hash', $newBlake3);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
"mietinkasso": "Mietinkasso",
|
||||
"aktenzeichen": "Aktenzeichen",
|
||||
"aktennummer": "Aktennummer",
|
||||
"aktenpfad": "Aktenpfad (Windows)",
|
||||
"syncStatus": "Sync-Status",
|
||||
"lastSync": "Letzte Synchronisation",
|
||||
"aktivierungsstatus": "Aktivierungsstatus",
|
||||
@@ -43,7 +42,6 @@
|
||||
"tooltips": {
|
||||
"syncStatus": "Globaler Synchronisationsstatus: synced = Alle Dokumente synchronisiert, unclean = Mindestens ein Dokument ist neu oder hat Änderungen, pending_sync = Synchronisierung wurde gestartet aber noch nicht abgeschlossen, failed = Synchronisierung fehlgeschlagen. Wird automatisch basierend auf den Dokumenten-Status aktualisiert.",
|
||||
"lastSync": "Zeitpunkt der letzten erfolgreichen Synchronisation aller Dokumente",
|
||||
"aktivierungsstatus": "Aktivierungsstatus der Akte: new = Neu angelegt, import = Aus Advoware importiert, active = Aktiv synchronisiert, paused = Synchronisation pausiert, deactivated = Synchronisation deaktiviert",
|
||||
"aktenpfad": "Windows-Dateipfad zur Akte in Advoware"
|
||||
"aktivierungsstatus": "Aktivierungsstatus der Akte: new = Neu angelegt, import = Aus Advoware importiert, active = Aktiv synchronisiert, paused = Synchronisation pausiert, deactivated = Synchronisation deaktiviert"
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@
|
||||
"syncedHash": "Sync-Hash",
|
||||
"usn": "USN",
|
||||
"dateipfad": "Dateipfad",
|
||||
"lastSyncTimestamp": "Letzter Sync",
|
||||
"advowareArt": "Advoware Art",
|
||||
"advowareBemerkung": "Advoware Bemerkung",
|
||||
"contactsvmhdokumente": "Freigegebene Nutzer",
|
||||
"vmhMietverhltnisesDokumente": "Mietverhältnisse",
|
||||
"vmhErstgespraechsdokumente": "Erstgespräche",
|
||||
@@ -47,7 +50,10 @@
|
||||
"syncStatus": "Status der Synchronisation mit Advoware: new=neu, unclean=geändert, synced=synchronisiert, failed=Fehler, unsupported=nicht unterstützt",
|
||||
"syncedHash": "Hash-Wert bei letzter erfolgreicher Synchronisation",
|
||||
"usn": "Update Sequence Number - Versionsnummer für Synchronisation",
|
||||
"dateipfad": "Windows-Dateipfad des Dokuments in Advoware"
|
||||
"dateipfad": "Windows-Dateipfad des Dokuments in Advoware",
|
||||
"lastSyncTimestamp": "Zeitstempel der letzten erfolgreichen Synchronisation mit Advoware",
|
||||
"advowareArt": "Dokumententyp/Art wie in Advoware klassifiziert",
|
||||
"advowareBemerkung": "Bemerkungsfeld aus Advoware - wird bei Sync übernommen"
|
||||
},
|
||||
"options": {
|
||||
"syncStatus": {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
"mietinkasso": "Mietinkasso",
|
||||
"aktenzeichen": "Aktenzeichen",
|
||||
"aktennummer": "Aktennummer",
|
||||
"aktenpfad": "File Path (Windows)",
|
||||
"syncStatus": "Sync Status",
|
||||
"lastSync": "Last Synchronization",
|
||||
"aktivierungsstatus": "Activation Status",
|
||||
@@ -44,7 +43,6 @@
|
||||
"tooltips": {
|
||||
"syncStatus": "Global synchronization status: synced = All documents synchronized, unclean = At least one document is new or has changes, pending_sync = Synchronization started but not yet completed, failed = Synchronization failed. Updated automatically based on document status.",
|
||||
"lastSync": "Timestamp of the last successful synchronization of all documents",
|
||||
"aktivierungsstatus": "Activation status of the file: new = Newly created, import = Imported from Advoware, active = Actively synchronized, paused = Synchronization paused, deactivated = Synchronization deactivated",
|
||||
"aktenpfad": "Windows file path to the file in Advoware"
|
||||
"aktivierungsstatus": "Activation status of the file: new = Newly created, import = Imported from Advoware, active = Actively synchronized, paused = Synchronization paused, deactivated = Synchronization deactivated"
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@
|
||||
"syncedHash": "Sync Hash",
|
||||
"usn": "USN",
|
||||
"dateipfad": "File Path",
|
||||
"lastSyncTimestamp": "Last Sync",
|
||||
"advowareArt": "Advoware Type",
|
||||
"advowareBemerkung": "Advoware Remarks",
|
||||
"contactsvmhdokumente": "Portal Users",
|
||||
"vmhMietverhltnisesDokumente": "Tenancies",
|
||||
"vmhErstgespraechsdokumente": "Initial Consultations",
|
||||
@@ -52,7 +55,10 @@
|
||||
"syncStatus": "Sync status with Advoware: new=new, unclean=changed, synced=synchronized, failed=error, unsupported=not supported",
|
||||
"syncedHash": "Hash value at last successful synchronization",
|
||||
"usn": "Update Sequence Number - Version number for synchronization",
|
||||
"dateipfad": "Windows file path of the document in Advoware"
|
||||
"dateipfad": "Windows file path of the document in Advoware",
|
||||
"lastSyncTimestamp": "Timestamp of last successful synchronization with Advoware",
|
||||
"advowareArt": "Document type/kind as classified in Advoware",
|
||||
"advowareBemerkung": "Remarks field from Advoware - synced automatically"
|
||||
},
|
||||
"options": {
|
||||
"syncStatus": {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"name": "name"
|
||||
},
|
||||
{
|
||||
"name": "aktenzeichen"
|
||||
"name": "aktivierungsstatus"
|
||||
}
|
||||
],
|
||||
[
|
||||
@@ -14,7 +14,7 @@
|
||||
"name": "aktennummer"
|
||||
},
|
||||
{
|
||||
"name": "aktenpfad"
|
||||
"name": "aktenzeichen"
|
||||
}
|
||||
],
|
||||
[
|
||||
@@ -24,12 +24,6 @@
|
||||
{
|
||||
"name": "lastSync"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "aktivierungsstatus"
|
||||
},
|
||||
false
|
||||
]
|
||||
],
|
||||
"style": "default",
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
{
|
||||
"name": "name"
|
||||
},
|
||||
{}
|
||||
{
|
||||
"name": "preview"
|
||||
}
|
||||
]
|
||||
],
|
||||
"dynamicLogicVisible": null,
|
||||
@@ -20,8 +22,13 @@
|
||||
"rows": [
|
||||
[
|
||||
{
|
||||
"name": "preview"
|
||||
"name": "advowareArt"
|
||||
},
|
||||
{
|
||||
"name": "advowareBemerkung"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "description"
|
||||
}
|
||||
@@ -60,7 +67,7 @@
|
||||
"name": "cAdvowareAkten"
|
||||
},
|
||||
{
|
||||
"name": "syncStatus"
|
||||
"name": "dateipfad"
|
||||
}
|
||||
],
|
||||
[
|
||||
@@ -73,7 +80,10 @@
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "dateipfad"
|
||||
"name": "syncStatus"
|
||||
},
|
||||
{
|
||||
"name": "lastSyncTimestamp"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
||||
@@ -2,26 +2,34 @@
|
||||
{
|
||||
"name": "name",
|
||||
"link": true,
|
||||
"width": 25
|
||||
},
|
||||
{
|
||||
"name": "dokument",
|
||||
"width": 20
|
||||
},
|
||||
{
|
||||
"name": "dokument",
|
||||
"width": 15
|
||||
},
|
||||
{
|
||||
"name": "advowareArt",
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"name": "syncStatus",
|
||||
"width": 10
|
||||
},
|
||||
{
|
||||
"name": "lastSyncTimestamp",
|
||||
"width": 12
|
||||
},
|
||||
{
|
||||
"name": "assignedUser",
|
||||
"width": 15
|
||||
"width": 12
|
||||
},
|
||||
{
|
||||
"name": "createdAt",
|
||||
"width": 14
|
||||
"width": 11
|
||||
},
|
||||
{
|
||||
"name": "modifiedAt",
|
||||
"width": 14
|
||||
"width": 10
|
||||
}
|
||||
]
|
||||
@@ -3,6 +3,10 @@
|
||||
"name": "name",
|
||||
"link": true
|
||||
},
|
||||
{
|
||||
"name": "advowareArt",
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"name": "advowareAktenHnr",
|
||||
"align": "left"
|
||||
@@ -12,7 +16,7 @@
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"name": "advowareAktenLastSync",
|
||||
"name": "lastSyncTimestamp",
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -57,12 +57,6 @@
|
||||
"disableFormatting": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"aktenpfad": {
|
||||
"type": "varchar",
|
||||
"maxLength": 500,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"syncStatus": {
|
||||
"type": "enum",
|
||||
"required": false,
|
||||
@@ -118,7 +112,12 @@
|
||||
},
|
||||
"dokumenteSyncstatus": {
|
||||
"type": "enum",
|
||||
"options": ["new", "unclean", "synced", "failed"],
|
||||
"options": [
|
||||
"new",
|
||||
"unclean",
|
||||
"synced",
|
||||
"failed"
|
||||
],
|
||||
"notStorable": true,
|
||||
"utility": true,
|
||||
"disabled": true
|
||||
|
||||
@@ -118,6 +118,24 @@
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"lastSyncTimestamp": {
|
||||
"type": "datetime",
|
||||
"tooltip": true,
|
||||
"readOnly": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"advowareArt": {
|
||||
"type": "varchar",
|
||||
"maxLength": 100,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"advowareBemerkung": {
|
||||
"type": "text",
|
||||
"rows": 4,
|
||||
"tooltip": true,
|
||||
"isCustom": true
|
||||
},
|
||||
"puls": {
|
||||
"type": "link",
|
||||
"entity": "CPuls",
|
||||
|
||||
@@ -360,7 +360,7 @@ return [
|
||||
0 => 'youtube.com',
|
||||
1 => 'google.com'
|
||||
],
|
||||
'microtime' => 1774447406.848339,
|
||||
'microtime' => 1774472414.650919,
|
||||
'siteUrl' => 'https://crm.bitbylaw.com',
|
||||
'fullTextSearchMinLength' => 4,
|
||||
'webSocketUrl' => 'ws://api.bitbylaw.com:5000/espocrm/ws',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'cacheTimestamp' => 1774447407,
|
||||
'microtimeState' => 1774447407.027399,
|
||||
'cacheTimestamp' => 1774472414,
|
||||
'microtimeState' => 1774472414.878455,
|
||||
'currencyRates' => [
|
||||
'EUR' => 1.0
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user