Funktionsreferenz: Übergreifende fn-Funktionen
Die übergreifenden fn-Funktionen ermöglichen serverseitige Berechnungen, Konvertierungen und Datenfeld-Auswertungen direkt in der GraphQL-Query. Sie sind in slowFilter-Ausdrücken, in expr:-Parametern (_string, _int, _float, _if) und in verschachtelten Expressions verfügbar. Sie operieren auf Feldwerten und Konstanten und werden vom ERP-Server ausgewertet.
Grundlegende GraphQL-Kenntnisse werden vorausgesetzt. Sollten Ihnen Konzepte wie Tabellenzugriff, Filter oder slowFilter-Syntax noch nicht vertraut sein, empfehlen wir zunächst die GraphQL Doku - Abfragen (Queries).
Inhaltsverzeichnis
- Überblick
- Syntax
- Text-Funktionen
- Datum/Zeit-Funktionen
- Konvertierungs-Funktionen
- Benutzer-Funktionen
- Nachschlagen/Auswerten-Funktionen
- Praxisbeispiele
- Stolpersteine
1. Überblick
Die Funktionen decken folgende Bereiche ab:
| Kategorie | Beispiele |
|---|---|
| Text/String | fnLeft, fnPos, fnLength, fnGetPosString |
| Datum/Zeit | fnYear, fnDiffDate, fnIncDate, fnFormatDateTime |
| Konvertierung | fnToInt, fnToDate, fnToBool, fnToText |
| Benutzer | fnGetAktBzr, fnGetAktBzrNr, fnGetAktBzrSel |
| Nachschlagen/Auswerten | fnDSInfo, fnEntfernung, fnGetBit, fnGetAlter, fnGetPlzInfo |
fnGetBit und fnToBool können direkt als Filterbedingung verwendet werden, ohne Vergleichsoperator.
Beachten Sie
In Filtern sind fn-Funktionen nur über slowFilter verfügbar, nicht über fastFilter. Wenn ein Filter auch ohne fn-Funktionen formuliert werden kann, ist fastFilter immer vorzuziehen, weil der Server die Daten direkt auf dem Index filtert statt sie erst zu laden und dann auszuwerten.
2. Syntax
Parameter-Konvention
Alle fn-Funktionen nehmen eine positionelle Liste von Expressions als Parameter. Jeder Parameter kann ein Literal (value), ein Feldverweis (field) oder eine verschachtelte Funktion sein.
# Literal
{fnLeft: [{value: "Hallo Welt"}, {value: 5}]}
# Feldverweis
{fnLeft: [{field: fldSuchBeg}, {value: 3}]}
# Verschachtelt: erst Datum konvertieren, dann Jahr extrahieren
{fnYear: [{fnToDate: [{value: "14.04.2026"}]}]}
Verwendung in slowFilter
Expression-Funktionen werden in Vergleichsoperatoren eingebettet:
query {
tblAddresses {
rowsRead(slowFilter: {
gt: [{fnLength: [{field: fldSuchBeg}]}, {value: 20}]
}) {
fldAdrNr
fldSuchBeg
}
}
}
Verwendung in Mutations-Expressions
Expression-Funktionen können auch direkt als Mutation über die _string, _int, _float Expression-Felder auf Root-Ebene ausgewertet werden:
mutation {
heute: _string(expr: { fnGetAktDate: [] })
jahr: _int(expr: { fnYear: [{fnGetAktDate: []}] })
left: _string(expr: { fnLeft: [{value: "Testprodukt"}, {value: 4}] })
}
{
"heute": "15.04.2026",
"jahr": 2026,
"left": "Test"
}
3. Text-Funktionen
fnLeft(text, anzahl) → String
Gibt die ersten anzahl Zeichen von text zurück.
mutation {
result: _string(expr: { fnLeft: [{value: "Testprodukt Premium"}, {value: 4}] })
}
{ "result": "Test" }
fnRight(text, anzahl) → String
Gibt die letzten anzahl Zeichen von text zurück. Gibt einen leeren String zurück wenn anzahl größer als die Textlänge ist.
mutation {
result: _string(expr: { fnRight: [{value: "Testprodukt Premium"}, {value: 7}] })
}
{ "result": "Premium" }
fnMid(text, start, anzahl) → String
Gibt anzahl Zeichen ab Position start (1-basiert) aus text zurück.
mutation {
result: _string(expr: { fnMid: [{value: "RE12600002"}, {value: 3}, {value: 3}] })
}
{ "result": "126" }
fnPos(suchtext, text) → Int
Sucht suchtext in text und gibt die Position zurück (1-basiert). Gibt 0 zurück wenn nicht gefunden.
mutation {
result: _int(expr: { fnPos: [{value: "Premium"}, {value: "Testprodukt Premium"}] })
}
{ "result": 13 }
Beachten Sie
Achtung bei RTF-Feldern:
Felder wie fldBez1 sind intern RTF-Blobs. Vor der Verwendung in Text-Funktionen mit fnToText konvertieren: {fnPos: [{value: "Silber"}, {fnToText: [{field: fldBez1}]}]}
fnLength(text) → Int
Gibt die Zeichenlänge von text zurück.
mutation {
result: _int(expr: { fnLength: [{value: "Hallo Welt"}] })
}
{ "result": 10 }
fnToString(wert) → String
Wandelt wert in einen String um. Liest Felder über ihren Rohwert. Bei RTF-Blob-Feldern wird daher der rohe RTF-Markup zurückgegeben ({\rtf1\ansi...), nicht der Klartext. Für RTF-Felder stattdessen fnToText verwenden.
mutation {
zahl: _string(expr: { fnToString: [{value: 42}] })
komma: _string(expr: { fnToString: [{value: 3.14}] })
}
{ "zahl": "42", "komma": "3,14" }
fnToText(wert) → String
Wandelt wert in Klartext um. Liest Felder über ihre Display-Darstellung. Bei RTF-Blob-Feldern (z.B. fldBez1) wird dadurch das RTF-Markup entfernt und der lesbare Text extrahiert.
query {
tblProducts {
rowsRead(slowFilter: {
gt: [{fnPos: [{value: "Silber"}, {fnToText: [{field: fldBez1}]}]}, {value: 0}]
}) {
fldArtNr
fldBez1(as: DISPLAY_TEXT)
}
}
}
fnGetPosString(text, position, trennzeichen?) → String
Teilt text am trennzeichen und gibt das Token an position zurück (1-basiert, Position 0 ergibt leeren String). position muss ein Integer sein. trennzeichen ist optional, Standard ist Komma.
mutation {
semikolon: _string(expr: {
fnGetPosString: [{value: "Berlin;Hamburg;München"}, {value: 2}, {value: ";"}]
})
komma: _string(expr: {
fnGetPosString: [{value: "Berlin,Hamburg,München"}, {value: 3}]
})
}
{ "semikolon": "Hamburg", "komma": "München" }
4. Datum/Zeit-Funktionen
Datum erzeugen und konvertieren
| Funktion | Parameter | Rückgabe | Beschreibung |
|---|---|---|---|
fnDate(wert) | [String] | Date | String in Datum konvertieren |
fnToDate(wert) | [String] | Date | Alias für fnDate (gleiche Implementierung) |
fnTime(wert) | [String] | Time | String in Uhrzeit konvertieren |
fnToTime(wert) | [String] | Time | Alias für fnTime (gleiche Implementierung) |
fnToDateTime(wert) | [String] | DateTime | String in Datum+Uhrzeit konvertieren |
Das Eingabeformat richtet sich nach den Ländereinstellungen des Servers. Auf einem deutschen Server:
- Datum:
"14.04.2026"oder"14.04.26" - Uhrzeit:
"14:30:00"oder"14:30" - Datum+Uhrzeit:
"14.04.2026 08:30:00"
ISO-Format ("2026-04-14") wird nicht akzeptiert.
mutation {
datum: _string(expr: {
fnFormatDateTime: [{value: "dd.mm.yyyy"}, {fnToDate: [{value: "14.04.2026"}]}]
})
}
{ "datum": "14.04.2026" }
Datum-Bestandteile extrahieren
| Funktion | Parameter | Rückgabe | Beschreibung |
|---|---|---|---|
fnYear(datum) | [Date/DateTime] | Int | Jahreszahl |
fnMonth(datum) | [Date/DateTime] | Int | Monat (1–12) |
fnDay(datum) | [Date/DateTime] | Int | Tag im Monat (1–31) |
fnHour(datum) | [DateTime] | Int | Stunde (0–23) |
fnMinute(datum) | [DateTime] | Int | Minute (0–59) |
fnSecond(datum) | [DateTime] | Int | Sekunde (0–59) |
mutation {
jahr: _int(expr: { fnYear: [{fnGetAktDate: []}] })
monat: _int(expr: { fnMonth: [{fnGetAktDate: []}] })
tag: _int(expr: { fnDay: [{fnGetAktDate: []}] })
stunde: _int(expr: { fnHour: [{fnGetAktDate: [{value: "Time"}]}] })
minute: _int(expr: { fnMinute: [{fnGetAktDate: [{value: "Time"}]}] })
}
{ "jahr": 2026, "monat": 4, "tag": 15, "stunde": 16, "minute": 30 }
Aktuelles Datum
| Funktion | Parameter | Rückgabe | Beschreibung |
|---|---|---|---|
fnGetDate() | [] | Date | Aktuelles Datum |
fnGetAktDate() | [] | Date | Aktuelles Programmdatum |
fnGetAktDate("Time") | ["Time"] | DateTime | Programmdatum mit Uhrzeit |
mutation {
datum: _string(expr: { fnGetAktDate: [] })
mitZeit: _string(expr: { fnGetAktDate: [{value: "Time"}] })
}
{
"datum": "15.04.2026",
"mitZeit": "15.04.2026 16:30:31"
}
Datum-Arithmetik
fnDiffDate(startDatum, endDatum) → Int
Berechnet die Anzahl der Tage zwischen startDatum und endDatum. Positiv wenn endDatum nach startDatum liegt.
mutation {
tage: _int(expr: { fnDiffDate: [
{fnToDate: [{value: "01.01.2026"}]},
{fnToDate: [{value: "15.04.2026"}]}
] })
}
{ "tage": 104 }
fnIncDate(datum, tage?, monate?) → Date
Addiert Tage und/oder Monate zu einem Datum. Negative Werte subtrahieren.
mutation {
plus7Tage: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnIncDate: [{fnGetAktDate: []}, {value: 7}]}
] })
plus3Monate: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnIncDate: [{fnGetAktDate: []}, {value: 0}, {value: 3}]}
] })
}
{ "plus7Tage": "22.04.2026", "plus3Monate": "15.07.2026" }
fnGetDateQuartalAnfang(datum) → Date
Gibt den ersten Tag des Quartals zurück in dem datum liegt.
fnGetDateQuartalEnde(datum) → Date
Gibt den letzten Tag des Quartals zurück in dem datum liegt. Die Rückgabe muss mit fnFormatDateTime formatiert werden.
mutation {
anfang: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnGetDateQuartalAnfang: [{fnGetAktDate: []}]}
] })
ende: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnGetDateQuartalEnde: [{fnGetAktDate: []}]}
] })
}
{ "anfang": "01.04.2026", "ende": "30.06.2026" }
fnFormatDateTime(format, datum) → String
Formatiert datum nach der angegebenen format-Zeichenkette.
| Platzhalter | Bedeutung | Beispiel |
|---|---|---|
dd | Tag mit führender Null | 15 |
mm | Monat mit führender Null | 04 |
yyyy | Vierstelliges Jahr | 2026 |
yy | Zweistelliges Jahr | 26 |
hh | Stunde mit führender Null | 16 |
nn | Minute mit führender Null | 30 |
ss | Sekunde mit führender Null | 00 |
w | Kalenderwoche | 16 |
ddd | Wochentag (Abkürzung) | Di |
dddd | Wochentag (ausgeschrieben) | Dienstag |
mutation {
iso: _string(expr: { fnFormatDateTime: [{value: "yyyy-mm-dd"}, {fnGetAktDate: []}] })
deutsch: _string(expr: { fnFormatDateTime: [{value: "dd.mm.yyyy hh:nn:ss"}, {fnGetAktDate: [{value: "Time"}]}] })
}
{ "iso": "2026-04-15", "deutsch": "15.04.2026 16:30:31" }
5. Konvertierungs-Funktionen
| Funktion | Parameter | Rückgabe | Beschreibung |
|---|---|---|---|
fnToInt(wert) | [Any] | Int | In Ganzzahl konvertieren |
fnToFloat(wert) | [Any] | Float | In Fließkommazahl konvertieren |
fnToBool(wert) | [Any] | Boolean | In Wahrheitswert konvertieren (0/1, true/false) |
fnToString(wert) | [Any] | String | In String konvertieren (bei RTF-Feldern: roher Markup) |
fnToText(wert) | [Any] | String | In Klartext konvertieren (bei RTF-Feldern: Markup entfernt) |
fnToDate(wert) | [String] | Date | In Datum konvertieren (Serverformat) |
fnToTime(wert) | [String] | Time | In Uhrzeit konvertieren |
fnToDateTime(wert) | [String] | DateTime | In Datum+Uhrzeit konvertieren |
mutation {
ganzzahl: _int(expr: { fnToInt: [{value: "42"}] })
kommazahl: _float(expr: { fnToFloat: [{value: "3,14"}] })
bool: _if(expr: { fnToBool: [{value: 1}] }) { r: _string(value: "true") }
}
{ "ganzzahl": 42, "kommazahl": 3.14, "bool": { "r": "true" } }
Beachten Sie
fnToFloat nutzt die Ländereinstellungen des Servers für das Dezimal- und Tausendertrennzeichen. Das Komma wird zusätzlich immer als Dezimaltrennzeichen akzeptiert. Auf einem deutschen Server: "3,14" → 3.14, "3.14" → 314 (Punkt = Tausender-Separator).
6. Benutzer-Funktionen
| Funktion | Parameter | Rückgabe | Beschreibung |
|---|---|---|---|
fnGetAktBzr() | [] | String | Benutzerkürzel des angemeldeten Benutzers |
fnGetAktBzrNr() | [] | Int/String | Nummer des angemeldeten Benutzers |
fnGetAktBzrSel(n) | [Int] | String | Selektionsfeld n des angemeldeten Benutzers |
mutation {
kuerzel: _string(expr: { fnGetAktBzr: [] })
nummer: _string(expr: { fnGetAktBzrNr: [] })
selektion1: _string(expr: { fnGetAktBzrSel: [{value: 1}] })
}
{ "kuerzel": "gql", "nummer": "2", "selektion1": "" }
Info
Die Rückgabewerte sind abhängig vom angemeldeten Benutzer.
7. Nachschlagen/Auswerten-Funktionen
fnDSInfo(feldname, schlüssel, format?, trennzeichen?) → String
Liest einen Wert aus einem Datenfeld das als Key-Value-Liste (CommaText) gespeichert ist. Nicht zu verwechseln mit DBInfo() im ERP-Feldeditor (Cross-Table-Lookup), das im GraphQL-Schema nicht verfügbar ist.
| Parameter | Typ | Beschreibung |
|---|---|---|
| 1 | String | Feldname oder Key-Value-String |
| 2 | String | Schlüssel dessen Wert zurückgegeben wird (leer = gesamte Liste) |
| 3 (optional) | String | "Text" für Zeilenformat, "SvlFormat" für StringValueList |
| 4 (optional) | String | Trennzeichen zwischen Name und Value |
Der erste Parameter kann ein Feldname des aktuellen Datensatzes sein (wird dann zur Laufzeit gelesen) oder ein direkter Key-Value-String. Wenn kein = im Wert vorkommt, wird er als Feldname interpretiert.
mutation {
tblAddresses {
name: _string(expr: {
fnDSInfo: [{value: "Name=Mueller,Ort=Berlin"}, {value: "Name"}]
})
ort: _string(expr: {
fnDSInfo: [{value: "Name=Mueller,Ort=Berlin"}, {value: "Ort"}]
})
alles: _string(expr: {
fnDSInfo: [{value: "Name=Mueller,Ort=Berlin"}, {value: ""}]
})
}
}
{
"tblAddresses": {
"name": "Mueller",
"ort": "Berlin",
"alles": "Name=Mueller,Ort=Berlin"
}
}
Im slowFilter kann der erste Parameter auch ein Feldverweis sein. Dann liest fnDSInfo den Inhalt dieses Feldes und parst ihn als Key-Value-Liste:
slowFilter: {eq: [{fnDSInfo: [{field: fldSel1}, {value: "Typ"}]}, {value: "Gold"}]}
Beachten Sie
fnDSInfo funktioniert im Tabellenkontext (Mutation auf einer Tabelle oder slowFilter), nicht in Mutations-Expressions auf Root-Ebene.
fnGetBit(wert, bitNr) → Boolean
Prüft ob das Bit an Position bitNr (0-basiert) in wert gesetzt ist.
mutation {
bit0: _if(expr: { fnGetBit: [{value: 5}, {value: 0}] }) { r: _string(value: "gesetzt") }
bit1: _if(expr: { fnGetBit: [{value: 5}, {value: 1}] }) { r: _string(value: "gesetzt") }
bit2: _if(expr: { fnGetBit: [{value: 5}, {value: 2}] }) { r: _string(value: "gesetzt") }
}
{
"bit0": { "r": "gesetzt" },
"bit1": null,
"bit2": { "r": "gesetzt" }
}
5 = binär 101: Bit 0 gesetzt, Bit 1 nicht, Bit 2 gesetzt. Nützlich für Felder die Bitmasken speichern (z.B. Status-Flags, Berechtigungen).
fnEntfernung(plz1, plz2, land1?, land2?) → Float
Berechnet die Entfernung zwischen zwei Postleitzahlen in Kilometern. Gibt einen negativen Wert zurück wenn die Berechnung nicht möglich ist (fehlende PLZ-Geodaten). Optional können Länderkennzeichen mitgegeben werden.
| Parameter | Typ | Beschreibung |
|---|---|---|
| 1 | String | PLZ Ausgangspunkt |
| 2 | String | PLZ Zielpunkt |
| 3 (optional) | String | Länderkennzeichen Ausgangspunkt |
| 4 (optional) | String | Länderkennzeichen Zielpunkt |
mutation {
km: _float(expr: { fnEntfernung: [{value: "55543"}, {value: "60329"}] })
}
{ "km": -1 }
Info
Negativer Wert wenn PLZ-Geodaten auf dem Server nicht verfügbar sind.
fnGetAlter(datum) → Int
Berechnet das Alter in Jahren ausgehend von datum. Verwendet das Serverdatum als Referenz.
mutation {
alter: _int(expr: { fnGetAlter: [{fnToDate: [{value: "15.06.1990"}]}] })
}
{ "alter": 35 }
fnGetPlzInfo(plz, feldname?) → String
Gibt zu plz Informationen aus der PLZ-Tabelle zurück.
| Parameter | Typ | Beschreibung |
|---|---|---|
| 1 | String | Postleitzahl |
| 2 (optional) | String | Feldname (leer = Ortsname) |
mutation {
ort: _string(expr: { fnGetPlzInfo: [{value: "55543"}] })
}
{ "ort": "Bad Kreuznach" }
8. Praxisbeispiele
8.1 Artikel mit „Silber" in der Bezeichnung finden
Die Artikelbezeichnung (fldBez1) ist ein RTF-Blob-Feld. Vor der Textsuche muss es mit fnToText konvertiert werden. Dieses Feld ist im fastFilter nicht verfügbar.
query {
tblProducts {
rowsRead(slowFilter: {
# fnPos gibt 0 zurück wenn nicht gefunden, >0 wenn gefunden
gt: [{fnPos: [
{value: "Silber"},
{fnToText: [{field: fldBez1}]} # RTF → Klartext
]}, {value: 0}]
}) {
fldArtNr
fldBez1(as: DISPLAY_TEXT)
}
}
}
8.2 Adressen mit langem Suchbegriff
Zeichenlänge ist eine Berechnung die nur per slowFilter möglich ist:
query {
tblAddresses {
rowsRead(slowFilter: {
gt: [
{fnLength: [{field: fldSuchBeg}]}, # Länge berechnen
{value: 20} # mit 20 vergleichen
]
}) {
fldAdrNr
fldSuchBeg
}
}
}
8.3 Vorgänge aus dem aktuellen Quartal
fnGetDateQuartalAnfang und fnGetDateQuartalEnde berechnen die Quartalsgrenzen dynamisch. Im Gegensatz zu einem statischen Datumsvergleich per fastFilter passt sich der Filter automatisch an:
query {
tblTransactions {
rowsRead(slowFilter: {
and: [
# Vorgangsdatum >= Quartalsanfang
{ge: [{field: fldDat}, {fnGetDateQuartalAnfang: [{fnGetAktDate: []}]}]},
# Vorgangsdatum <= Quartalsende
{le: [{field: fldDat}, {fnGetDateQuartalEnde: [{fnGetAktDate: []}]}]}
]
}) {
fldBelegNr
fldDat
}
}
}
8.4 Quartalsgrenzen und Datumsarithmetik berechnen
Quartalsgrenzen, Datumsverschiebungen und Formatierungen in einer Query:
mutation {
# Quartalsanfang und -ende für das aktuelle Datum
quartalAnfang: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnGetDateQuartalAnfang: [{fnGetAktDate: []}]}
] })
quartalEnde: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnGetDateQuartalEnde: [{fnGetAktDate: []}]}
] })
# Datum verschieben: 7 Tage in die Zukunft
plus7Tage: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnIncDate: [{fnGetAktDate: []}, {value: 7}]}
] })
# Datum verschieben: 3 Monate in die Zukunft (0 Tage, 3 Monate)
plus3Monate: _string(expr: { fnFormatDateTime: [
{value: "dd.mm.yyyy"},
{fnIncDate: [{fnGetAktDate: []}, {value: 0}, {value: 3}]}
] })
}
{
"quartalAnfang": "01.04.2026",
"quartalEnde": "30.06.2026",
"plus7Tage": "22.04.2026",
"plus3Monate": "15.07.2026"
}
8.5 Adressen nach Suffix im Suchbegriff filtern
fnRight extrahiert die letzten Zeichen eines Feldes. Suffix-Suchen sind mit fastFilter nicht möglich:
query {
tblAddresses {
rowsRead(slowFilter: {
eq: [
{fnRight: [{field: fldSuchBeg}, {value: 8}]}, # letzte 8 Zeichen
{value: "RECHNUNG"} # mit "RECHNUNG" vergleichen
]
}) {
fldAdrNr
fldSuchBeg
}
}
}
8.6 Vorgänge aus einem bestimmten Monat per fastFilter-Datumsbereich
Wenn das Datum als Feld im fastFilter verfügbar ist (wie fldDat bei Vorgängen), ist ein Datumsbereich per fastFilter immer vorzuziehen:
query {
tblTransactions {
# fastFilter: performanter als slowFilter mit fnYear+fnMonth
rowsRead(fastFilter: {
and: [
{ge: [{field: fldDat}, {value: "2026-03-01"}]}, # ab 1. März
{lt: [{field: fldDat}, {value: "2026-04-01"}]} # bis vor 1. April
]
}) {
fldBelegNr
fldDat
}
}
}
8.7 Adressen deren Suchbegriff "GALERIE" enthält
fnPos auf einem normalen String-Feld (kein RTF, kein fnToText nötig):
query {
tblAddresses {
rowsRead(slowFilter: {
gt: [{fnPos: [{value: "GALERIE"}, {field: fldSuchBeg}]}, {value: 0}]
}) {
fldAdrNr
fldSuchBeg
}
}
}
8.8 Semikolon-getrenntes Feld aufsplitten
Ein Selektionsfeld enthält mehrere Werte getrennt durch Semikolon. Das zweite Token extrahieren:
mutation {
token: _string(expr: {
# "Berlin;Hamburg;München" am ";" splitten, Position 2 holen
fnGetPosString: [{value: "Berlin;Hamburg;München"}, {value: 2}, {value: ";"}]
})
}
{ "token": "Hamburg" }
9. Stolpersteine
Parameter-Typen beachten
Die Fehlermeldungen des Servers sind aussagekräftig:
GetAktBzrSel(): Ungültiger Parametertype. 1. Parameter Erwartet: Integer. Gefunden: ftWideString
Häufige Fehlerquellen: - Integer-Parameter als String übergeben: {value: "1"} statt {value: 1} - Datum als String statt als fnToDate-Ergebnis: {value: "14.04.2026"} statt {fnToDate: [{value: "14.04.2026"}]}