zurück zur Dokumentation
[reference] actions DSL workflows triggers logic

Aktionen & Workflows

Server-seitige Aktionen mit der dForge-DSL: Parameter, Bedingungen, Ausführungsmodi, eingebaute Funktionen und Trigger.

veröffentlicht · aktualisiert

Was sind Aktionen?

Aktionen sind serverseitige Operationen, die über das grundlegende CRUD hinausgehen. Sie führen eigene Geschäftslogik aus, die in einer einfachen Skriptsprache (DSL) definiert wird. Beispiele:

  • Einen Lead in ein Konto, einen Kontakt und eine Verkaufschance konvertieren
  • Eine Rechnung aus einem Angebot generieren
  • Bestand zwischen Lagern transferieren
  • Benachrichtigungs-E-Mails versenden

DSL-Struktur

Jede Aktion wird in einer .dsl-Datei unter logic/actions/ in Ihrem Modul definiert, mit bis zu drei Blöcken:

params:
    param_name: type required "Label" [constraints]

canExecute:
    [field] != 'SomeValue'

execute:
    // Ihre Logik hier

Die DSL wird zu JavaScript kompiliert und serverseitig in einer sandboxed Engine mit 5-Sekunden-Timeout ausgeführt. Jede Ausführung erhält eine frische Engine — es gibt keinen geteilten Zustand zwischen Läufen. Die Aktion wird in ui/actions.json registriert, das auf die Skriptdatei verweist und Metadaten wie Symbol, Bezeichnung, Ausführungsmodus und Entitätsbindung setzt.

params (optional)

Deklariert Parameter, die der Anwender ausfüllt, bevor die Aktion läuft:

params:
    dest_warehouse_id: text required "Ziel-Lager"
    quantity: number required "Menge" min=1
    reference_no: text optional "Transfer-Referenz"

Parametertypen: text, number, date, datetime, checkbox, lookup.

canExecute (optional)

Eine Formel, die bestimmt, ob die Aktion verfügbar ist. Wenn sie zu false ausgewertet wird, ist der Aktions-Button deaktiviert. Wird auf dem Client für sofortigen Button-Zustand ausgewertet und vor der Ausführung auf dem Server erneut geprüft.

Wenn canExecute weggelassen wird, ist die Aktion für jeden verfügbar, der das E-Recht (Execute) auf sie hat.

canExecute:
    [stage] != 'Closed Won' AND [stage] != 'Closed Lost'

Bei Aktionen über mehrere Datensätze müssen alle ausgewählten Datensätze canExecute erfüllen — wenn auch nur einer fehlschlägt, ist der Button deaktiviert.

execute (Pflicht)

Der Hauptlogik-Block. Hat Zugriff auf die Felder des aktuellen Datensatzes, Parameter und eingebaute Funktionen.

Feldzugriff

Greifen Sie auf die Felder des aktuellen Datensatzes mit Klammer-Syntax zu:

var name = [account_name]
var total = [quantity] * [unit_price]

Über Referenzen navigieren:

var industry = [account_id].[industry]

Auf Parameter zugreifen:

var dest = params[dest_warehouse_id]

Eingebaute Funktionen

Datenfunktionen

FunktionBeschreibung
insert(entity, data)Einen neuen Datensatz einfügen. Gibt die vollständige eingefügte Zeile zurück.
query(sql, args)Ein parametrisiertes SELECT ausführen. Tabellenreferenzen werden automatisch mit dem aktuellen Modul-Schema qualifiziert. Gibt ein Array von Zeilen-Objekten zurück.
getRecord(entity, pk)Einen einzelnen Datensatz per Primärschlüssel abrufen. Gibt einen schreibgeschützten Accessor zurück.
preloadRef(fkField)Einen per Fremdschlüssel referenzierten Datensatz in den Speicher laden (nur Single-/Each-Modus).
nextNumber(entity)Die nächste Dokumentnummer aus der Nummernsequenz der Entität generieren. Unterstützt modulübergreifend: nextNumber('fin.invoice').
callProc(name, args)Eine Stored Procedure mit benannten Argumenten aufrufen.

Benachrichtigungsfunktionen

FunktionBeschreibung
notify(userId, message)Eine In-App-Benachrichtigung an einen bestimmten Anwender senden.
sendEmail(to, subject, body)Eine E-Mail senden (Raw-Modus — direkter Betreff und HTML-Body).
sendEmail(to, templateCd, data)Eine E-Mail aus einer Vorlage in email_template rendern und versenden.
info(message)Dem Anwender eine Erfolgs-/Info-Meldung anzeigen.
warn(message)Eine Warnung anzeigen. Die Ausführung läuft weiter.
error(message)Einen Fehler anzeigen und die Aktion abbrechen.

Kontext & Hilfsfunktionen

