Entwickler, der außergewöhnliche CRM- und Laravel-Lösungen liefert

Als erfahrener Entwickler spezialisiere ich mich auf Laravel- und Vue.js-Entwicklung, die Implementierung von Vtiger CRM sowie auf vielfältige WordPress-Projekte. Meine Arbeit zeichnet sich durch kreative, dynamische und benutzerzentrierte Weblösungen aus, die individuell an die Bedürfnisse meiner Kunden angepasst werden.

Im Entwicklungsalltag mit der Vtiger CRM API kommt es häufig zu der unangenehmen Situation, dass beim Löschen eines Datensatzes die zugehörigen Verknüpfungen nicht automatisch entfernt werden. Dies führt dazu, dass verwandte Datensätze in separaten Abfragen gelöscht werden müssen – ein mühsamer und ineffizienter Prozess.

Entfernen von verknüpften Datensätzen über Webservices in Vtiger CRM

Im Entwicklungsalltag mit der Vtiger CRM API kommt es häufig zu der unangenehmen Situation, dass beim Löschen eines Datensatzes die zugehörigen Verknüpfungen nicht automatisch entfernt werden. Dies führt dazu, dass verwandte Datensätze in separaten Abfragen gelöscht werden müssen – ein mühsamer und ineffizienter Prozess. Um diesen Umstand zu umgehen, habe ich eine Hilfsfunktion entwickelt, die es ermöglicht, verknüpfte Datensätze automatisch zu löschen. Die Funktion vtws_delete_related nimmt als Parameter die ID des übergeordneten (Source) und des untergeordneten (Related) Datensatzes sowie optional ein User-Modell zur Kontrolle der Zugriffsrechte entgegen.

Im Folgenden wird der Code der Funktion erläutert und präsentiert. Sie können diese Funktion beispielsweise in die Datei include/Webservices/DeleteRelatedRecords.php einfügen.


function vtws_delete_related($sourceRecordId, $relatedRecordId, $user = false)
{
    global $log, $adb;

    // Zerlegung der Quell-ID in Modul- und Elementkomponenten
    list($moduleSourceId, $elementSourceId) = vtws_getIdComponents($sourceRecordId);
    $webserviceObject = VtigerWebserviceObject::fromId($adb, $moduleSourceId);

    // Ermitteln des Handler-Pfads und der Handler-Klasse
    $handlerPath = $webserviceObject->getHandlerPath();
    $handlerClass = $webserviceObject->getHandlerClass();

    require_once $handlerPath;
    $handler = new $handlerClass($webserviceObject, $user, $adb, $log);
    $meta = $handler->getMeta();

    // Ermitteln des Modulnamens des Quell-Datensatzes
    $sourceModuleName = $meta->getObjectEntityName($sourceRecordId);

    // Prüfung der Benutzerrechte: Liste der erlaubten Module abrufen
    $types = vtws_listtypes(null, $user);

    if (!in_array($sourceModuleName, $types['types'])) {
        throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, 'Permission to perform the operation is denied');
    }

    // Sicherstellen, dass der Quell-Datensatz zum erwarteten Modul gehört
    if ($sourceModuleName !== $webserviceObject->getEntityName()) {
        throw new WebServiceException(WebServiceErrorCode::$INVALIDID, 'Id specified is incorrect');
    }

    if (!$meta->hasPermission(EntityMeta::$UPDATE, $sourceRecordId)) {
        throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, 'Permission to read given object is denied');
    }

    // Prüfung, ob der Quell-Datensatz existiert
    if (!$meta->exists($elementSourceId)) {
        throw new WebServiceException(WebServiceErrorCode::$RECORDNOTFOUND, 'Record you are trying to access is not found');
    }

    // Prüfung der Schreibrechte
    if ($meta->hasWriteAccess() !== true) {
        throw new WebServiceException(WebServiceErrorCode::$ACCESSDENIED, 'Permission to write is denied');
    }

    // Zerlegung der Related-ID in Modul und Element
    list($moduleRelatedId, $elementRelatedId) = vtws_getIdComponents($relatedRecordId);

    // Instanz des verknüpften Datensatzes abrufen
    $relatedRecordInstance = Vtiger_Record_Model::getInstanceById($elementRelatedId);
    $relatedModuleName = $relatedRecordInstance->getModuleName();

    // Instanz des Quellmoduls holen
    $sourceModuleFocus = CRMEntity::getInstance($sourceModuleName);

    if ($sourceModuleFocus && $relatedRecordInstance) {
        // Abhängig von den Modulen (z.B. Potentials mit Products oder Contacts)
        if ($sourceModuleName == 'Potentials' && $relatedModuleName == 'Products') {
            $query = 'DELETE FROM vtiger_seproductsrel WHERE crmid=? AND productid=? AND setype=?';
            $adb->pquery($query, [$elementSourceId, $elementRelatedId, 'Potentials']);
        } elseif ($sourceModuleName == 'Potentials' && $relatedModuleName == 'Contacts') {
            $query = 'DELETE FROM vtiger_contpotentialrel WHERE potentialid=? AND contactid=?';
            $adb->pquery($query, [$elementSourceId, $elementRelatedId]);
        } else {
            // Standardmethode zum Aufheben der Verknüpfung
            $sourceModuleFocus->delete_related_module($sourceModuleName, $elementSourceId, $relatedModuleName, $elementRelatedId);
        }
    }

    // Zwischenspeicher leeren
    VTWS_PreserveGlobal::flush();

    return true;
}

Funktionsweise und Erläuterung

  1. Zunächst wird die Quell-ID (sourceRecordId) in Modul- und Elementkomponenten zerlegt, um den entsprechenden Webservice-Handler zu identifizieren.
  2. Anhand der aktuellen Benutzerrechte wird geprüft, ob der Zugriff auf den Quell-Datensatz erlaubt ist.
  3. Der verknüpfte Datensatz (relatedRecordId) wird ebenso in seine Komponenten zerlegt, und es wird eine Instanz des zugehörigen Modells erzeugt.
  4. Abhängig von den beteiligten Modulen – im Beispiel speziell bei Potentials mit Products oder Contacts – wird ein spezifischer Löschbefehl ausgeführt. Für alle anderen Module wird der Standardmechanismus von Vtiger verwendet, um die Verknüpfung zwischen den Datensätzen zu löschen.
  5. Schließlich wird der Cache geleert (VTWS_PreserveGlobal::flush()) und true zurückgegeben, um anzuzeigen, dass der Vorgang erfolgreich abgeschlossen wurde.

Fazit
Mithilfe der Funktion vtws_delete_related können Sie verknüpfte Datensätze automatisiert über die Vtiger CRM Webservices löschen. Dieses universelle Lösungsbeispiel vereinfacht den Löschvorgang erheblich, da es nicht mehr erforderlich ist, jeden verbundenen Datensatz einzeln über weitere Anfragen zu entfernen. Administratoren und Entwickler profitieren von einer vereinfachten, einheitlichen Methode, die Prozesse zu beschleunigen und den Wartungsaufwand zu reduzieren.