Werkspur Docs Zur Website

Eigene Entitäten

Was ist das

Eine eigene Entität ist ein selbst definierter, ereignisbasierter Datensatztyp: ein Name plus eine Liste von Attributen. WERKSPUR führt für eine eigene Entität dieselbe Ereignis-Historie wie für ein Los. Jede Änderung bleibt damit nachvollziehbar, auch wenn ein Datensatz später gelöscht wird.

Für jede eigene Entität legt WERKSPUR automatisch eine SQL-Sicht cv_<name> an, zum Beispiel cv_batch. Gelesen wird eine eigene Entität also über gespeicherte Abfragen auf diese Sicht, genau wie jede eingebaute Tabelle. Geschrieben wird sie über zwei Kommandos in einer Aktion, custom.create und custom.update, oder über das form-Widget einer Ansicht, das diese Kommandos für Sie aufruft.

Wann einsetzen

Legen Sie eine eigene Entität für Daten an, die WERKSPUR noch nicht führt. Ein Fotolabor braucht zum Beispiel Sammel-Chargen für seinen Fotodruck: batch für die Charge selbst, batch_item für eine einzelne Position darin, box für einen Versandkarton und box_item für einen darin verpackten Artikel. Die Positionen verweisen jeweils auf ihren Kopf.

Anatomie der Definition

Eine eigene Entität hat einen name, der dem Muster ^[a-z][a-z0-9_]{0,62}$ folgt, eine description und eine Liste attrs. Jedes Attribut ist ein {name, type, ref?}. type ist eines von string, number, integer, boolean, string_array oder number_array.

Ein ref macht ein Attribut zum Verweis auf eine andere eigene Entität. Ein ref-Attribut muss vom Typ string sein, weil es die ID des Zieldatensatzes trägt. Zeigt ein ref auf einen fehlenden oder bereits gelöschten Datensatz, lehnt WERKSPUR das Schreiben mit 422 ab.

Die Prüfung liest direkt die Ereignishistorie, nicht eine möglicherweise nachlaufende Abfragetabelle. Ein Ziel, das eine frühere Aktion in derselben Buchung gerade angelegt hat, ist deshalb sofort sichtbar.

Für Formulare gibt es das form-Widget einer Ansicht. Es trägt einen mode, entweder create oder update, und eine Liste von Feldern, die die Attribute der Entität spiegeln. Beim Absenden bucht das Widget über die mitgelieferten Aktionen custom-create beziehungsweise custom-update. Sie müssen dafür keine eigene Aktion bauen.

Beispiele

Die folgenden zwei Aktionen sind Beispiel-Definitionen zum Nachbauen und zeigen custom.create und custom.update an echten Schritten.

charge-anlegen action
{
  "name": "charge-anlegen",
  "summary": "Legt eine neue Charge an und hängt das erste Werkstück ein.",
  "min_role": "operator",
  "params": [
    {
      "name": "product_id",
      "kind": "text",
      "label": "Artikel",
      "source": "operator",
      "required": true
    },
    {
      "name": "lot",
      "kind": "scan",
      "label": "Los",
      "source": "operator",
      "required": true
    }
  ],
  "steps": [
    {
      "command": "custom.create",
      "bind": {
        "data": {
          "literal": "{\"product_id\":\"${product_id}\",\"capacity\":3,\"status\":\"open\"}"
        },
        "entity": {
          "literal": "batch"
        }
      }
    },
    {
      "command": "custom.create",
      "bind": {
        "data": {
          "literal": "{\"batch_id\":\"${step0.id}\",\"lot\":\"${lot}\"}"
        },
        "entity": {
          "literal": "batch_item"
        }
      }
    }
  ]
}
Mit dem Assistenten
Ich brauche eine Aktion, die eine neue Sammel-Charge anlegt und gleich das erste Werkstück einhängt.

Diese Aktion legt eine neue Sammel-Charge an und ordnet ihr sofort ein Werkstück zu. Der erste Schritt legt per custom.create eine "batch" an, mit den Daten {"product_id":"${product_id}","capacity":3,"status":"open"}: Der Artikel kommt vom Bediener, Kapazität und Status sind feste Werte. Sein Ergebnis liefert die neue ID des Datensatzes im Feld id. Der zweite Schritt legt einen "batch_item" an: {"batch_id":"${step0.id}","lot":"${lot}"}. Die batch_id stammt als step-Bindung aus dem Ergebnis des ersten Schritts, das Los liest der Bediener per Scan ein. Der batch_id-Wert wandert damit als Verweis (ref: batch) in den neuen batch_item-Datensatz.

charge-schliessen action
{
  "name": "charge-schliessen",
  "summary": "Schließt eine einzelne Charge manuell ab.",
  "min_role": "operator",
  "params": [
    {
      "name": "batch_id",
      "kind": "text",
      "label": "Charge",
      "source": "operator",
      "required": true
    }
  ],
  "steps": [
    {
      "command": "custom.update",
      "bind": {
        "data": {
          "literal": "{\"status\":\"closed\"}"
        },
        "entity": {
          "literal": "batch"
        },
        "id": {
          "param": "batch_id"
        }
      }
    }
  ]
}
Mit dem Assistenten
Ich brauche eine Aktion, die eine einzelne Sammel-Charge manuell abschließt.

Der einzige Schritt ist ein custom.update auf die Entität "batch": id kommt aus dem Param batch_id, den der Aufrufer mitgibt, und data trägt nur {"status":"closed"}. Weil custom.update nur die übergebenen Felder ändert, bleiben product_id und capacity dieser Charge unangetastet.

Mit dem Assistenten arbeiten

Eine eigene Entität lässt sich auch über den Assistenten anlegen: Sie beschreiben in einem Satz, welche Daten Sie brauchen, und er schlägt Name, Beschreibung und Attribute samt etwaiger Verweise vor. Besonders bei eigenen Entitäten wächst eine Bearbeitung nur die Attributliste: Der Assistent trägt neue Felder nach, ohne ein bestehendes zu entfernen oder zu ändern. Wie der Assistent grundsätzlich arbeitet, beschreibt das Kapitel Der KI-Assistent.

Fallstricke

Wie eine Aktion ihre Kommando-Schritte aufbaut, zeigt das Kapitel Aktionen. Wie das form-Widget und weitere Widgets in einer Ansicht zusammenspielen, beschreibt das Kapitel Ansichten. Wie Sie eine eigene Entität per SQL lesen, erklärt das Kapitel Gespeicherte Abfragen. Und welche eingebauten Tabellen WERKSPUR bereits führt, zeigt das Kapitel Datenmodell.