Mastodon HermanRonk.nl - Pagina 2 van 10 -

Tesla Model 3 VIN status met Azure Logic Apps

Als je je droomauto mag bestellen moet je vaak wachten tot je deze daadwerkelijk in ontvangst mag nemen. Bij Tesla is dat wachten een “beetje” een black box, dus wat doe je dan om de tijd te verdrijven? Inderdaad.. kijken hoe je Microsoft Azure kan toepassen op dat wachtproces šŸ˜‰

Voor wie niet bekend is met het bestellen van een Tesla zal ik eerst kort opsommen hoe dat proces ongeveer gaat (in het geval van een leasemaatschappij):

  1. Je regelt intern de order en deze gaat naar de leasemaatschappij
  2. De leasemaatschappij bestelt daadwerkelijk de auto bij Tesla en doet de aanbetaling
  3. Je ontvangt een mailtje “Welkom bij de Tesla familie” en mag een account aanmaken
  4. Je krijgt een RN nummer en als je geluk hebt een leverindicatie
  5. Vervolgens is eerst alleen in de broncode het serienummer (VIN) van je auto zichtbaar
  6. Het serienummer is zichtbaar op je profiel pagina
  7. Je krijgt een leverdatum aangeboden
  8. Je mag je auto ophalen
Tesla bestelling overzicht. (goed irritant dat de kleur van het interieur op het plaatje niet klopt :()
Beetje jammer dat de interieurkleur niet overeen komt met de kleur in de bestelling šŸ™

Stap 1 tot 4 gaan redelijk vanzelf, en dan begint het kijken naar sheets zoals deze om te zien wanneer er weer een schip/shit-load aan Tesla Model 3’s deze kant op komen, in de hoop dat die van jou daar ook bij staat en je dus een serienummer toegekend krijgt.

Het vervelende is echter dat je dus iedere keer (als je een beetje ongeduldig bent, zoals de gemiddelde Tesla besteller) met de hand in de source moet zoeken of er een VIN beschikbaar is (of je gebruikt een Chrome plugin)

Automatiseren die hap

Alles wat of vervelend is om te doen, of je meer dan eens moet doen moet je proberen te automatiseren, en gelukkig zijn er dan oplossingen als Azure Logic Apps om dat te realiseren.

Tesla heeft een API beschikbaar waar je met je account gebruik van kan maken, er is niet echt officiele documentatie van, maar zoals vaker heeft dat het internet er niet van weerhouden er toch gebruik van te maken.

De stappen die we gaan doorlopen:

  1. Een autorisatie token genereren met je Tesla account
  2. Een Azure Logic App bouwen die ieder uur:
    1. Een webrequest doet bij Tesla
    2. Het webrequest interpreteert en een als dan functie uitvoert
    3. Je een mailtje stuurt bij goed nieuws

Ik heb eigenlijk alleen Postman gebruikt voor het maken van de initiele requests, maar met de code voorbeelden hier onder kan je als het goed is zelf wel uit de voeten zonder het gebruik van Postman.

Door wat tijdgebrek ben ik er niet aan toe gekomen om een generator te maken voor je autorisatie token, dus dat moet voor nu nog met de hand middels postman. Je kan eventueel ook een externe website gebruiken voor het genereren van je token, zoals bijvoorbeeld deze.

Autorisatie token genereren

Je kan je (Oauth) autorisatie token ophalen door de onderstaande stappen te volgen. Samengevat gaan we een API call doen om met je inloggegevens een token te genereren.

Als je Postman geopend hebt kies je voor “New request”:

Postman "Create New" menu
Postman – New Request

Je moet het request een naam geven en toevoegen aan een “Collection”, je kan hier een bestaande kiezen of een nieuwe aanmaken.

Postman save request menu
Postman – New request details

Als je een nieuw request aangemaakt hebt krijg je onderstaand scherm te zien (alleen dan nog leeg):

Postman request editor
Postman request
  1. Pas het type request aan naar een “POST”
  2. Voer de volgende URL in: https://owner-api.teslamotors.com/oauth/token
  3. Maak de volgende parameters aan en vul de value’s
    1. grant_type – password
    2. client_id – De waarde voor dit veld vind je hier: https://pastebin.com/pS7Z6yyP en de toelichting hier: https://tesla-api.timdorr.com/api-basics/authentication
    3. client_secret – De waarde voor dit veld vind je hier: https://pastebin.com/pS7Z6yyP en de toelichting hier: https://tesla-api.timdorr.com/api-basics/authentication
    4. email – het email adres van je Tesla account
    5. password – het wachtwoord van je Tesla account
  4. Druk vervolgens op Send

Je krijgt nu een response te zien die er grofweg zo uit ziet:

{
    "access_token": "****",
    "token_type": "bearer",
    "expires_in": 3888000,
    "refresh_token": "****",
    "created_at": 1568872567
}

Het access_token heb je in de volgende stappen nodig.

LET OP: Het token dat je hier aanmaakt (en je login gegevens sowieso) geven controle over veel meer dan alleen de data die we nu ophalen, ook zodra je je auto eenmaal hebt kan dit token gebruikt worden voor bijvoorbeeld het openen van de deuren.. Zorg er dus voor dat je zorgvuldig om gaat met het token. Tokens zijn momenteel 30 dagen houdbaar en moeten dan vervangen worden (zie daarvoor de documentatie)

Azure Logic App aanmaken

Logic apps kosten (zoals veel services op Azure als je ze goed gebruikt) zo ongeveer niks, en zeker niet als je het voor dit doel gebruikt. Als het wachten een beetje mee zit zou je zelfs in je trial account genoeg dagen gratis gebruik moeten hebben zitten om daarmee de wachttijd uit te zitten.

Als je nog geen account hebt kan je deze aanmaken via portal.azure.com, als je wel al een account hebt kan je daar inloggen en in de zoekbalk zoeken naar “Logic Apps”

Azure overzicht
Azure Logic Apps

Op de volgende pagina kan je vervolgens middels “Add” een nieuwe logic app aanmaken:

Azure logic apps
Logic app overzicht

Het aanmaken van de lege Logic App is in tegenstelling tot sommige andere Microsoft Azure onderdelen relatief eenvoudig:

Logic App aanmaken interface
Logic App Aanmaken

Je voert een naam in, kiest een subscription en een bestaande of nieuwe resource group (een bundel gerelateerde services en onderdelen) en kiest tot slot een locatie, waarbij het zinnig is een locatie zo dicht mogelijk bij je eigen locatie te kiezen.

Het aanmaken zelf duurt vervolgens even (1-2 minuten, verwaarloosbaar in Tesla-tijd), maar na een tijdje zie je je gloednieuwe Logic App in de lijst staan:

Azure Logic App overzicht
Logic App overzicht na aanmaken App

Je kan hier vervolgens op klikken en zal dan naar de design view gestuurd worden waar we de logic app kunnen gaan inrichten.

Azure Logic App configureren

In het eerste overzicht dat je krijgt zie je allerlei templates staan. Deze zijn leuk om eens mee te experimenteren, maar voor deze app kiezen we voor een “Blank Logic App”

Lege logic app template
Een leeg template

De eerste stap die je vervolgens zet is het bepalen van een trigger. De trigger bepaalt wanneer het proces in de Logic App moet starten. Je hebt hier een grote hoeveelheid opties die interessant zijn om te bekijken. In dit geval kiezen we voor de “Schedule” optie, en vervolgens voor recurring (oftewel, starten op basis van een timer):

Logic app recurrence
Logic App trigger

De vervolgstap is het invoegen van de daadwerkelijke actie waar het proces mee moet beginnen. In ons geval gaan we een “GET” actie uitvoeren tegen de Tesla API. We geven hierbij een autorisatie header mee met het Autorisatie token dat we eerder in deze post aangemaakt hebben met ons account.

Voor het toevoegen van deze stap zoeken we naar HTTP, en kiezen voor de HTTP actie, je krijgt dan een veld zoals hier onder:

Logic app http request
HTTP Request opbouwen

De waardes die je hier invult:

  • Method: GET
  • URI: https://owner-api.teslamotors.com/api/1/vehicles
  • Headers: Authorization | Bearer “token zoals eerder gegenereerd”

Wat deze stap doet is het webrequest opbouwen dat volgens het schema dat we eerder samengesteld hebben aangeroepen wordt.

De volgens stap is het oppakken van het resultaat van het webrequest dat we hiervoor aangemaakt hebben. We gaan het resultaat omzetten naar een JSON object, dat is niet per definitie nodig voor de werking zoals de app nu is, maar bied wel meer mogelijkheden voor de toekomst en is een kleine moeite.

Voeg een action toe en zoek naar “Parse JSON”. Je krijgt een blok te zien zoals hier onder:

Logic app JSON parser
Parse JSON configuratie

Klik hier eerst in het “Content” vak (1) en vervolgens in het Dynamic Content veld onder HTTP (eventueel even op klikken als je geen opties ziet) op “Body” (2). Tot slot klik je dan op ” Use Sample Payload to generate schema ” (3) en voer deze code in:

{
    "response": [],
    "count": 0
}

Er zal een schema gegenereerd worden waar we later naar refereren.

De volgende stap is een stukje “Als, dan” logicia om te zorgen dat je alleen een bericht ontvangt als er een VIN gekoppeld is aan je account. Je zoekt hiervoor naar de actie “Control” en kiest vervolgens voor “Condition”:

Logic app controller / condition
Condition Operators

De eerste stap die we hier zetten is de werkelijke vergelijking bepalen. In her eerste veld klikken we en kiezen we in de “Dynamic” content voor de waarde “Count”. Deze stap is iets makkelijker geworden door het schema dat we hier voor toegevoegd hebben, anders had je dat veld hier handmatig moeten specificeren.

Als de “Count” waarde niet gelijk is aan 0 is er dus blijkbaar een auto toegevoegd aan je account, dus dan gaan we in de volgende stap een “If true” actie instellen. Klik hiervoor op “Add an action” in het “If true” blok. Vervolgens zoek je naar “Send email”, in mijn geval kies ik hier voor Office 365 en vervolgens opnieuw voor “Send Email”, je mag vervolgens inloggen:

Logic app mailer connector
O365 Sign In

Na het inloggen kan je de mail opmaken, je kan hierbij elementen gebruiken uit alle eerdere stappen, deze zijn beschikbaar als dynamic content. Ik heb het niet al te moeilijk gemaakt en gewoon de hele HTTP response gepakt, als de auto eenmaal gekoppeld is maakt het me niet zo veel meer uit dat het mailtje niet zo mooi is ;). Als het menu bij Dynamic Content leeg blijft moet je even op “See more” klikken.

