Willkommen bei der Einrichtungshilfe für das orderbase PlanningBoard!

Wenn bei der Einrichtung Schwierigkeiten auftreten, kontaktieren Sie uns gern.

Telefon: 0251 20 750 0
Mail: service@orderbase.de

Inhalt

Einbinden des PlanningBoards in ein BC-System..

Download
Assisted Setup
Zentrale Steuerungsinstanz
Umgang mit http-Anfragen

Board Einrichtung

Ladehorizont
Initialisierung von Daten
Initialisiert PB Benutzerauthentifizierungs E-Mail
Initialisieren des Sortierindex für Artikel
Berechtigungen für aktuellen Benutzer setzen
PlanningBoard Engine
Lizenz hochladen

Konfigurieren der Entra-Applikation
Anlegen mit Skript
Anlegen der Applikation ohne Skript
Registrierung
API-Berechtigungen
Authentifizierung
Zertifikat und Geheimnisse (Secret)

Microsoft Entra-Anwendungen
Rechte

Noch ein paar letzte Schritte bevor es losgehen kann…

Benutzer Einrichtung

Allgemeine Einstellungen

Planningboard
Lager
Starten des PlanningBoards
Vorlagen Importieren
Skripttext

Einbinden des PlanningBoards in ein BC-System

Download

Sie können das orderbase PlanningBoard in einer Testversion über den Microsoft AppSource in Ihre Microsoft Dynamics 365 Business Central Umgebung herunterladen. Die Installation der App erfolgt automatisch.

Assisted Setup

Folgend können Sie in den „PlanningBoard-Einstellung“ die unterstütze Einrichtung durchführen. In der Einrichtung sind Standardeinstellungen hinterlegt, die Sie bei Bedarf anpassen können.

Die Schritte bestimmen:

Zentrale Steuerungsinstanz

Umgang mit http-Anfragen

http-Anfragen müssen erlaubt sein (haken setzen), damit das PlanningBoard mit BusinessCentral interagieren kann. Z.b kann dann nicht zurückgespeichert werden.

Board Einrichtung

Die Seite dient der Einrichtung und Initialisierung wichtiger Werte.

Im Folgenden werden die einzelnen Bereiche erklärt:

Ladehorizont

Der Ladehorizont bestimmt die Zeitspanne, die für das PlanningBoard geladen wird, also die Zeitspanne der Daten, die Sie sehen. Bitte bedenken Sie, dass ein längerer Ladehorizont eine längere Ladezeit bedeuten kann. Den Ladehorizont können Sie später in der PlanningBoard-Oberfläche anpassen.

Initialisierung von Daten

Mit dieser Einstellung werden alle Übertragungstabellen an das PlanningBoard gelöscht und neu aufbereitet. Auch diese Initialisierung kann später erneut durchgeführt werden.

Initialisiert PB Benutzerauthentifizierungs E-Mail

Initialisiert alle Benutzereinstellungen, bei denen keine PB Benutzerauthentifizierungs E-Mail angegeben ist. Diese wird zur Anmeldung im Planningboard benötigt und befindet sich in den „Benutzer Einrichtungen“ im BC.

Initialisieren des Sortierindex für Artikel

Ist diese Einstellung gesetzt, werden die Artikel anhand des Artikelcode durchnummeriert. Der Sortierindex kann auf der Artikelkarte angepasst werden. Wird diese Einstellung nicht gesetzt, werden die Artikel ausschließlich alphanummerisch nach Namen sortiert.

Berechtigungen für aktuellen Benutzer setzen

Benutzerberechtigungen für den aktuellen Benutzer auf „Alle“ setzen.

PlanningBoard Engine

Diese Einrichtungsseite stellt eine Verbindung zu Engine her. Wenn Sie keine anderen Informationen erhalten und das PlanningBoard testen möchten, verwenden Sie bitte die hier eingetragenen Adressen.

Lizenz hochladen

Hier müssen Sie nun die Lizenz einfügen, damit das PB gestartet werden kann.
Ist die Lizenz eingefügt, brauchen Sie nur noch auf „Beenden“ klicken.

