# D365NAV — Microsoft Dynamics NAV

> Konnektor für Microsoft Dynamics NAV. Unterstützt Lesen und Schreiben über OData.

---

Site [llms.txt](/llms.txt)

---

Der D365NAV-Konnektor verbindet die DataBridge mit **Microsoft Dynamics NAV**
über OData. Er ist auf die ältere NAV-API-Struktur ausgelegt und unterstützt auch
OnPremise-Installationen mit NTLM-Authentifizierung.

| Eigenschaft | Wert |
|---|---|
| Lesen | ✅ unterstützt |
| Schreiben | ✅ unterstützt |
| Job-Filter | ✅ wird als OData-`$filter` an NAV übergeben |
| Status | Freigegeben |
| Getestete Mindestversion | NAV 2018 |

> **Die Mindestversion wird nicht geprüft**
>
> Die Angabe beschreibt den getesteten Stand. Die DataBridge fragt die NAV-Version **nicht**
> ab. Ältere Installationen können funktionieren, sofern sie OData mit `$metadata`
> bereitstellen — abgesichert ist das jedoch nicht.



> **Nicht alle BC-Funktionen stehen auch in NAV zur Verfügung**
>
> Der NAV-Konnektor ist dem [D365BC-Konnektor](../d365bc/) nachempfunden, aber **nicht mit
> ihm identisch**. Die wichtigsten Abweichungen:
> 
> - **Statische Schlüsselwerte (`StaticValue`) werden nicht unterstützt.** Die Schlüssel-
>   und Filtererzeugung greift stets auf `attributeName` zu; ein `KeyValue` ohne
>   `attributeName` führt zum Abbruch.
> - **Ein leerer Textwert wird als `null` geschrieben**, nicht als leerer String — das
>   Zielfeld bleibt damit unverändert, statt geleert zu werden.
> - **`LookupType: Name` wird nicht unterstützt** (siehe SourceOperations).



---

## Verbindungsparameter

### Cloud-Umgebung (OAuth2)

```json
{
  "clientId": "<App-Registration Client ID>",
  "clientSecret": "<App-Registration Client Secret>",
  "tenantId": "<Entra Tenant ID>",
  "environment": "<NAV-Umgebungsname>",
  "companyId": "<Company ID (GUID)>",
  "url": "https://<server>/<pfad>/"
}
```

### OnPremise-Umgebung (NTLM)

```json
{
  "userName": "<domain\\benutzername>",
  "password": "<Passwort>",
  "url": "https://<server>:<port>/<pfad>/",
  "baseAddress": "https://<server>:<port>/",
  "authenticationMethod": "NTLM"
}
```

> **`url` ist immer erforderlich — auch bei NTLM**
>
> `baseAddress` ersetzt `url` **nicht**. Sämtliche Anfrage-Adressen — Datenabruf,
> Metadaten, Schreib- und Löschvorgänge — werden aus `url` gebildet. Fehlt der Parameter,
> bricht der Konnektor beim ersten Aufruf mit einem Fehler ab.
> 
> `baseAddress` wird ausschließlich bei `authenticationMethod = NTLM` für den
> NTLM-Credential-Cache verwendet und ist ansonsten entbehrlich.
> 
> Ein fehlender Schrägstrich am Ende von `url` wird automatisch ergänzt.
> 
> Die Metadaten werden eine Ebene oberhalb von `url` abgefragt. Aus
> `https://<server>:<port>/<instanz>/ODataV4/Company('CRONUS')/` wird also
> `https://<server>:<port>/<instanz>/ODataV4/$metadata`. Antwortet der Server dort nicht mit einem
> Erfolgsstatus, bricht der Konnektor mit `Could not read Metadata from <URL> (StatusCode: …)` ab.



> **`authenticationMethod` wirkt nur beim Wert NTLM**
>
> Nur der Wert `NTLM` (Groß-/Kleinschreibung egal) schaltet auf NTLM-Authentifizierung um —
> und auch das nur, wenn zusätzlich `userName` und `password` gesetzt sind.
> 
> Bei **jedem anderen Wert** — auch beim Vorgabewert `Basic` — entscheidet die DataBridge
> automatisch anhand der vorhandenen Felder: `userName` + `password` ergibt Basic Auth,
> sonst `clientId` + `clientSecret` + `tenantId` für OAuth2. Ein Tippfehler im Wert bleibt
> daher folgenlos, solange nicht NTLM benötigt wird.