Logic app mail
Logic App mail

Uiteindelijk heb je dan iets zoals hier onder:

Logic app totaaloverzicht
Logic App overzicht

Als je hier eerst nog op “Save” (1) en vervolgens op “Run” (2) klikt zal de app eerst een keer zichtbaar draaien en vervolgens ieder uur op de achtergrond (volgens het eerder ingestelde schema). Je kan op deze pagina meteen zien wat er in iedere stap gebeurt is en wat het resultaat is geweest. Als het “goed” is zal je geen mail krijgen omdat er nog geen gekoppelde auto is. Als je zeker wil weten dat alles naar behoren werkt zou je ook een bericht kunnen koppelen aan de “If false” branch, maar dat is normaal gezien eigenlijk niet nodig.

Wachten

Als de logic app eenmaal draait merk je daar doorgaans niets van (tot je goed nieuws krijgt). Als je dan toch de status wil zien kan je de logic app op de Azure Portal opzoeken en open klikken. Je ziet dan altijd een overzicht van de keren dat de app gelopen heeft en de resultaten van iedere run:

Logic app history
Azure logic app history

Verder rest er nu dan niets meer dan wachten tot de mail komt.

Tot slot

Echt heel erg zinnig is deze logic app natuurlijk niet, maar het is wel een (erg simpele) introductie tot een zeer krachtig Microsoft Azure onderdeel wat eindeloos veel toepassingen kent en eigenlijk voor iedereen relatief goedkoop beschikbaar is.

koppeling AFAS Profit & Microsoft Azure & Power BI

De eerdere posts waren gericht op het live (of near live) ontsluiten van data uit AFAS Profit naar een Power BI rapport. Alhoewel dit erg goed werkt voor rapporten waarbij de data zo live mogelijk moet zijn is het niet de beste optie als performance belangrijker is dan de meest actuele data. Zeker in de gevallen waarbij je de data maar eens per dag of nog minder hoeft te verversen.

Voor dit scenario maken we van de volgende diensten gebruikt:

  • AFAS Profit (on-prem of AFAS Online)
  • Azure Automation
  • Azure (Blob) Storage
  • Microsoft Power BI

