EntwicklerMitarbeiter-Handbuch

Beispiele

Drei vollständige Beispiel-Plugins, die du als Template verwenden kannst.

Entwickler-Handbuch · Plugin-Authoring

1. Artikel-KPI (Report, read-only)

Das Demo-Plugin, das im Hub mit Demo-Plugin laden erzeugt wird.

manifest.json

jsonmanifest.json
{
  "id": "sellx.artikel-kpi",
  "name": "Artikel-KPI",
  "version": "1.0.0",
  "category": "report",
  "requiresDbRole": "read",
  "description": "Top-Artikel nach Verkaufsmenge und Umsatz",
  "author": {
    "name": "sellx GmbH",
    "email": "plugins@sellx.de"
  },
  "queries": [
    {
      "id": "top-articles",
      "name": "Top 10 Artikel",
      "description": "Verkaufte Menge und Umsatz der meistverkauften Artikel",
      "file": "sql/top-articles.sql",
      "parameters": [
        {
          "name": "limit",
          "type": "number",
          "label": "Anzahl",
          "required": true,
          "default": 10,
          "min": 1,
          "max": 100
        }
      ]
    },
    {
      "id": "low-stock",
      "name": "Niedriger Bestand",
      "description": "Artikel mit Lagerbestand unter Schwelle",
      "file": "sql/low-stock.sql",
      "parameters": [
        {
          "name": "threshold",
          "type": "number",
          "label": "Min. Bestand",
          "required": true,
          "default": 10
        }
      ]
    }
  ]
}

sql/top-articles.sql

sqlsql/top-articles.sql
SELECT TOP (@{limit})
  a.cName AS Artikelname,
  a.cArtNr AS Artikelnummer,
  CAST(SUM(b.fAnzahl) AS INT) AS VerkaufteMenge,
  CAST(SUM(b.fGesamtsumme) AS DECIMAL(18,2)) AS Umsatz
FROM tBestellung b
INNER JOIN tBestellPos bp ON bp.tBestellung_kBestellung = b.kBestellung
INNER JOIN tArtikel a ON a.kArtikel = bp.tArtikel_kArtikel
WHERE b.dErstellt >= DATEADD(MONTH, -12, GETDATE())
GROUP BY a.kArtikel, a.cName, a.cArtNr
ORDER BY Umsatz DESC

sql/low-stock.sql

sqlsql/low-stock.sql
SELECT
  a.cArtNr AS Artikelnummer,
  a.cName AS Artikelname,
  CAST(a.fLagerbestand AS INT) AS Bestand,
  CAST(@{threshold} AS INT) AS Schwelle
FROM tArtikel a
WHERE a.fLagerbestand < @{threshold}
ORDER BY a.fLagerbestand ASC

2. Cross-Seller (Report mit Kunden-Parameter)

Zeigt für einen Kunden, welche Artikel er zusammen mit welchem Hauptartikel gekauft hat (Cross-Selling-Analyse).

manifest.json

jsonmanifest.json
{
  "id": "sellx.cross-seller",
  "name": "Cross-Seller",
  "version": "1.0.0",
  "category": "report",
  "requiresDbRole": "read",
  "queries": [
    {
      "id": "frequently-bought-together",
      "name": "Zusammen gekauft",
      "description": "Artikel, die Kunden zusammen mit dem gewählten Artikel kaufen",
      "file": "sql/cross.sql",
      "parameters": [
        {
          "name": "article",
          "type": "article",
          "label": "Hauptartikel",
          "required": true
        },
        {
          "name": "limit",
          "type": "number",
          "label": "Top N",
          "required": true,
          "default": 10
        }
      ]
    }
  ]
}

sql/cross.sql

sqlsql/cross.sql
SELECT TOP (@{limit})
  a2.cName AS Artikelname,
  a2.cArtNr AS Artikelnummer,
  CAST(COUNT(*) AS INT) AS Haeufigkeit
FROM tBestellPos bp1
INNER JOIN tBestellPos bp2
  ON bp2.tBestellung_kBestellung = bp1.tBestellung_kBestellung
  AND bp2.tArtikel_kArtikel <> bp1.tArtikel_kArtikel
INNER JOIN tArtikel a2 ON a2.kArtikel = bp2.tArtikel_kArtikel
WHERE bp1.tArtikel_kArtikel = @{article}
GROUP BY a2.kArtikel, a2.cName, a2.cArtNr
ORDER BY Haeufigkeit DESC

3. Wer-gekauft (Report mit Kunden-Suche)

Zeigt, welche Kunden einen bestimmten Artikel gekauft haben.

manifest.json

jsonmanifest.json
{
  "id": "sellx.who-bought",
  "name": "Wer-gekauft",
  "version": "1.0.0",
  "category": "report",
  "requiresDbRole": "read",
  "queries": [
    {
      "id": "buyers",
      "name": "Käufer",
      "description": "Kunden, die einen Artikel gekauft haben",
      "file": "sql/buyers.sql",
      "parameters": [
        {
          "name": "article",
          "type": "article",
          "label": "Artikel",
          "required": true
        },
        {
          "name": "fromDate",
          "type": "date",
          "label": "Seit",
          "required": false
        }
      ]
    }
  ]
}

sql/buyers.sql

sqlsql/buyers.sql
SELECT DISTINCT
  k.cKundenNr AS KundenNr,
  k.cName AS Kundenname,
  CAST(SUM(bp.fAnzahl) AS INT) AS Menge,
  CAST(SUM(bp.fGesamtsumme) AS DECIMAL(18,2)) AS Umsatz
FROM tBestellPos bp
INNER JOIN tBestellung b ON b.kBestellung = bp.tBestellung_kBestellung
INNER JOIN tKunde k ON k.kKunde = b.tKunde_kKunde
WHERE bp.tArtikel_kArtikel = @{article}
  AND (@{fromDate} IS NULL OR b.dErstellt >= @{fromDate})
GROUP BY k.kKunde, k.cKundenNr, k.cName
ORDER BY Umsatz DESC

Packen

Alle drei Plugins haben die gleiche Verzeichnisstruktur:

textlayout.txt
mein-plugin/
├── manifest.json
├── sql/
│   └── <query-id>.sql
└── icon.png   (optional)

Packen:

bashpack.sh
cd mein-plugin
zip -r ../mein-plugin.sellxpkg .

Installieren im Hub: /plugins .sellxpkg installieren → Datei wählen.

Test-Checkliste

Vor der Veröffentlichung:

1

Queries gegen echte Daten prüfen

Jede Query läuft in SSMS mit echten Daten
2

Manifest validieren

Manifest validiert gegen Schema (siehe Manifest-Schema)
3

Parameter-UX prüfen

Alle Parameter haben sinnvolle label und default
4

Pflichtfelder setzen

Pflichtfelder sind required: true
5

Report-Konformität

Bei report: keine INSERT/UPDATE/DELETE
6

Automation-Sicherheit

Bei automation: requiresDbRole: "write" und Signatur vorhanden
7

SQL-Dateinamen prüfen

Dateinamen der SQL-Files stimmen mit queries[].file überein
8

ZIP-Layout verifizieren

ZIP hat keine führende Verzeichnis-Ebene