### Optionale Parameter

| Parameter | Standardwert | Beschreibung |
|---|---|---|
| `scope` | `https://api.businesscentral.dynamics.com/.default` | OAuth2-Scope beim Token-Abruf |
| `baseAddress` | *(leer)* | Basis-Adresse für den NTLM-Credential-Cache |
| `authenticationMethod` | `Basic` | Siehe Hinweis oben |
| `maxPageSize` | `5000` | Maximale Datensätze pro Abruf-Seite |
| `language` | `de-DE` | Kultur für die Interpretation von Zahlen- und Datumsformaten |
| `httpClientTimeoutSeconds` | `100` | Zeitlimit für einzelne HTTP-Aufrufe in Sekunden |
| `keyVaultUrl` | *(leer)* | Key-Vault-Secret-URL; ersetzt sämtliche übrigen Parameter |
| `logCreateRequests` | `false` | Protokolliert die vollständigen Anfragen beim Anlegen |
| `logUpdateRequests` | `false` | Protokolliert die vollständigen Anfragen beim Aktualisieren |
| `logReceivedData` | `false` | Protokolliert die vollständigen Antwortdaten |

Die drei Diagnose-Schalter erzeugen erhebliche Datenmengen und können Geschäftsdaten im
Klartext protokollieren — nur gezielt für die Dauer einer Analyse aktivieren.
Vollständige Beschreibung unter [Verbindungen](../../konfiguration/verbindungen/).

---

## Tabellen- und Feldnamen

- **SourceTable / TargetTable:** Name des OData-EntitySets, so wie er in `$metadata` steht
- **SourceField / TargetField:** Exakter Feldname aus der NAV-OData-API (case-sensitive)

---

## Unterstützte TargetKey-Typen

| Typ | Beschreibung |
|---|---|
| `PrimaryKey` | NAV-nativer Primärschlüssel. Der Wert wird in Anführungszeichen gesetzt. |
| `Id` | Systemeigene ID. Der Wert wird **ohne** Anführungszeichen eingesetzt. |
| `CustomKey` | Benutzerdefinierter Schlüssel über ein oder mehrere Felder |
| `Filter` | Suche über Feldwert-Kombination |

Bei `CustomKey` werden die Metadatentypen `int32` und `string` unterstützt, bei `Filter`
die Typen `string` und `guid`. Jeder andere Typ des Schlüsselfeldes führt zum Abbruch
(`Metadata type … not yet implemented for CreateKeyString`).

> **Kein `StaticValue` in NAV-Schlüsseln**
>
> Die für [D365BC](../d365bc/) ab v2.1 verfügbaren statischen Schlüsselwerte gibt es im
> NAV-Konnektor nicht. Jeder Schlüsselteil muss über `attributeName` auf ein Quellfeld
> verweisen. Ein `KeyValue`, das nur `StaticValue` enthält, führt beim Verarbeiten zu einem
> Fehler, weil der Zugriff auf das Quellattribut ins Leere läuft.



---

## SourceOperations

### LookupValue

Liest einen Wert aus einer anderen NAV-Tabelle nach — Aufbau und Parameter wie beim
[D365BC-Konnektor](../d365bc/).

```json
{
  "Operations": [
    {
      "Name": "LookupValue",
      "Parameters": {
        "LookupType": "Attribute",
        "SourceField": "countryRegionCode",
        "LookupTable": "CountryRegions",
        "LookupField": "Name",
        "UseCache": true
      }
    }
  ]
}
```

Unterstützt wird ausschließlich `LookupType: Attribute`. Der Wert `Name` führt zu einem
Abbruch (`SourceOperation for Lookups`).

### ReadFromMessage

Liest einen Wert aus der NAV-Antwort — **nur in ResponseJobs**. Das `SourceField` muss
einen `_`-Prefix haben. Verhalten wie bei D365BC.

---

## Datentypen — Zieltyp und akzeptierte Quelltypen

Beim Schreiben bestimmt der Datentyp des **Zielfeldes** aus den NAV-Metadaten, welche
Umwandlung angewendet wird.