De kosten van de Azure storage zijn afhankelijk van het gebruik, maar normaal gezien zouden we het over maximaal enkele euro’s per maand moeten hebben. De precieze kosten van Azure Blob Storage vind je eventueel hier (https://azure.microsoft.com/nl-nl/pricing/details/storage/blobs/)

Het stappenplan bevat de volgende onderdelen:

  • Aanmaken getconnectoren AFAS Profit
  • Aanmaken app-connector AFAS Profit en genereren token
  • Aanmaken Azure Automation instance
  • Aanmaken Azure Blob Storage
  • Invoeren Automation Runbook
  • Koppelen Power BI rapport

Aanmaken getconnectoren AFAS Profit

Binnen AFAS Profit kan je middels het aanmaken van een getconnector data buiten het pakket beschikbaar stellen. Deze connector is na het uitvoeren van de volgende stap vai de REST API beschikbaar.

De belangrijkste keuze die je in deze stap moet maken (naast de te ontsluiten velden natuurlijk) is waar je de filtering van de data uit wil voeren. Het is altijd een goed idee om niet meer data beschikbaar te stellen dan strikt noodzakelijk. Het heeft dan ook mijn persoonlijke voorkeur om filters waarvan je zeker weet dat die nooit veranderen aan de Profit kant in te regelen en alle overige filters af te handelen in de scripts die de data ophalen (of Power BI zelf).

Hoe je een getconnector in AFAS Profit aanmaakt vind je hier. (https://help.afas.nl/help/NL/SE/App_Cnr_XML_Get_Build.htm)

Aanmaken app-connector AFAS Profit en genereren token

De getconnectoren die we in de vorige stap aangemaakt hebben moeten nu nog naar buiten toe bescchikbaar gesteld worden. In de onderstaande twee stukken heb ik uitgewerkt hoe je de connectoren kan toevoegen aan een App connector en hoe je de autorisatie tokens klaar kan maken voor gebruik:

Normaal gezien gebruik ik een systeem gebruiker (Binnen AFAS Profit) en een specifieke groep van connectoren zodat ik de autorisatie van deze user middels groep autorisatie in kan regelen.

Alle get-connectoren die je mee neemt in de app connector zullen worden gedownload. Je kan de lijst later dus ook nog uitbreiden. Als je de lijst wil inkrimpen zal je handmatig de json’s van de verwijderde connectoren moeten verwijderen uit je blob-storage.

Aanmaken Azure Automation instance

Tot dusver hebben we nog niets gedaan dat we in eerdere stappen niet ook al gedaan hebben. Voor de volgende stappen moeten we in de Azure omgeving een aantal dingen voorbereiden. Je kan als je nog geen account hebt via https://portal.azure.com een nieuw account aanmaken. De kosten van de onderdelen die we inzetten zijn we erg afhankelijk van hoeveel data we opslaan, maar normaal gezien zou het maar een paar euro per maand moeten zijn.

In de Azure portal kan je zoeken naar ā€œAzure Automationā€ je krijgt dan een optie om een Azure Automation Acocunt aan te maaken, als je dat onderdeel opent krijg je een beeld zoals hier onder:

Azure Automation menu

Klik hier op ā€œAddā€ om een nieuwe Azure Automation Instance aan te maken. Je krijgt een venster zoals hier onder te zien:

Azure Automation Account aanmaken

Je moet de instance een naam geven en eventueel aan een bestaande resource group koppelen, als je die nog niet hebt kan je die ook meteen even aanmaken. Tot slot moet je een regio kiezen, qua functionaliteit maakt het niet uit, maar het is sterk aan te raden om de dichtstbijzijnde regio te kiezen. In ons geval dus West Europa.

Als alles goed gegaan is krijg je uiteindelijk een venster zoals dit te zien:

Azure Automation overview

Om er voor te zorgen dat je alle acties uit kan voeren is het noodzakelijk om te zorgen dat de juiste modules geactiveerd zijn (via de modules knop kan je de lijst aanpassen). In ons geval is dit de lijst die we gebruiken:

Azure Automation Modules

Dit zijn er iets meer dan strikt noodzakelijk voor dit artikel maar dat is verder geen probleem. Let er wel op dat je deze modules af en toe zal moeten updaten.

Het aanmaken van het Automation Account kan even duren, je kan onderstussen aan de slag met de volgende stap, we maken het Automation Account verderop af.

Vanuit hier kunnen we verder met de voorbereidingen en gaan we een Storage account aanmaken.

Aanmaken Azure Blob Storage

In tegenstelling tot de directe koppelingen waar ik eerder over schreef maken we nu een tussenstap door de data in Azure Blob Storage te zetten. Dat komt de performance ten goede en bied ook een aanzienlijk aantal extra mogelijkheden als we meer met de data zouden willen doen.

Op de Azure portal zoeken we naar ā€œStorage Acocuntsā€. Als je daar op klikt krijg je een overzicht met de bestaande storage accounts. Indien nodig kan je nu zelf een nieuw acocunt aanmaken door op ā€œAddā€ te klikken

Microsoft Azure Storage Accounts

Over de gevraagde velden in, normaal gezien staat alles goed, let wel op de regio waar je het storage account aanmaakt. Voor de beste performance houd je deze in dezelfde regio als je automation account.

Microsoft Azure Storage account aanmaken

Als het aanmaken gelukt is kan je de nieuw aangemaakte resource openen:

Micorosoft Azure Storage Account overview

Kies hier voor ā€œBlobā€ om de container aan te maken waar we de JSON files die uit de AFAS Profit connector komen op gaan slaan.

Microsoft Storage Blob aanmaken

Tot slot hebben we nog twee zaken nodig uit ons Azure Storage account. Allereerst hebben we het access token nodig. Deze kan je vinden door op de Azure Storage Acocunt overview pagina in het menu op ā€œAccess Keysā€ te klikken en key 1 of 2 te kopiĆ«ren.

Azure Storage acces keys

Vervolgens hebben we de URL nodig waarop je Blob beschikbaar is. Open daarvoor vanuit  de Azure Storage Acocunt overview pagina het ā€œBlobsā€ menu en open daar de Blob die we net aangemaakt hebben. Open daar vervolgens de properties en kopier de URL.

Microsoft Azure Storage Blob url

Invoeren Automation Runbook

De eerste stap die we moeten zetten in het Azure Automation account is het aanmaken van een runbook voor het draaien van het script. Ga hiervoor naar het runbook menu:

Azure Automation Runbook

Mogelijk staan hier een aantal voorbeeldscripts, die kan je verwijderen om het beeld wat overzichtelijker te maken. Vervolgens klik je op de ā€œnieuwā€ knop, en vul je de velden in. De naam die je het script geeft is niet zo van belang, maar zorg er voor dat ā€œtypeā€ op ā€œPowershellā€ staat:

Azure Automation aanmaken runbook

Vervolgens kan je het runbook bewerken om het script toe te voegen. Het script heb ik onder aan deze post staan en nog even toegelicht.

Azure Automation Runbook bewerken

Wanneer je de code ingevoerd hebt kan je op ā€œPublishā€ drukken, er is ook een save knop, maar het script draait altijd de laatste versie die gepubliceerd is, dus zeker voor de eerste keer opslaan is het van belang om ā€œPublishā€ te gebruiken.

Je kan nu terug gaan naar het runbook overzicht zoals hier onder, als je op het script klikt ga je na de status pagina van dat script/runbook. Als je hier op ā€œrunā€ drukt zal het script in de wachtrij gezet worden, je gaat dan naar een status pagina waar je de ā€œjobā€ kan bekijken.

Azure Automation Runbook overzicht
Azure Automation Job status

Als alles goed gegaan is zal de job naar completed springen en zie je geen errors. (mogelijk moet je even op refresh drukken). Je kan ondertussen ook de blob storage opnieuw openen en controleren of de files daar verschenen zijn.

Tot slot willen we nog een schema toevoegen om het script/runbook periodiek te draaien. Je kan in de runbook op ā€œScheduleā€ klikken:

Azure Automation Scheduling

Als je hier de stappen volgt kan je een script toevoegen dat bijvoorbeeld ieder uur of iedere dag draait:

Azure Automation Schedule aanmaken

Script

Je vind de code van het script hier (op Github, https://github.com/HermanRonk/ProfitExportToAzureBlob ), de nummers hier onder verwijzen naar de verschillende blokken in dat script.

  1. In het eerste blok worden de inloggegevens voor de Profit omgeving vastgelegd. En de header opgebouwd
  2. Hier worden de Variabelen voor het Azure Storage account vastgelegd.
  3. Hier maken we verbinding met de Azure Storage omgeving
  4. Hier halen we eerst de lijst met geautoriseerde connectoren op en vervolgens loopen we door deze connectoren heen. Voor iedere connector wordt een JSON file naar de storage geschreven.

Koppelen Power BI rapport

Het koppelen van de databron werkt niet helemaal intuitief, het is dus zaak om deze stappen goed te volgen.

Open de Power BI client en begin een nieuw rapport

  • Kies voor een nieuwe gegevensbron, gebruik eventueel het zoekveld en zoek naar Azure Blob
Power BI Gegevensbron toevoegen
  • Je krijgt vervolgens een veld waar je het adres van de Azure Blob in kan voeren. Je vind dit adres op de properties pagina van de Storage Blob in Azure.
Power BI gegevensbron URL
  • In het volgende veld moet je de ā€œKeyā€ van het storage account invoeren. Je vind deze ā€œKeyā€ op de ā€œaccess keysā€ pagina van het storage account (dus 1 niveau hoger dan de Storage Blob).
Power BI Blob Accountsleutel
  • Je krijgt vervolgens een pagina te zien met alle beschikbare files op de Blob, je mag hier op laden klikken
Power BI Tabel
  • Als je vervolgens de Query Editor opent zie je een aantal regels, klik in de eerste regel op ā€œBinaryā€
Power BI Tabel
  • In het volgende venster zie je weer een aantal regels, klik hier op ā€œListā€
Power BI List
  • In de nieuwe weergave mag je in het ribbon op de ā€œNaar tabelā€ knop drukken
Power BI convert to table
  • Vervolgens kan je op de onderstaande knop drukken om de tabel om te zetten in alle kolommen.
Power BI Expand
  • Selecteer hier de kolommen die je wil gebruiken.
Power BI Kolommen selecteren

Je kan deze stappen herhalen voor iedere JSON / Connector die je in je rapportage wil gebruiken. Om de eerste stappen wat te versnellen kan je eventuele in de advanced editor de code die je heb na stap 4 kopieren en als nieuwe query plakken. Dat scheel eventueel wat handwerk.

Als je deze stappen doorlopen hebt is de data ā€œliveā€ beschikbaar in Power BI. Afhankelijk van de refresh die je in Azure Automation hebt ingesteld zal de data periodiek worden bijgewerkt. Als je de rapportage open hebt staan kan je op ā€œRefreshā€ drukken om de nieuwe data op te halen.

Tot slot

Als je de bovenstaande stappen gevolgd heb zal alles normaal gezien naar behoren moeten werken. Er is dan wel nog ruimte voor verbetering, maar om het voorbeeld een beetje overzichtelijk te houden heb ik het hier bij gehouden. De eerste stap die eigenlijk nog gezet moet worden is het het gebruiken van de Azure Credential Store in je Azure Automation account, dat voorkomt dat de autorisatie tokens zichtbaar in het script staan en is dus uiteindelijk een veiligere implementatie.

Verder kan je het versiebeheer en de uitrol van het script nog mooi inregelen in Azure Devops of Github, maar dat is een post voor later :).

AFAS Profit bijlagen exporteren (Powershell)

AFAS Profit bijlagen exporteren is in bulk helaas niet zo eenvoudig. Als je een keer een enkele bijlage uit een AFAS Profit dossier nodig hebt ga je eenvoudig in de applicatie naar het desbetreffende dossieritem en download je de bijlage. Maar wat als je nou van alle abonnementen uit ƩƩn groep of administratie alle bijlages wil exporteren om deze in een andere applicatie in te lezen?

Dit leek me wel een mooie Powershell oefening en na enig uitstel ben ik er maar eens voor gaan zitten. Ik sla de voorbereidende stappen in AFAS Profit even over in deze post, maar ik zal verwijzen naar de bestaande instructies voor die stappen.

Wat gaan we doen?

Doel: Alle bijlages uit de abonnementsdossiers opslaan buiten AFAS Profit. Per abonnement maken we een map aan en daar worden alle bijlages die bij dat abonnement gevonden worden opgeslagen.

Stappenplan:

  1. Connectoren aanmaken in AFAS Profit
  2. Connectoren autoriseren in AFAS Profit
  3. Powershell script maken met een aantal functies:
  4. Draaien export

Stap 1 en 2 ga ik nu niet al te veel tijd aan besteden, als je de instructies volgt die hier staan moet je hier wel uit komen, als je geen idee hebt hoe dat werkt kan je het beste mij of een consultant even een berichtje sturen šŸ™‚

Wel heb ik de twee getconnectoren die ik in dit voorbeeld gebruik hier staan zodat je deze kan gebruiken en/of aanpassen. (zip)

Powershell

Zoals aangegeven gaan we het exporteren van de files doen middels Powershell en de AFAS Profit getconnectoren. In dit geval heb ik Powershell 6.2 gebruikt in verband met een Invoke-RestMethod functionaliteit.

Het script is opgebouwd uit een aantal functies die ik vervolgens aanroep in een runner die de daadwerkelijke uitvoering doet. Onderaan staat een linkje naar de hele file, maar ik loop hier even door de scriptblokken heen, ik heb overal de url en autorisatie tokens aangepast:

Functie: ProfitAuthorisatie

function ProfitAuthorisatie {
    # Bouw de autorisatie header voor AFAS Profit
    $token = '<token><version>1</version><data>****</data></token>'
    $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($token))
    $authValue = "AfasToken $encodedToken"
    $Headers = @{
        Authorization = $authValue
    }
    $Headers
    return
}

Deze functie bouwt de autorisatie header op die we nodig hebben voor het aanroepen van de REST API van AFAS Profit. Deze code wordt een aantal keer aangeroepen in de komende functies. Vergeet niet je eigen Autorisatie token in te voeren.

Functie: GetAbo

function GetAbo {
    param (
        [int32]$administratie
    )
    # Definieer de URL voor de Profit omgeving
    $url = 'https://****/profitrestservices/connectors/DossierBijlagen?filterfieldids=AdministratieAbo%3BAdministratieProject&filtervalues=' + $administratie + '%3B' + $administratie + '&operatortypes=1%3B1&skip=-1&take=200'
    # Connect and retrieve the table
    $auth = ProfitAuthorisatie
    ((Invoke-WebRequest -Uri $url -UseBasicParsing -Headers $auth).content | ConvertFrom-Json).Rows
}

Deze functie haalt een lijst op van alle abonnementen die dossieritems hebben. Ik haal direct ook de verschillende dossieritem ID’s op die ik later nodig heb om de bijlagen op te sporen. De functie heeft een parameter nodig om te kunnen werken, dit is de administratiecode waarvan je de abonnementen op wil halen. Je geeft deze code als parameter mee wanneer je het uiteindelijke script aanroept.

Functie: GetBijlagen

function GetBijlagen {
    param (
        [int32]$DossieritemID
    )
    # Definieer de URL voor de Profit omgeving
    $url_dossier = 'https://****/profitrestservices/connectors/AbonnementenExport?filterfieldids=DossieritemID&filtervalues=' + $DossieritemID + '&operatortypes=1&skip=-1&take=-1'
    # Connect and retrieve the table
    $auth = ProfitAuthorisatie
    ((Invoke-WebRequest -Uri $url_dossier -UseBasicParsing -Headers $auth).content | ConvertFrom-Json).Rows
}

Deze functie heeft het ID van het dossieritem als input parameter nodig. Dit is een van de velden die als resultaat uit de GetAbo functie is gekomen. De reden dat we los de bijlagen op moeten halen is dat de GUID en de filename niet direct in het dossieritem beschikbaar zijn. Daar komt bij dat een enkel dossieritem weer meerdere bijlagen kan hebben. De output hier is een object/array met alle bijlages die beschikbaar zijn bij dit dossieritem.

Functie: DownloadBijlagen

function DownloadBijlagen {
    param (
        [string]$filename,
        [string]$guid,
        [string]$map,
        [string]$abo
    )

    # Definieer de URL voor de Profit omgeving
    $url_download = 'https://****/profitrestservices/fileconnector/' + $guid + '/' + $filename 
    # Connect and retrieve the table
    $auth = ProfitAuthorisatie
    $fileout = $map + '\' + $abo + '-' + $filename 
    $download_error = 0

    # Voorkomen dat we lege files wegschrijven omdat de download niet uitgevoerd kan worden.
    try {
        $tempfile = Invoke-RestMethod -Uri $url_download -Method Get -Headers $auth 
    }
    catch {
        Write-Host $_ -fore Red
        $download_error = 1
    }
    
    if ($download_error -eq 0) {
        $bytes = [System.Convert]::FromBase64String($tempfile.filedata)
        [IO.File]::WriteAllBytes($fileout, $bytes)
        Write-Host $filename "- Succesvol weggeschreven in"  $fileout -ForegroundColor green
    } 
}

Op basis van de items in de lijst die uit GetBijlagen gekomen is kunnen we de files gaan downloaden. Je hebt sowieso de filename en de guid nodig om de fileconnector (subjectconnector) aan te kunnen roepen. Daarnaast geef ik de map mee waar we de file op gaan slaan en het abonnementsnummer (deze neem ik op in de filename, dit is wel een punt, het is niet uitgesloten dat dit dubbele bestanden op kan leveren, in ons geval komt dat niet voor, maar technisch zou je hier bestanden kunnen overschrijven).

In dit stukje code zit ook een error check, heel af en toe kan een file niet goed gedownload worden, dit leverde lege bestanden op. Om dat te voorkomen vang ik die error af (en meld dat in de output) en doe dan dus geen download.

Op dit moment levert dit wel nog lege mappen op als de enkele bijlage bij een abonnement niet goed gedownload kan worden, maar dat zou je simpel op kunnen lossen als dat een probleem is.

Functie: ScriptUitvoeren

function ScriptUitvoeren {
    param (
        [int32]$administratie
    )
    
    # Eerst Getabo
    $records = GetAbo $administratie

    # Per Abo dossieritems ophalen
    foreach ($record in $records) {
        
        # Map bepalen voor het eventueel opslaan van bijlagen
        $map = "C:\Exports\" + $record.Abonnement  

        # Bijlagenlijst per dossieritem maken
        $bijlagenlijst = GetBijlagen $record.DossieritemID

        # Als de map voor het abonnement nog niet bestaat deze aanmaken
        If (!(test-path $map) -And $bijlagenlijst.count -gt 0) {
            New-Item -ItemType Directory -Force -Path $map
        }

        # Per bijlage file downloaden
        foreach ($bijlage in $bijlagenlijst) {
            DownloadBijlagen $bijlage.Naam $bijlage.Bijlage $map $record.Abonnement
        }
    }
}

Dit is de functie die we aanroepen als we het script gaan draaien, je zou deze functie ook direct in de code aan kunnen roepen. Gezien ik het script per administratie wil kunnen draaien heb ik er voor gekozen om hem los aan te roepen. De functie heeft het administratienummer als parameter nodig.

In dit geval is de map waar we de bijlagen opslaan c:\exports\ maar daar kan je van maken wat je wil.

Je ziet in deze funtie dat alle eerdere functies stap voor stap opgeroepen worden en de output daarvan weer als input in een andere functie gestopt wordt. Er worden twee nested foreach loops gebruikt om door alle abonnementen en dossieritems heen te lopen.

Tot slot

Het script is zeker niet perfect, ik zou de lege mappen nog op kunnen ruimen en wat betere logging toe kunnen passen, maar voor ons doel was dit voldoende. Als je eventueel vragen hebt over het script kan je die in de comments stellen.

Het script is hier te downloaden en in te zien. Nadat je de ps1 file gedraaid hebt kan je met “ScriptUitvoeren #” het script starten (vervang # door het administratienummer).

Documenten

Azure Function App Proxy

In de voorgaande posts hebben we het gehad over een directe koppeling tussen AFAS Profit en Power BI en het gebruik van een Azure Function App om scripts te kunnen draaien. Deze twee onderdelen hebben echter nog een extra toepassing.

Wanneer je een Power BI rapportage die gebruik maakt van directe AFAS Profit data wil publiceren ga je bij de refresh problemen krijgen met het autoriseren van de (web) databronnen. Het probleem is dat het deel van de URL met de autorisatie token afgekapt wordt (samen met eventuele filters). Waarom dit precies gebeurt is mij niet helemaal duidelijk. Een mogelijke oplossing is het gebruik van een Azure Function App Proxy. Als je toch al een Azure Function App hebt voor het draaien van je scripts kost deze proxy je normaal gezien niets extra.

Wat gaan we doen?

Een Azure Function App Proxy kent vele mogelijke toepassingen. In dit voorbeeld gaan we de Proxy tussen de AFAS Profit Webconnector (REST) en Power BI plaatsen. Power BI gaat een request naar de proxy sturen met een aantal parameters, de proxy reformat het verzoek en doet het verzoek bij de Profit omgeving. Het resultaat wordt vervolgens 1-op-1 doorgestuurd naar Power BI. (We zouden hier eventueel nog acties aan de response kunnen hangen, maar dat is nu niet nodig).

De stap voor het maken van de function app zelf slaan we deze keer even over, als je wil weten hoe dat werkt kan je dit item lezen. Ik ga dan ook uit van dezelfde demo als in die post, het startpunt is dan ongeveer het volgende:

Azure Function App

Toelichting endpoint (AFAS Profit REST API)

Wanneer je gebruik wil maken van de AFAS Profit REST API moet er gewerkt worden met een bepaalde opbouw van de URL gecombineerd met een een autorisatie header. Wanneer je deze direct vanuit Power BI ingeeft als bron kan je deze handmatig autoriseren, echter, wanneer je de rapportage publiceert werkt deze authenticatie niet meer. Dat betekend dat we een tussenstap moeten maken.

Het doel is uiteindelijk dat we een request zoals deze naar naar de REST API van Profit kunnen sturen:

https://url_van_omgeving/profitrestservices/connectors/{connector}

Vervolgens moeten daar de connector specifieke velden, filters en autorisatie aan meegegeven worden. Alle velen die we nodig hebben zijn al bekend gezien we deze in de directe koppeling uit de eerdere posts ook al gebruikt hebben.

Inrichting Azure Function App Proxy

Wanneer je in het Function App menu zit zie je bij Proxies ongeveer het volgende:

Azure Function Apps menu

Je kan daar op de + klikken om een nieuwe proxy aan te maken, daarvoor moet het een en ander ingevoerd worden, dat ziet er dan uiteindelijk ongeveer als volgt uit:

Azure Function Apps - Proxies

We lopen even door de velden heen:

Route template

Hier geef je de structuur van de proxy url op, in dit geval beginnen we met de “/naca” dit doet van zichzelf niets. Het geeft een stukje structuur waarmee de url’s en verwijzingen van elkaar onderscheiden kunnen worden. Dit wordt gevolgd door een aantal velden tussen {} geplaatst zijn. Dit zijn de variabelen die we willen kunnen gebruiken in de “request override” of de “header”. In dit geval zijn dat:

Token = Autorisatie token (zie eerdere posts)
Periode = De periode waarvan we de data op willen halen, dit gaan we in een filter gebruiken
Connector = De naam van de connector die we op willen roepen.

Het resultaat van deze route template komt terug in de URL die je gebruikt in Power BI.

Backend url

Dit is het adres waarop de AFAS Profit REST API benaderd kan worden. Je ziet hier aan het einde {connector} staan, dat wil dus zeggen dat hij de variabele uit de request URL overneemt naar de backend url.

Request override

Vervolgens zal je de “Request override” open moeten klikken en invullen, voor de duidelijkheid staat hieronder nog specifiek een screenshot van dat onderdeel:

Azure Function Apps - Request override

Dit is het deel waar we het request dat naar de Azure Funtion App Proxy gestuurd is om gaan zetten naar het request waar onze AFAS Profit omgeving wat mee kan.

De skip en take velden zijn gelijk aan wat we kennen uit de directe koppeling. We kunnen hier direct ook een specifieke periode ophalen. We gebruiken hiervoor de standaard filter opties van de AFAS Profit REST API. Het “filterfieldsids” geeft de velden aan waar je op wil filteren. Het “filtervalues” veld is de waarde waarop je op wil filteren, je ziet hier {periode}  staan, wat weer betekend dat we de variabele die we in de route template gespecificeerd hebben overnemen in het filter voor AFAS. Tot slot staat er nog “operatortypes” en dat is weer een onderdeel van de filteropties vanuit Profit.

Je kan in deze velden eigenlijk alles kwijt wat je normaal ook zou gebruiken bij het ophalen van een getconnector in AFAS Profit.

Headers

Tot slot moeten we nog de autorisatie headers mee geven. Dit is namelijk de hele reden dat we de directe koppeling niet in de gepubliceerde rapportages kunnen gebruiken. Het token wat we nodig hebben zit al in het route template. Zoals eerder zie je ook hier weer dat we de variabele kunnen gebruiken, in dit geval het veld {token}:

Het “ContentType” veld en de inhoud (“application/json;charset=utf-8”) zijn voor Profit connectoren altijd gelijk.

Als we dit alles ingevuld hebben kan de proxy opgeslagen worden. Je krijgt dan een URL terug die je in het vervolg kan gebruiken voor het ophalen van de data uit AFAS Profit. De URL ziet er grofweg als volgt uit:

https://****.azurewebsites.net/naca/{token}/{periode}/{connector}

Verwerking in Power BI

Je kan de URL hier boven nu gebruiken in de rapporten die je wil publiceren. Hiervoor maak je in Power BI een “web” bron aan:

Je bouwt deze vervolgens op aan de hand van de structuur voor de proxy url zoals we deze in de vorige stap gemaakt hebben:

Power BI databron gevuld

Wanneer je deze bron nu opslaat kan je de data gebruiken op dezelfde manier als de directe koppeling die we in een van de eerdere posts gemaakt hebben. In het voorbeeld hierboven heb ik gebruik gemaakt van parameters in Power BI om de variabelen op te slaan en mee te nemen. Je kan hier ook direct de waardes voor de variabelen vullen.

Veiligheid

Op zich is het gebruik van de proxy net minder veilig dan de directe koppeling naar Profit. Echter, het is wel altijd een goed idee om een stap extra te zetten om de hoeveelheid mensen die potentieel de data kunnen benaderen te verkleinen. Je kan daarvoor op IP niveau filtering aanbrengen voor je Azure Function App. In ons geval weten we zeker dat alleen vanaf 2 kantoren en onze datacenters gewerkt mag worden met deze data (alles voor Power BI loopt via onze “On-premises Data Gateways”).

Open hiervoor het overzicht van je function app, kies hier voor “Platform features”:

Azure Function Apps  - Overview

Vervolgens voor “networking”:

Azure Function Apps - Networking

Onderaan zie je de optie “ip restrictions”:

Azure Function Apps - beveiliging - IP

Je ziet dan een pagina zoals hier onder:

Azure Function Apps - beveiliging - IP Filter

Hier kan je regels toevoegen om de adressen vanaf waar de apps benaderd mogen worden te beperken.

Tot slot

Het heeft even geduurd voordat ik dit artikel daadwerkelijk helemaal af heb kunnen maken. De techniek hier achter is niet heel complex maar er zijn talloze mogelijkheden en oplossingen denkbaar in Azure. Ik wilde graag iets meer ervaring opdoen voordat ik dit stuk helemaal af zou ronden. Dit zodat iemand die hier mee aan de slag gaat geen onnodige stappen hoeft te zetten of onnodige risico’s loopt.

Mochten er naar aanleiding van dit stuk nog vragen zijn hoor ik het graag!

Azure function apps in combinatie met AFAS Profit

Als je wil proberen om zo min mogelijk eigen infrastructuur te gebruiken zonder dat dat meteen veel geld moet kosten zijn er talloze opties te bedenken. Een van die opties is Microsoft Azure. De eerste stap die je zal moeten zetten is gaan denken in de daadwerkelijke handelingen die er uitgevoerd moeten worden. Deze handelingen wil je vervolgens in logische blokken opdelen, met als voorwaarde dat deze blokken moeten onafhankelijk van elkaar kunnen functioneren. Vervolgens kan je per blok gaan kijken wat de beste manier is om de gewenste functionaliteit te realiseren.

Het “Probleem”

In dit voorbeeld gaan we voor nieuwe medewerkers in AFAS Profit een aantal velden vullen. Omwille van de eenvoud van het voorbeeld heb ik het gebruikte script even eenvoudig gehouden. Gezien het in Profit niet mogelijk is om logica toe te passen bij het automatisch vullen van velden hebben we een externe oplossing nodig om dit te doen. Het heeft mijn voorkeur om dit soort zaken met Powershell en de connectoren in Profit op te lossen. Voorheen gebruikte ik hiervoor altijd een van onze applicatieservers voor (om het script te draaien). We kunnen dit echter ook prima in Azure oplossen

De oplossing (Microsoft Azure)

Als je in MicrosoftĀ Azure scripts wil laten draaien die gebruik kunnen maken van web connectiviteit zijn de “Function Apps” een goede optie. Binnen dit systeem heb je bijvoorbeeld ook Web Proxies beschikbaar en die gaan we in een latere post gebruiken :). We gaan dus een Function App aanmaken waarbinnen we ƩƩn of meerdere scripts op een tijdschema laten draaien. In dit voorbeeld gaan we een lijst ophalen van medewerkers die nog geen licenties toegekend gekregen hebben. Deze lijst met medewerkers krijgt vervolgens de juiste licenties toegekend op hun medewerkerkaart. Voor deze stappen heb je een actieve Azure Subscription nodig (je moet dus of in de trial zitten of een betaalmethode gekoppeld hebben). De kosten van het draaien van dit script (15 uur per dag) zijn 6 eurocent per maand (afhankelijk van de gebruikte opslag / data). Ik zou Azure altijd instellen op de Engelse taal gezien de vertalingen naar het Nederlands erg verwarrend kunnen zijn. Daarnaast zijn niet alle vertalingen correct.

