Code-Beispiele: Mit und ohne MCP
Die folgenden Beispiele zeigen denselben Anwendungsfall – einmal mit einer Standard-KI (ohne MCP) und einmal mit unserem MCP. Die Unterschiede in Syntax, Funktionen und Code-Qualität sind deutlich sichtbar.
Promt für einen einfachen Button-Code:
Ich habe in Ninox eine Tabelle "Aufträge" und dazu eine Tabelle "Auftragspositionen" (ein Auftrag hat mehrere Positionen). Auf dem Auftrag soll ein Button sein. Wenn ich draufklicke, soll folgendes passieren:
Es sollen nur die Positionen genommen werden, die den Status "Offen" haben. Für diese offenen Positionen soll die Summe aus Menge mal Stückpreis ausgerechnet werden und das Ergebnis in das Feld "Gesamtsumme" im Auftrag geschrieben werden. Außerdem soll ein Dialog aufgehen, in dem steht, wie viele offene Positionen es sind. Wenn es gar keine offenen Positionen gibt, soll eine Meldung erscheinen "Keine offenen Positionen".
Bitte schreibe mir das Ninox-Skript dafür.
Ergebnis ohne MCP
// Ninox-Skript für Button auf dem Auftrag
// Voraussetzung: Tabelle "Auftragspositionen" hat Felder: Auftrag (Referenz auf Aufträge), Status, Menge, Stückpreis
// Auftrag hat Feld: Gesamtsumme
let a := this;
let offenePositionen := select Auftragspositionen where Auftrag = a and text(Status) = "Offen";
let anzahl := count(offenePositionen);
if anzahl = 0 then
set(this, "Gesamtsumme", 0);
alert("Keine offenen Positionen")
else
let gesamtsumme := 0;
for p in offenePositionen do
gesamtsumme := gesamtsumme + (p.Menge * p.Stückpreis)
end;
set(this, "Gesamtsumme", gesamtsumme);
alert(string(anzahl) + " Positionen")
endlet offenePositionen := (select Auftragspositionen where Auftrag = this and Status = "Offen");
let anzahl := count(offenePositionen);
if anzahl > 0 then
let summe := sum(offenePositionen, Menge * Stückpreis);
Gesamtsumme := summe;
alert(text(anzahl) + " offene Position(en)")
else
Gesamtsumme := 0;
alert("Keine offenen Positionen")
endFehler:
- Kommentieren mit
//führen zu Syntaxfehlern - Nutzt
set()statt:=, um Felder zu beschreiben - Syntax
sum([nid], number)ist falsch - Die
Auftragspositionen-Rückverknüpfung könnte direkt ausgelesen werden.selectist nicht notwendig und ineffizient.
Ergebnis mit MCP
let my := this;
let offene := my.'Auftragspositionen'[text(Status) = "Offen"];
if cnt(offene) > 0 then
let summe := sum(for i in offene do i.Menge * i.'Stückpreis' end);
'Gesamtsumme' := summe;
dialog("Offene Positionen", "Es gibt " + text(cnt(offene)) + " offene Position(en).", ["OK"])
else
alert("Keine offenen Positionen")
endlet offenePos := Auftragspositionen[Status = "Offen"];
let anzahl := cnt(offenePos);
if anzahl > 0 then
let summe := sum(offenePos.(Menge * 'Stückpreis'));
Gesamtsumme := summe;
alert("Es gibt " + text(anzahl) + " offene Position(en).")
else
alert("Keine offenen Positionen")
endPromt 2:
Ich habe eine Projektstundenerfassung, von der ich alle offenen Stunden (=noch keine Rechnungsposition verknüpft) in Rechnungen übernehmen möchte. Die Rechnungen muss ich pro Unternehmen erstellen. Die Projekte gehören jeweils zu einem Unternehmen.
Die Projektstunden sollen außerdem noch wie folgt gefiltert werden:
- Keine als gelöscht markierten Stunden
- Nur innerhalb von meinem Abrechnungszeitraum ('Startdatum', 'Enddatum')
- Stunden, wo stornierte Rechnungen verknüpft sind, müssen mit aufgenommen werden
- Stunden, die zum selben Projekt gehören, müssen in einer Rechnungsposition zusammengerechnet werden. Der Positionstitel soll der Projektname sein
Schreibe mir den Code für Ninox. Das Rechnungsdatum soll automatisch gesetzt und die Rechnung mit dem Unternehmen verknüpft werden.
Ergebnis ohne MCP
// =============================================================================
// Ninox: Rechnungen aus offenen Projektstunden erstellen (pro Unternehmen)
// =============================================================================
//
// VORAUSSETZUNG:
// - Skript an einen Button binden (z.B. auf einem Abrechnungszeitraum-Datensatz
// oder auf einer Seite mit Startdatum/Enddatum).
// - Tabellen- und Feldnamen ggf. an Ihre Datenbank anpassen (siehe Anpassungen unten).
//
// LOGIK:
// - Nur Stunden: nicht gelöscht, im Abrechnungszeitraum, ohne Rechnungsposition
// ODER mit stornierter Rechnung verknüpft.
// - Pro Unternehmen eine Rechnung (Rechnungsdatum = heute, Unternehmen verknüpft).
// - Pro Projekt eine Rechnungsposition (Titel = Projektname, Menge = Summe der Stunden).
// - Alle betroffenen Stunden werden mit der neuen Rechnungsposition verknüpft.
//
// ANPASSUNGEN (Tabellen- und Feldnamen):
// - Projektstundenerfassung → Ihre Tabelle für Projektstunden
// - Gelöscht → Boolean „als gelöscht markiert“
// - Datum → Datum der Stunde
// - Rechnungsposition → Referenz von Stunde auf Rechnungsposition (optional)
// - Projekt → Referenz von Stunde auf Projekt
// - Rechnungen → Tabelle Rechnungen
// - Rechnungsdatum, Unternehmen → Felder auf Rechnung
// - Rechnungspositionen → Tabelle Rechnungspositionen
// - Rechnung, Titel, Menge → Felder auf Rechnungsposition (Menge = Stunden)
// - Rechnung.Storniert → Boolean auf Rechnung
// - Projekt.Unternehmen → Referenz Projekt → Unternehmen
// - Projekt.Name (oder Projektname) → Anzeigename des Projekts
// - Stunden (oder Anzahl, etc.) → Zahlenfeld mit der erfassten Stundenzahl
// =============================================================================
// Abrechnungszeitraum: von einem Datensatz "this" (z.B. Abrechnungszeitraum).
// Alternative ohne "this": feste Werte oder Dialog, z.B.:
// let startDatum := date(2025, 3, 1);
// let endDatum := date(2025, 3, 31);
// let startDatum := dialog("Startdatum (YYYY-MM-DD)");
// let endDatum := dialog("Enddatum (YYYY-MM-DD)");
let startDatum := this.Startdatum;
let endDatum := this.Enddatum;
// 1) Offene Stunden: nicht gelöscht, im Zeitraum, keine Rechnungsposition ODER Rechnung storniert
// Hinweis: Falls "Rechnungsposition'.'Rechnung'.'Storniert" in where nicht unterstützt wird,
// zuerst nur Zeitraum + Gelöscht filtern, danach in einer Schleife die Storniert-Bedingung prüfen.
let offeneStunden := select 'Projektstundenerfassung' where
'Gelöscht' != true
and 'Datum' >= startDatum
and 'Datum' <= endDatum
and (
'Rechnungsposition' = null
or 'Rechnungsposition'.'Rechnung'.'Storniert' = true
);
// FALLBACK: Wenn die obige where-Bedingung mit Storniert in Ihrer Ninox-Version
// fehlschlägt, ersetzen Sie den select durch diese zwei Zeilen und filtern danach:
// let alleImZeitraum := select 'Projektstundenerfassung' where 'Gelöscht' != true and 'Datum' >= startDatum and 'Datum' <= endDatum;
// let offeneStunden := []; for s in alleImZeitraum do if s.('Rechnungsposition') = null or (s.('Rechnungsposition').('Rechnung').('Storniert') = true) then offeneStunden := concat(offeneStunden, [s]) end end;
// Eindeutige Unternehmen aus diesen Stunden (über Projekt)
let companies := [];
for s in offeneStunden do
let c := s.Projekt.Unternehmen;
if c != null and not contains(companies, c) then
companies := concat(companies, [c])
end
end;
// Pro Unternehmen eine Rechnung erstellen
for unternehmen in companies do
let rechnung := (create Rechnungen);
rechnung.('Rechnungsdatum') := today();
rechnung.('Unternehmen') := unternehmen;
// Stunden dieses Unternehmens (Projekt gehört zum Unternehmen)
let stundenUnternehmen := [];
for s in offeneStunden do
if s.Projekt != null and s.Projekt.Unternehmen = unternehmen then
stundenUnternehmen := concat(stundenUnternehmen, [s])
end
end;
// Eindeutige Projekte innerhalb dieses Unternehmens
let projekte := [];
for s in stundenUnternehmen do
let p := s.Projekt;
if p != null and not contains(projekte, p) then
projekte := concat(projekte, [p])
end
end;
// Pro Projekt eine Rechnungsposition (Titel = Projektname, Menge = Summe Stunden)
for projekt in projekte do
let stundenProjekt := [];
for s in stundenUnternehmen do
if s.Projekt = projekt then
stundenProjekt := concat(stundenProjekt, [s])
end
end;
let position := (create Rechnungspositionen);
position.('Rechnung') := rechnung;
position.('Titel') := projekt.('Name'); // oder 'Projektname' – Ihren Feldnamen verwenden
position.('Menge') := sum(stundenProjekt.('Stunden')); // Feldname für Stundenzahl anpassen
// Alle Stunden dieser Position zuordnen (Verknüpfung setzen)
for stunde in stundenProjekt do
stunde.('Rechnungsposition') := position
end
end
endlet vStart := Startdatum;
let vEnd := Enddatum;
let anzahl := 0;
do as server
for u in (select Unternehmen) do
let uStunden := (select Projektstunden where
not Gelöscht and
Datum >= vStart and
Datum <= vEnd and
Projekt.Unternehmen = u and
(not Rechnungsposition or
Rechnungsposition.Rechnung.Status = "Storniert")
);
if count(uStunden) > 0 then
let rechnung := (create Rechnungen);
rechnung.(Rechnungsdatum := today());
rechnung.(Unternehmen := u);
for p in (select Projekte where Unternehmen = u) do
let pStunden := for st in uStunden where st.Projekt = p do st end;
if count(pStunden) > 0 then
let summe := sum(for st in pStunden do number(st.Stunden) end);
let pos := (create Rechnungspositionen);
pos.(Rechnung := rechnung);
pos.(Titel := text(p.Projektname));
pos.(Stunden := summe);
for st in pStunden do
st.(Rechnungsposition := pos)
end
end
end;
anzahl := anzahl + 1
end
end
end;
if anzahl > 0 then
alert("Es wurden " + text(anzahl) + " Rechnungen erfolgreich erstellt.")
else
alert("Keine abrechenbaren Stunden im gewählten Zeitraum gefunden.")
endFehler:
- Kommentieren mit
//führen zu Syntaxfehlern concat([nid], [nid])ergibt kein neues Array und führt zu Syntaxfehlerwherekann nur in Verbindung mitselectgenutzt werden, nicht um Arrays zu filtern
Ergebnis mit MCP
---
Projektstunden in Rechnungen pro Unternehmen übernehmen.
- Abrechnungszeitraum: Startdatum, Enddatum (Variante A: Felder auf aktuellem Record; Variante B: unten eintragen).
- Tabellen-/Feldnamen ggf. an Ihre Datenbank anpassen (Projektstunden, Rechnungen, Rechnungspositionen, Projekte, Unternehmen, etc.).
---;
" Abrechnungszeitraum: Bei Button auf Abrechnungszeitraum-Record: let startDatum := this.'Startdatum'; let endDatum := this.'Enddatum'; ";
" Sonst z. B. aus Konfigurationstabelle oder fest: date(Jahr, Monat, Tag) ";
let startDatum := Startdatum;
let endDatum := Enddatum;
" Alle offenen Stunden: nicht gelöscht, im Zeitraum, keine Rechnungsposition ODER stornierte Rechnung verknüpft ";
let offeneStunden := select Projektstunden where not Gelöscht and Datum >= startDatum and Datum <= endDatum and (not Rechnungsposition or Rechnungsposition.Rechnung.Storniert = true);
if cnt(offeneStunden) = 0 then
dialog("Hinweis", "Keine offenen Stunden im Abrechnungszeitraum.", ["OK"])
else
do as transaction
" Eindeutige Unternehmen aus den Stunden (über Projekt) ";
let unternehmenListe := unique(offeneStunden.Projekt.Unternehmen);
for unternehmen in unternehmenListe do
if unternehmen then
" Rechnung pro Unternehmen anlegen ";
let neueRechnung := create Rechnungen;
neueRechnung.(
Unternehmen := unternehmen;
Rechnungsdatum := today()
);
" Eindeutige Projekte dieses Unternehmens mit offenen Stunden ";
let projekteDesUnternehmens := unique(offeneStunden[Projekt.Unternehmen = unternehmen].Projekt);
for projekt in projekteDesUnternehmens do
if projekt then
let stundenFuerProjekt := offeneStunden[Projekt = projekt];
let summeStunden := sum(stundenFuerProjekt.Stunden);
if summeStunden and summeStunden > 0 then
" Eine Rechnungsposition pro Projekt (Titel = Projektname) ";
let neuePosition := create Rechnungspositionen;
neuePosition.(
Rechnung := neueRechnung;
Positionstitel := projekt.Name;
Stunden := summeStunden
);
" Alle zugehörigen Stunden mit dieser Position verknüpfen ";
stundenFuerProjekt.(
Rechnungsposition := neuePosition
)
end
end
end
end
end
end;
dialog("Fertig", "Rechnungen wurden erstellt.", ["OK"])
endlet my := this;
let startDate := my.Startdatum;
let endDate := my.Enddatum;
let offeneStunden := select Projektstunden where
not Gelöscht and
Datum >= startDate and
Datum <= endDate and
(cnt(Rechnungsposition) = 0 or Rechnungsposition.Rechnung.Storniert);
if cnt(offeneStunden) = 0 then
alert("Keine offenen Stunden im Abrechnungszeitraum gefunden.")
else
"Eindeutige Projekte und Unternehmen ermitteln (Pre-Fetch)";
let projekte := unique(offeneStunden.Projekt);
let unternehmenListe := unique(projekte.Unternehmen);
for unt in unternehmenListe do
"Rechnung erstellen und mit Unternehmen verknüpfen";
let rechnung := create Rechnungen;
rechnung.(
Rechnungsdatum := today();
Unternehmen := unt
);
"Projekte dieses Unternehmens filtern";
let untProjekte := projekte[Unternehmen = unt];
for proj in untProjekte do
"Stunden dieses Projekts zusammenrechnen";
let projektStunden := offeneStunden[Projekt = proj];
let gesamtStunden := sum(projektStunden.Stunden);
"Rechnungsposition mit Projektname als Titel erstellen";
let position := create Rechnungspositionen;
position.(
Bezeichnung := proj.Projektname;
Menge := gesamtStunden;
Rechnung := rechnung
);
"Stunden mit der neuen Rechnungsposition verknüpfen";
for stunde in projektStunden do
stunde.(Rechnungsposition := position)
end
end
end
end