Info: Die Demo-Lizenz ist für 2 Wochen gültig, danach benötigen Sie eine neue Lizenz.

Konfigurieren der Entra-Applikation

Für diesen Teil der Einrichtung ist es notwendig, administrative Berechtigungen zu haben.
Bitte wenden Sie sich ggfs. an Ihren Systemadministrator.


WICHTIG: Lesen Sie zuerst alle Einrichtungsschritte, bevor sie fortfahren.

Anlegen mit Skript

Um die nächsten Einrichtungsschritte einfach zu gestalten, ist dem PlanningBoard ein Skript beigelegt, das die Konfiguration der Entra-Applikation für Sie übernimmt.

Dieses können Sie über den „Assist“- Button herunterladen.

Damit Sie es sicher herunterladen und öffnen können, wird das Skript als .download Datei heruntergeladen. Um es zu nutzen ist es notwendig, eine Umbenennung in .ps1 durchzuführen.

Wenn Sie sich dabei unsicher sind, das Skript auszuführen, können Sie sich gern bei uns melden, wir helfen Ihnen oder Ihrem Admin gern bei der händischen Einrichtung. Den Inhalt des Skripts finden Sie am Ende dieses Dokuments.

Das Skript durchläuft folgende Schritte:

  • App-Registrierung anlegen
  • Authentifizierungen konfigurieren
  • Zertifikate und Geheimnisse anlegen
  • API Berechtigungen verwalten

Nachdem Sie das Skript ausgeführt haben, kopieren Sie bitte die Informationen in Ihrer Zwischenablage direkt in das dafür vorgesehene Fenster (s.o.: Replace with….). Die Einrichtung ist damit abgeschlossen.

Wichtig: Merken Sie sich das Secret(Geheimnis) bzw. speichern Sie es sicher ab. Sie können es ab jetzt nicht mehr einsehen.

Wenn Sie sich für das Skript entschieden haben, springen Sie bitte zum Punkt Microsoft Entra-Anwendungen. Folgend ist die manuelle Erstellung der Azur-App beschreiben

Anlegen der Applikation ohne Skript

Wenn Sie die Applikation ohne Skript anlegen möchten, ist es ebenfalls notwendig, einen Administrationszugriff auf die Microsoft Azure-Einrichtungen zu haben, spezifisch die App Registrierungen.

Registrierung

Legen Sie eine neue Registrierung an und benennen Sie diese z.B „orderbase PlanningBoard“.

Als nächstes wählen Sie unter „Unterstützte Kontotypen“ den Punkt „nur Konten in Ihrem Organisationsverzeichnis“ aus.

Schließen Sie die Registrierung ab.

API-Berechtigungen

Konfigurieren Sie dann API-Berechtigungen. Sie benötigen „Microsoft Graph“-Berechtigungen und „Business Central“-Berechtigungen in folgender Konfiguration:

Information: Die Graph-Berechtigung dient dazu, in BC die Entra-App Registrierung durchzuführen. Wenn diese abgeschlossen ist, können Sie die Berechtigung wieder entfernen.

Authentifizierung

Fügen Sie im Menüpunkt „Authentifizierung“ eine Web-Plattform mit folgender Konfiguration hinzu:

https://businesscentral.dynamics.com/OAuthLanding.htm

Zertifikat und Geheimnisse (Secret)

Im nächsten Schritt müssen Sie ein Zertifikat erstellen. Erstellen Sie dafür ein neues Geheimnis, fügen Sie eine Beschreibung und ein Ablaufdatum hinzu und kopieren Sie den Wert aus der Tabelle.

Das Geheimnis ist, nach Verlassen der Seite, nicht mehr kopierbar oder einsehbar. Wir empfehlen Ihnen das Geheimnis in einem sicheren Ort zu speichern.

Microsoft Entra-Anwendungen