Stappenplan (functie)

We starten op de AzureĀ portalĀ en kiezen daar voor het aanmaken van een nieuwe resource:
Azure portal "Create Resource"
In het volgende venster zoek je naar “Function app”:
Azure function app aanmaken
Je krijgt een nieuw menu te zien waar je een aantal instellingen in kan geven. De “App name” is voor dit stappenplan niet zo van belang. Mocht je later de Proxy functionaliteit wil gaan gebruiken wordt dit de URL waarop je de proxy kan benaderen. In ons geval moeten we een nieuwe resoursegroup aanmaken waar alle elementen voor deze functionaliteit gebundeld worden. als locatie kiezen we voor West Europe gezien die geografisch het dichtste bij onze AFAS Profit omgeving zal staan. De naam van de storagegroup is niet heel belangrijk in dit geval, als je het maar eenvoudig terug kan vinden. Uiteindelijk heb je dan grofweg het onderstaande. Als je nu op “Create” klikt wordt de Function App aangemaakt, dit kan ongeveer een minuut duren.
Na een minuutje wachten kan je de Function App openen en krijg je een overzicht zoals dit te zien:
Function app overzicht.
We kunnen nu daadwerkelijk de functie aan gaan maken die het script gaat draaien. We klikken hiervoor bij “Funtions” op het plusje om de wizzard te openen. Er zijn een groot aantal standaard functies beschikbaar, maar in ons geval willen we een custom function bouwen:
In het volgende venster zal je de beta talen aan moeten zetten. Powershell is nu nog in beta (al tijden), maar werkt prima. Om deze mogelijkheid te krijgen moet je deze switch even omzetten:
Vervolgens kan je de “Time Trigger” optie kiezen:
Azure function Time Trigger
In het volgende venster zal je de taal moeten kiezen (in ons geval PowerShell) en het schema moeten definiƫren. Dit schema maakt gebruik van dezelfde notatie als CRON en is niet heel erg gemakkelijk leesbaar als je er niet veel mee werkt. Je kan hiervoor eventueel een generator gebruiken. In het voorbeeld hier onder draaien we het script ieder uur vanaf 7.00 in de ochtend tot 20.00 in de avond. (let wel op dat je je tijdzone goed ingesteld hebt).
Na het aanmaken van de functie krijg je een leeg venster te zien waar het script geplaatst kan worden. Je kan dit allemaal integreren met bijvoorbeeld Github (of andere repositories), maar dat gaat voor dit voorbeeld even te ver.