AusdruckBeschreibung
userIdDie ID des aktuellen Anwenders (long).
TODAY()Aktuelles Datum.
NOW()Aktuelles Datum und Zeit (UTC).
addDays(date, n)Tage zu einem Datumswert hinzufügen.
IF(cond, then, else)Bedingter Ausdruck.

Beispiel: Bestand transferieren

params:
    dest_warehouse_id: text required "Ziel-Lager"
    quantity: number required "Zu transferierende Menge" min=1

canExecute:
    [quantity] > 0

execute:
    if ([warehouse_id] == params[dest_warehouse_id]) {
        error('Quell- und Ziel-Lager dürfen nicht identisch sein')
    }

    var stock = query(
        "SELECT stock_id, quantity FROM stock WHERE warehouse_id = @wh AND product_id = @prod",
        { wh: [warehouse_id], prod: [product_id] }
    )

    if (stock[0]['quantity'] < params[quantity]) {
        error('Unzureichender Bestand. Verfügbar: ' + stock[0]['quantity'])
    }

    insert('stock_movement', {
        movement_type: 'Transfer Out',
        warehouse_id: [warehouse_id],
        product_id: [product_id],
        quantity: params[quantity],
        movement_date: TODAY()
    })

    insert('stock_movement', {
        movement_type: 'Transfer In',
        warehouse_id: params[dest_warehouse_id],
        product_id: [product_id],
        quantity: params[quantity],
        movement_date: TODAY()
    })

    info(params[quantity] + ' Einheiten erfolgreich transferiert')

Ausführungsmodi

Aktionen können in verschiedenen Modi laufen, konfiguriert über executionMode (und is_single) in ui/actions.json:

ModusBeschreibung
singleAktion arbeitet auf genau einem Datensatz. Der Button ist nur aktiv, wenn ein Datensatz ausgewählt ist.
eachAktion läuft einmal pro ausgewähltem Datensatz. Jede Ausführung sieht einen Datensatz.
batchAktion erhält alle ausgewählten Datensätze auf einmal und verarbeitet sie als Gruppe.

Bei Aktionen über mehrere Datensätze steuert das isTransacted-Flag den Transaktionsumfang:

  • isTransacted: true — alle Datensätze werden in einer Transaktion verarbeitet. Wenn einer fehlschlägt, werden alle Änderungen zurückgerollt.
  • isTransacted: false — jeder Datensatz läuft in seiner eigenen Transaktion. Fehler sind isoliert; erfolgreiche Datensätze werden trotzdem committet.

Hintergrund-Aktionen

Lang laufende Aktionen können asynchron ausgeführt werden, indem is_async: true gesetzt wird:

  • Die Aktion wird in der background_action-Tabelle eingereiht
  • Die Oberfläche kehrt sofort zurück, sodass der Anwender weiterarbeiten kann
  • Ein Hintergrund-Worker pollt die Queue (alle 2 Sekunden) und führt die Aktion aus
  • Der Anwender erhält eine Benachrichtigung, wenn der Job abgeschlossen ist
  • Fortschritt wird über Server-Sent Events veröffentlicht

Verwenden Sie den asynchronen Modus für Imports, Massen-E-Mails, PDF-Generierung oder alles, was länger als ein paar Sekunden dauert.

Nummernsequenzen

Entitäten können automatische Nummernsequenzen für Dokumentnummerierung definieren:

{
  "numberSequence": {
    "column": "invoice_no",
    "pattern": "{prefix}{yyyy}-{seq:3}",
    "resetPeriod": "year"
  }
}

Wenn ein neuer Datensatz angelegt wird und die Zielspalte leer ist, generiert die Plattform automatisch die nächste Nummer. Der Präfix wird aus ordnergebundenen Modul-Einstellungen aufgelöst.

Pattern-Platzhalter: {yyyy}, {yy}, {mm}, {dd}, {seq:N} (N = mit Nullen aufgefüllte Breite).

Trigger

Trigger lösen Aktionen automatisch als Reaktion auf Datenänderungen aus. Konfigurieren Sie sie in logic/triggers.json:

EventLöst aus bei
insertNeuer Datensatz angelegt
updateBeliebiges Feld am Datensatz geändert
deleteDatensatz gelöscht
status_changeWert eines bestimmten Feldes geändert (vergleicht alt vs. neu)
anyAlle obigen

Ein Trigger kann synchron (innerhalb der ursprünglichen Transaktion) oder asynchron (async: true — als Hintergrund-Job nach dem Commit der Transaktion eingereiht) laufen. Siehe Trigger & Webhooks für die vollständige Referenz.

/ war das hilfreich?

Stecken Sie irgendwo fest?
Sagen Sie es uns.

Wir lesen jede Nachricht und aktualisieren die Dokumentation auf Basis dessen, was Leser fragen. Der schnellste Weg, die Dokumentation zu verbessern, ist, uns zu schreiben.