Wechseln Sie jetzt wieder in Ihr Business Central-System und öffnen Sie die Microsoft Entra-Anwendungen und wählen Sie die PlanningBoard-Integration aus. Diese wird automatisch angelegt, wenn Sie die vorherigen Schritte ausgeführt haben. Bitte prüfen Sie die Client Id. Diese sollte identisch sein mit der Client Id aus der Entra-Applikation.

Unter Extention wählen Sie bitte die „orderbase PlanningBoard – Integration with Custom Web Service“-App aus.

Rechte

Die Anwendung benötigt folgende Rechte:

  • D365 BUS FULL ACCESS
  • D365PREM MFG, EDIT
  • OCG PBIC CUSTOM WS
  • OCG PBM MANUFACT.

Stellen Sie den Status auf „Aktiviert“. Nun muss noch ein Benutzer mir Administrationsrechten die „Zustimmung erteilen“.

Noch ein paar letzte Schritte bevor es losgehen kann

Benutzer Einrichtung

In den Benutzereinrichtungen muss zum einen die „PB Benutzerauthentifizierungs Email“ (dies ist der Anmeldename), als auch die „oc Berechtigungen PB Produktion“ gefüllt sein

Allgemeine Einstellungen

Einrichtungen für „Benutzer Webservice“

Planningboard

In den „General Settings“ muss der Engine und Client, sowie die Entra App Registration hinterlegt sein.

Lager

In der Einrichtung „Lager“ muss ein Lagerort hinterlegt sein. Wenn kein Lagerort vorhanden ist, sollte hier der Default Lagerortcode (undefined) hinterlegt werden. Dies dient ausschließlich zur Anzeige.

Hiermit ist die Einrichtung abgeschlossen.

Starten des PlanningBoards

Anschließend können Sie das PlanningBoard starten und Ihre Daten darin sehen und anpassen.

Sie finden es auf der Startseite der Rolle „Produktionsleiter“. Sollten Sie Ihre Daten noch nicht sehen, versuchen Sie, das Board einmal zu neu zu Initialisieren über Settings -> Board.

Vorlagen Importieren

Damit Sie die volle „user expirience“ des PlanningBoards bekommen, empfehlen wir Ihnen, folgende Einstellung im BC für das Board vorzunehmen:

Gehen Sie auf die Board Karte. Öffnen Sie unter dem Punkt „Aktionen“ die Vorlagen

Anschließend gehen Sie auf dem Menüpunkt „Zugehörig à Vorlagen importieren“

Hier wird die Vorlage mit der Sprache importiert, die unter „Meine Einstellungen à Sprache“ ausgewählt wurde.
Sonst ansonsten werden nur die Defaults gezogen.

Skripttext:

# Function to check if the script is running with elevated privileges

function Test-Admin {

$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())

return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

}

# Function to install the MSAL.PS module if not available

function Install-MsalModule {

if (-not (Get-Module -ListAvailable -Name MSAL.PS)) {

Write-Host „Installing MSAL.PS module…“ -ForegroundColor Yellow

Install-Module MSAL.PS -Force -Scope CurrentUser

Write-Host „MSAL.PS module installed successfully.“ -ForegroundColor Green

# Restart the script after installing the module

Start-Process powershell -ArgumentList „-NoProfile -ExecutionPolicy Bypass -File `“$PSCommandPath`““ -Verb RunAs

exit

}

Write-Host „MSAL.PS module is available.“ -ForegroundColor Green

}

# Function to get required resource access configuration

function Get-RequiredResourceAccess {

return @(

@{

resourceAppId = „00000003-0000-0000-c000-000000000000“ # Microsoft Graph

resourceAccess = @(

@{

id = „1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9“ # Application.ReadWrite.All

type = „Role“

}

)

},

@{

resourceAppId = „996def3d-b36c-4153-8607-a6fd3c01b89f“ # Dynamics 365 Business Central

resourceAccess = @(

@{

id = „a42b0b75-311e-488d-b67e-8fe84f924341“ # API.ReadWrite.All

type = „Role“

}

)

}

)

}

# Function to check API permissions and admin consent