Het script

De laatste stap is het toevoegen van het script zelf. Ik ga niet al te veel in op de werking van het script, maar kort samengevat gebeurt er het volgende:
  • Roep een getconnector aan die een gefilterde lijst met gebruikers zonder licenties ophaalt.
  • Loop door deze lijst en voer de gewenste licentiecodes in bij de diverse users.
Om het voorbeeld een beetje overzichtelijk te houden staat hier onder een versimpelde versie van ons script. We gebruiken zelf een complexer script met een aantal randvoorwaarden om te bepalen welke licentie nodig is voor welke gebruiker.
begin {

    # define the access token for the AFAS service
    $token = '<token><version>1</version><data>***</data></token>'
    $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($token))
    $authValue = "AfasToken $encodedToken"
    $Headers = @{
        Authorization = $authValue
    }

    # Connect and retrieve the table
    $url = 'https://**/profitrestservices/connectors/***?skip=-1&take=-1'
    $records = ((Invoke-WebRequest -Uri $url -UseBasicParsing -Headers $Headers).content  | ConvertFrom-Json).Rows
}

process {
    # Specify update authorization
    $token = '<token><version>1</version><data>***</data></token>'
    $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($token))
    $authValue = "AfasToken $encodedToken"
    $Headers = @{
        Authorization = $authValue
    }
    $connectorname = "KnEmployee"
    
    # Process records 
    foreach ($record in $records) {
        $url = "https://***/profitrestservices/connectors/KnEmployee"

        Write-Host $record.profituser
        $medewerker = $record.profituser

        $messagecontent = '{"AfasEmployee": {"Element": {"@EmId": "' + $medewerker + '", "Fields": { "***": "02", "***": "01"}}}}'

        $results = ((Invoke-WebRequest -Uri $url -UseBasicParsing -ContentType 'application/json;charset=utf-8' -Method PUT -Headers $Headers -Body $messagecontent).content | ConvertFrom-Json)
        Write-Host $results
    }
}
Na het invoeren van het script kan je op “save en run” klikken en daarna zal het script volgens het voorgestelde schema draaien. Je kan eventuele fouten opsporen door de logging na te kijken, deze is voor de losse run direct onder in het scherm beschikbaar:
En later via het monitor menu:

