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.

Leave a Reply

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.