function Check-ApiPermissions {

param (

[string]$appObjectId,

[hashtable]$headers

)

$status = @{

MissingPermissions = $false

MissingConsent = $false

Details = @()

}

# Get current permissions

$currentApp = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications/$appObjectId“ -Headers $headers -Method Get

$requiredAccess = Get-RequiredResourceAccess

# Get service principal to check admin consent

$servicePrincipal = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/servicePrincipals?`$filter=appId eq ‚$($currentApp.appId)'“ -Headers $headers -Method Get

foreach ($required in $requiredAccess) {

$currentResource = $currentApp.requiredResourceAccess | Where-Object { $_.resourceAppId -eq $required.resourceAppId }

if (-not $currentResource) {

$status.MissingPermissions = $true

$status.Details += „Missing permissions for resource: $($required.resourceAppId)“

continue

}

foreach ($access in $required.resourceAccess) {

$hasPermission = $currentResource.resourceAccess | Where-Object { $_.id -eq $access.id }

if (-not $hasPermission) {

$status.MissingPermissions = $true

$status.Details += „Missing permission ID: $($access.id)“

}

# Check admin consent if permission exists

if ($hasPermission) {

$spOauth2PermissionGrants = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/servicePrincipals/$($servicePrincipal.value[0].id)/oauth2PermissionGrants“ -Headers $headers -Method Get

if (-not $spOauth2PermissionGrants.value) {

$status.MissingConsent = $true

$status.Details += „Missing admin consent for permission ID: $($access.id)“

}

}

}

}

return $status

}

# Function to check secret status

function Check-Secret {

param (

[string]$appObjectId,

[hashtable]$headers

)

$app = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications/$appObjectId“ -Headers $headers -Method Get

$currentSecrets = $app.passwordCredentials

$status = @{

HasValidSecret = $false

SecretId = $null

ExpiryDate = $null

}

if ($currentSecrets) {

$validSecret = $currentSecrets | Where-Object {

$endDateTime = [DateTime]::Parse($_.endDateTime)

$endDateTime -gt (Get-Date)

} | Select-Object -First 1

if ($validSecret) {

$status.HasValidSecret = $true

$status.SecretId = $validSecret.keyId

$status.ExpiryDate = $validSecret.endDateTime

}

}

return $status

}

# Main script execution

if (-not (Test-Admin)) {

Write-Host „Requesting administrative privileges…“ -ForegroundColor Yellow

Start-Process powershell -ArgumentList „-NoProfile -ExecutionPolicy Bypass -File `“$PSCommandPath`““ -Verb RunAs

exit

}

Install-MsalModule

Import-Module MSAL.PS

# Configuration

$config = @{

TenantId = „f0751b63-c782-40b3-8e04-f4cd345f1e23“

ClientId = „1950a258-227b-4e31-a9cf-717495945fc2“

Scope = „https://graph.microsoft.com/.default“

AppDisplayName = „orderbase PlanningBoard Integration“

RedirectUri = „https://businesscentral.dynamics.com/OAuthLanding.htm“

SecretDisplayName = „Orderbase PlanningBoard Engine Access“

SecretExpiry = (Get-Date).AddYears(2).ToString(„yyyy-MM-ddTHH:mm:ssZ“)

}

# Initialize status tracking

$statusTracker = @{

NeedsPortalAccess = $false

SecretStatus = @{

Created = $false

Existing = $false

Error = $false

Message = „“

}

}

# Get authentication token

Write-Host „Authenticating…“ -ForegroundColor Yellow

$tokenResponse = Get-MsalToken -ClientId $config.ClientId -TenantId $config.TenantId -Scopes $config.Scope -Interactive

$headers = @{ Authorization = „Bearer $($tokenResponse.AccessToken)“ }

# Check if app registration exists

$existingAppResponse = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications?`$filter=displayName eq ‚$($config.AppDisplayName)'“ `

-Headers $headers -Method Get

if ($existingAppResponse.value.Count -gt 0) {

$appId = $existingAppResponse.value[0].appId

$appObjectId = $existingAppResponse.value[0].id

Write-Host „Found existing app registration ‚$($config.AppDisplayName)‘ (App ID: $appId)“ -ForegroundColor Green

# Check API permissions and consent status

$permissionStatus = Check-ApiPermissions -appObjectId $appObjectId -headers $headers

if ($permissionStatus.MissingPermissions) {

Write-Host „Missing API permissions detected. Attempting to add…“ -ForegroundColor Yellow

$updatePayload = @{

requiredResourceAccess = Get-RequiredResourceAccess

} | ConvertTo-Json -Depth 10

try {

Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications/$appObjectId“ `

-Headers $headers -Method Patch -Body $updatePayload -ContentType „application/json“

$statusTracker.NeedsPortalAccess = $true

}

catch {

Write-Host „Error updating permissions: $($_.Exception.Message)“ -ForegroundColor Red

$statusTracker.NeedsPortalAccess = $true

}

}

if ($permissionStatus.MissingConsent) {

Write-Host „Admin consent required for some permissions.“ -ForegroundColor Yellow

$statusTracker.NeedsPortalAccess = $true

}

}

else {

# Create new app registration

$appRegistrationPayload = @{

displayName = $config.AppDisplayName

signInAudience = „AzureADMyOrg“

web = @{

redirectUris = @($config.RedirectUri)

}

requiredResourceAccess = Get-RequiredResourceAccess

} | ConvertTo-Json -Depth 10

try {

$newAppResponse = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications“ `

-Headers $headers -Body $appRegistrationPayload -Method Post -ContentType „application/json“

$appId = $newAppResponse.appId

$appObjectId = $newAppResponse.id

Write-Host „Created new app registration (App ID: $appId)“ -ForegroundColor Green

$statusTracker.NeedsPortalAccess = $true

}

catch {

Write-Host „Error creating app registration: $($_.Exception.Message)“ -ForegroundColor Red

exit 1

}

}

# Check existing secrets

$secretStatus = Check-Secret -appObjectId $appObjectId -headers $headers

if ($secretStatus.HasValidSecret) {

Write-Host „Valid secret found (ID: $($secretStatus.SecretId)) expires on $($secretStatus.ExpiryDate)“ -ForegroundColor Green

$statusTracker.SecretStatus.Existing = $true

$statusTracker.SecretStatus.Message = „Existing secret ID: $($secretStatus.SecretId)“

}

else {

# Create a new secret

try {

$secretPayload = @{

passwordCredential = @{

displayName = $config.SecretDisplayName

endDateTime = $config.SecretExpiry

}

} | ConvertTo-Json -Depth 10

$secretResponse = Invoke-RestMethod -Uri „https://graph.microsoft.com/v1.0/applications/$appObjectId/addPassword“ `

-Headers $headers -Body $secretPayload -Method Post -ContentType „application/json“

$statusTracker.SecretStatus.Created = $true

$statusTracker.SecretStatus.Message = „New secret created successfully“

}

catch {

$statusTracker.SecretStatus.Error = $true

$statusTracker.SecretStatus.Message = „Failed to create secret: $($_.Exception.Message)“

Write-Host „Error creating secret: $($_.Exception.Message)“ -ForegroundColor Red

}

}

# Prepare output

$output = @{

appId = $appId

expireDate = if ($secretStatus.HasValidSecret) { $secretStatus.ExpiryDate } elseif ($statusTracker.SecretStatus.Created) { $config.SecretExpiry } else { $null }

secretValue = if ($statusTracker.SecretStatus.Created) { $secretResponse.secretText } else { „“ }

} | ConvertTo-Json -Depth 10

# Copy to clipboard and display

Set-Clipboard -Value $output

Write-Host „`nApp Registration details have been copied to clipboard:“ -ForegroundColor Green

Write-Host $output

# Open Azure Portal if needed

if ($statusTracker.NeedsPortalAccess) {

$appPortalLink = „https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/$appId/isMSAApp/“

Write-Host „`nOpening Azure Portal for permission review and consent…“ -ForegroundColor Yellow

Start-Process $appPortalLink

}

Read-Host -Prompt „Press Enter to exit“