Tot slot

Dit is natuurlijk maar een eenvoudig voorbeeld, maar je kan je voorstellen dat je op deze manier veel zaken kan automatiseren zonder dat je hier eigen infrastructuur voor nodig hebt. Het script wat ik gebruikt heb in dit voorbeeld is gemaakt samen met Jaap de Koning, lees ook eens zijn blog als je geĆÆnteresseerd bent in automatisering. Laat even een berichtje achter als je meer wil weten over deze manier van automatiseren rondom AFAS Profit of het gebruik van Azure functions. De komende tijd zal ik meer in gaan op deze aanpak. Daarbij kijken we naar de veranderingen die nodig zijn in de manier van denken om goed gebruik te maken van cloud en hybride oplossingen.

AFAS Profit Power BI directe koppeling

Ik heb eerder een aantal berichten geschreven over het koppelen van AFAS Profit aan Power BI door middels de connectoren en een stukje Powershell JSON files te genereren. Hiervoor had je een stukje storage nodig om de files te plaatsen en daarnaast een Power BI Gateway. Daarmee dus ook een server om die op te draaien. Zeker voor de AFAS Online klanten is het niet vanzelfsprekend dat je die infrastructuur hebt, en dus was er genoeg aanleiding om even verder te zoeken naar de mogelijkheden :).