| Zieltyp (NAV-Metadaten) | Akzeptierte Quelltypen | Verhalten und Sonderfälle |
|---|---|---|
| `Boolean` | `boolean`, `string` | Leerwert → `null`. Ein nicht als Wahrheitswert lesbarer Text führt zum Abbruch. |
| `Date` | `date`, `datetime`, `string` | Ausgabe im Format `yyyy-MM-dd`. Leerwert → `0001-01-01`. |
| `DateTimeOffset` | `date`, `datetime`, `string` | Ausgabe im Format `yyyy-MM-ddTHH:mm:ss.fffZ`. Leerwert → `0001-01-01T00:00:00.000Z`. |
| `Decimal` | `decimal`, `money`, `double` | Interpretation mit der Kultur aus `language`. Leerwert → `null`. |
| `Decimal` | `string` *(ab v2.1)* | Interpretation **immer** als `en-US` (Punkt als Dezimaltrennzeichen), unabhängig von `language`. |
| `Double` *(ab v2.1)* | `decimal`, `money`, `double` | Interpretation mit der Kultur aus `language`. **`string` wird nicht akzeptiert** und führt zum Abbruch. |
| `Guid` | `guid`, `string`, `entityreference` | Leerwert → `00000000-0000-0000-0000-000000000000`, **nicht** `null`. |
| `Int32` | `int32`, `optionsetvalue`, `string` | Leerwert → `null`. Nicht als Ganzzahl lesbarer Wert → Abbruch. |
| `String` | alle Quelltypen | Wert wird getrimmt. Leerwert → **`null`**. Liegt eine `OptionMapping`-TargetOperation vor, wird stattdessen der zugeordnete Wert geschrieben; ein unbekannter Quellwert führt zum Abbruch. |

Jeder in der Tabelle nicht genannte NAV-Zieltyp führt beim Schreiben zu einem Abbruch
(`No Resolver defined for edmPrimitiveTypeKind …`).

> **Leerer Textwert leert das Zielfeld nicht**
>
> Das ist der wichtigste Unterschied zu Business Central. Ein leerer Quellwert wird in NAV
> als `null` übergeben — das Zielfeld behält damit seinen bisherigen Inhalt. Soll ein Feld
> im Zielsystem tatsächlich geleert werden, lässt sich das über einen leeren Textwert
> **nicht** erreichen.



---

## ResponseJob

Der NAV-Konnektor unterstützt das ResponseJob-Muster wie D365BC: Nach erfolgreichem
Schreiben in NAV kann ein ResponseJob ausgelöst werden, der Felder aus der NAV-Antwort
(z. B. neu vergebene Nummern) zurück ins Quellsystem schreibt. Aufbau und Konfiguration
sind unter [D365BC → ResponseJob](../d365bc/) beschrieben.

---

## Änderungserkennung (Watermark)

| Eigenschaft | Wert |
|---|---|
| Empfohlener WatermarkType | `datetime` oder `date` |
| Typisches WatermarkField | Systemabhängig — z. B. `Last_Date_Modified`, `Timestamp` |
| Filterformat | `{{WatermarkField gt %watermark%}}` |

Im Gegensatz zu Business Central gibt es kein einheitliches `lastModifiedDateTime`-Feld.
Das korrekte Watermark-Feld hängt von der NAV-Version und der verwendeten Seite bzw.
Codeunit ab. Im Zweifelsfall mit dem NAV-Administrator klären.

Der Filterausdruck aus dem Job wird als OData-`$filter` an die NAV-Anfrage angehängt.
Die Regeln zur Klammerung und zum Platzhalter `%watermark%` sind unter
[Jobs → Filter-Syntax](../../konfiguration/jobs/) beschrieben.

---

## Fehlersuche

Fehler beim Schreiben werden mit dem Text **`Error in NAV-Communication`** protokolliert,
zusammen mit der verwendeten relativen Adresse sowie dem neuen und dem bestehenden
Datensatz. Bis einschließlich v2.0 lautete derselbe Text irreführend
`Error in BC-Communication` — ältere Logeinträge einer NAV-Verbindung sind also trotz
BC-Nennung dem NAV-Konnektor zuzuordnen.