Het doel

Er zijn grofweg 3 manieren om data in Power BI te krijgen:

  • Direct (live)
  • Direct (update via schema)
  • Files via de Enterprise Gateway

In mijn eerdere posts ging ik in op de mogelijkheden via de Enterprise Gateway. Dit is overigens een variatie op de Directe koppeling met een update via een schema. Het streven was nu vooral het koppelen zonder tussenkomst van eigen servers, services of storage.

De uitdaging

Power BI heeft een flink aantal mogelijkheden als het gaat om het koppelen van databronnen. Een van de opties is een web connector:

De Power BI web data source connector

Het is alleen even wat puzzelwerk om de autorisatie voor de REST connector van AFAS Profit goed te krijgen, vooral ook omdat hier eigenlijk geen hele goede documentatie van beschikbaar is. Maar goed, daar zijn artikelen als deze voor :).

De oplossing

Om data uit AFAS Profit beschikbaar te krijgen in Power BI zonder dat daar (behalve bij het aanmaken) handmatige acties voor nodig zijn moeten we gebruik maken van de web/app connectoren in Profit. In dit voorbeeld maken we gebruik van de REST API van AFAS Profit. Hoe je deze connectoren aan kan maken heb ik eerder omschreven in dit artikel.

Het belangrijkste is dat je de autorisatie token die je in dat stappenplan maakt goed bewaart. Het is niet mogelijk om deze code opnieuw te generen zonder de oude code te laten vervallen. De code die je genereert zit er grofweg als volgt uit:

<token><version>1</version><data>***</data></token>

Je kan deze code echter niet 1-op-1 gebruiken om via Power BI te autoriseren voor de connector, er dient een Base64 string van gemaakt te worden en de tekst “AfasToken” dient voorgevoegd te worden. Om het gemakkelijk te maken heb ik een kleine tool gemaakt om deze handelingen snel uit te voeren.

Screenshot Profitkey.hermanronk.nl

Je vind deze tool op profitkey.hermanronk.nl. Als je ons voorbeeldtoken door deze tool heen halen is dit het resultaat:

AfasToken PHRva2VuPjx2ZXJzaW9uPjE8L3ZlcnNpb24+PGRhdGE+KioqPC9kYXRhPjwvdG9rZW4+

Het laatste wat we nog nodig hebben is het web-pad naar de connector. Het eerste deel van de URL is altijd hetzelfde voor je eigen omgeving en de rest is variabel. Het eerste deel is als volgt opgebouwd:

AFAS Online:Ā https://12345.afasonlineconnector.nl/profitrestservices/ (12345 is je deelnemersnummer)
Lokale installatie:Ā https://”webadres”/profitrestservices/ (webadres is veelal het gelijk aan het eerste deel van de url voor InSite)

Het laatste deel van de URL kan dus wisselen, de opbouw is als volgt:

/connectors/pbi_mdw?skip=-1&take=-1

/connectors/ = meestal gelijk
pbi_mdw = de naam van de connector die je wil benaderen
?skip=-1&take=-1 = opties en filters

Wanneer je met grote datasets werkt wil je eventueel filters gebruiken en een datasource per bijvoorbeeld periode aanmaken in Power BI. een filter op periode zou er bijvoorbeeld als volgt uit kunnen zien (we filteren hier op periode 7):

&filterfieldids=Periode&filtervalues=7&operatortypes=1

Aan de slag in Power BI

Met de bovenstaande informatie hebben we alles wat we nodig hebben om in Power BI de connector aan te maken. We kiezen zoals aan het begin van deze post aangegeven voor de bron “Web”, wanneer je daarna op geavanceerd klikt krijg je onderstaand scherm te zien:

Power BI Web bron configuratie scherm

Hier moeten we drie velden vullen:

  1. URL
  2. Header 1: Content-Type
  3. Header 2: Autorisation

De URL zou in het geval van een AFAS Online omgeving volgens de bovenstaande instructies als volgt opgebouwd zijn:

https://12345.afasonlineconnector.nl/profitrestservices/connectors/pbi_mdw?skip=-1&take=-1&filterfieldids=Periode&filtervalues=7&operatortypes=1

Bij het tweede en derde veld moeten de headers ingevoerd worden, de eerste specificeert de content type.Ā Dus kies hier in het linker veld “Content-Type” en voer in het rechter veld “application/json;charset=utf-8” in.

Het derde veld is de autorisatie, hiervoor hebben we via profitkey.hermanronk.nl een string gegenereerd. In het linker veld kies je voor “Authorization” en in het rechter veld voer je de gegenereerde string in, zoals bijvoorbeeld “AfasToken PHRva2VuPjx2ZXJzaW9uPjE8L3ZlcnNpb24+PGRhdGE+KioqPC9kYXRhPjwvdG9rZW4+”

Als je op voltooien drukt krijg je een venster waar je moet aangeven op welk niveau de autorisatie moet worden toegepast. Kies hier uit het dropdown menu de meest specifieke optie:

Power BI connector autorisatie

Vervolgens klik je op “verbinden”, je krijgt dan grofweg het volgende te zien:

PBI JSON verwerking

Je kan hier op “List” klikken en vervolgens op naar tabel:

Tot slot moet je de kolom nog uitvouwen en de kolommen selecteren die je wil behouden:

Power BI Kolommen uitvouwen

Als je nu de Query opslaat kan je aan de slag met de Profit data in Power BI! De laatste tip die ik nog even mee wil geven is als volgt. Eerder heb ik aangegeven dat je grotere datasets moet splitsen middels filters. Als je dat gedaan hebt kan je deze tabellen in Power BI naadloos samenvoegen:

Power BI Query toevoegenPower BI tabellen samenvoegen

Er wordt dan een nieuwe tabel aangemaakt die een samenvoeging is van de hier boven geselecteerde tabellen.

Tot slot

Het is even wat werk om op deze manier de data naar Power BI te halen, maar als het eenmaal ingericht is kan je het basisbestand eindeloos kopiƫren en uitbreiden. De data kan via de scheduler prima periodiek ververst worden, houd er alleen wel even rekening mee dat zeker grotere connectoren best wat impact kunnen hebben op de performance.

Ik zal in de komende tijd nog twee andere mogelijkheden voor het ontsluiten van Profit data in Power BI uitwerken. Beide opties maken dan wel gebruik van een tussenstap, maar zijn misschien wat meer geschikt voor grotere hoeveelheden data.