Microsoft Flow is een ‘gratis dienst’ van Microsoft die je kan gebruiken om processen te automatiseren. Onze collega Niek Jachimowski schreef hier al eerder een blog over: https://blog.portiva.nl/2016/09/06/aan-de-slag-met-microsoft-flow/
Flow biedt natuurlijk geweldige mogelijkheden en wordt vaak aangehaald als de vervanger voor SharePoint Designer workflows. De standaard voorbeelden voor een goedkeuring op een document binnen SharePoint zijn natuurlijk heel leuk en helpen je al een eind op weg. Maar wanneer je op een kwaliteitsafdeling zit en je moet borgen dat al je kwaliteitsprocedures goedgekeurd worden door verschillende afdelingsmanagers en kwaliteitsmedewerker van de afdeling. Dan wordt de Flow al snel complexer. In deze blog willen we je daarom meenemen in zaken waar je tegen loopt bij het maken van een geavanceerde goedkeuringsworkflow met Microsoft Flow.
Al deze punten gaan we stapsgewijs met jullie door.
Voor een kwaliteitssysteem is in dit geval gekozen voor een oplossing waarbij de procedures en werkinstructies in een SharePoint bibliotheek worden opgeslagen. De bibliotheek moet voorzien worden van de volgende instellingen:
De kolom met (meerdere) goedkeurders wordt als volgt ingericht.
Deze kolom wordt later in het goedkeuringsproces gebruikt zodat alle goedkeurders tegelijkertijd zijn of haar goedkeuring moeten geven.
In SharePoint Designer workflows is deze stap een eitje en kun je ook eenvoudig aangeven of maar 2 van de X goedkeurders moeten bevestigen. Bekijk de onderstaande afbeeldingen maar eens:
Bron: https://collab365.community/sharepoint-2013-approval-workflow-with-3-dinamically-determined/
Deze zaken zijn nog niet mogelijk met Microsoft Flow. Toch gaan we met MS Flow het volgende scenario behandelen: we willen graag dat alle geselecteerde goedkeurders (dus parallel) moeten goedkeuren voordat het document de status goedgekeurd heeft in de documentbibliotheek. Dit betekend dat na de goedkeuring het document ook naar een primaire versie gaat. En dus voor alle gebruikers zichtbaar wordt!
Microsoft Flow heeft een standaard oplossing voor een goedkeuring genaamd ‘Start an approval’
Gedurende deze handleiding maken we gebruik van deze specifieke koppeling.
Daarnaast noteren we de naam van de goedkeurder niet in de Flow zelf. Het komt vaak voor dat de goedkeurders veranderen en er zelfs meerdere en verschillende goedkeurders zijn per document.
Wanneer de goedkeuring door meerdere personen moet worden gegeven dan kan dat serieel of parallel.
Het voordeel van een parallelle goedkeuring is dat ‘Keuring 2’ niet hoeft te wachten op het resultaat van ‘Keuring 1’. Hierdoor zal het gehele proces eerder voltooid zijn. Je hebt binnen Microsoft Flow meerdere methodes om parallelle acties uit te voeren. De bekendste en makkelijkste is het toevoegen van een parallelle branch:
Deze methode heeft echter enkele nadelen:
Het is ook mogelijk om maar één actie aan te maken die meerdere keren parallel wordt uitgevoerd. Maak hiervoor een kolom aan in de bibliotheek waarin de goedkeurders worden vastgesteld en zorg ervoor dat deze kolom meerdere personen kan bevatten:
Selecteer deze SharePoint kolom voor de ‘Toegewezen aan’ optie in de Approval:
Vervolgens zal je zien dat er automatisch een ‘Apply to each’ blok wordt toegepast op de approval:
Dit gebeurdt automatisch omdat de kolom ’Goedkeurder’ in dit geval meerdere personen kan bevatten. Hierdoor zal het goedkeuringsverzoek naar alle personen gestuurd wordt die in de kolom ‘Goedkeurder’ zijn ingevuld.
Ga vervolgens naar de instellingen van het ‘Apply to each’ blok:
Zet daar ‘Override Default’ aan en zet ‘Degree of Parallelism’ op de hoogste stand (50):
Wanneer de Flow nu start zullen alle gebruikers tegelijkertijd het verzoek tot goedkeuring ontvangen via mail.
Op het moment van schrijven heeft Microsoft Flow een retentie periode van 30 dagen. Dit houdt in dat Flows na 30 dagen stoppen, zelfs als er een approval actief is. Het is belangrijk hiervan bewust te blijven bij het ontwerpen van een goedkeuring workflow. Er zijn meerdere opties om dit probleem te verzachten, bijvoorbeeld door de Flow in meerdere Flows op te splitsen.
Wanneer het hele proces in één Flow wordt gebouwd kan het interessant zijn om de Flow initiator een mailtje te sturen wanneer de 30 dagen bijna verlopen indien nog niet iedereen heeft gereageerd. Dit is simpel te realiseren door de volgende methode:
Voer hiervoor de volgende stappen in de Flow uit:
Dit proces is ook te gebruiken voor bijvoorbeeld reminders of escalaties.
In het geval van goedkeuringen is het vaak belangrijk om ook achteraf te zien wat er is gebeurd met de goedkeuringen. Wie heeft wat goedgekeurd of afgekeurd. Middels Flow is deze informatie makkelijk weg te schrijven in SharePoint. Dit kan in een kolom bijbehorend bij het document zelf of in een andere lijst.
Beide hebben voor en nadelen:
Kolom bij het document |
Afzonderlijke lijst |
|
Voordelen |
|
|
Nadelen |
|
|
Met de volgende stappen laten we zien hoe het mogelijk om de goedkeuringsproces geschiedenis in een afzonderlijke lijst te bewaren.
2. Maak in de documentenbibliotheek een kolom (type nummer) aan genaamd ‘GeschiedenisID’ en een kolom (type hyperlink) genaamd ‘Goedkeuringsgeschiedenis’.
3. Flow updaten zodat deze de geschiedenis wegschrijft in de nieuwe lijst:
Voeg een ‘Initialize variable’-actie toe (type Integer) met de naam GoedkeuringsGeschiedenisID:
Voeg voor het goedkeuringsproces een scope toe genaamd ‘Goedkeuringsgeschiedenis’ met daarin een condition met de volgende ‘geavanceerde’ vergelijking:
@empty(string(body('Get_item')?['GeschiedenisID']))
Deze code kijkt of het GeschiedenisID is gevuld. Dit is niet het geval wanneer de Flow nog niet eerder heeft gelopen.
In het ‘No’-gedeelte van de conditie voeg je de volgende acties toe:
Omdat de ‘Naam’ verplicht is om in deze actie in te vullen vul je deze met de naam die al in het item stond.
De No kant (niet gevulde GeschiedenisID) is hiermee afgerond.
In de ‘Yes’ sectie voeg je de volgende acties toe:
De conditie is hiermee volledig en zou er ongeveer als volgt moeten uitzien:
Tussen de ‘Goedkeuringsgeschiedenis’-scope en de ‘Goedkeuringsproces’-actie voeg je een ‘Get item’-actie toe om nogmaals de gegevens van het ‘Goedkeuringsgeschiedenis’-item op te halen. Je gebruikt hiervoor het ID dat is opgeslagen in de variabel ‘GoedkeuringsGeschiedenisID’
Het is handig wanneer je deze actie een makkelijk te herkennen naam geeft zoals in het voorbeeld hierboven. Deze stap is noodzakelijk omdat je vooraf niet weet of het een bestaande of nieuwe goedkeuringsgeschiedenis koppeling betreft.
Voeg tenslotte in de Flow op de plaatsten waar het nodig is Goedkeuringsgeschiedenis updates toe wanneer informatie weggeschreven moet worden door middel van de actie ‘Update item’. Bijvoorbeeld wanneer iemand het document goed of afkeurt:
Let hierbij op dat je de Goedkeuringsgeschiedenis lijst selecteert en daarbij het ID & Naam gebruikt die je hebt opgehaald met de laatste ‘Get item’-actie (in dit geval met de naam ‘Get item Goedkeuringsgeschiedenis’).
De Flow is nu gereed en zou er als volgt uit moeten zien:
Zo we hebben nu een flow gemaakt, de status van het document staat in de bibliotheek en we hebben een kolom met een lelijke url voor de werkstroomgeschiedenis.
3 punten die super zijn om met een column formatter te gaan doen:
We passen hier de stappen toe die standaard hier beschreven staan dit is niet zo spannend, maar het effect voor de eindgebruiker is natuurlijk superhandig. Geen dropdowns of menu’s meer door om het goedkeuringsproces te starten.
In het begin van het document werd gevraagd om een laatste reviewdatum aan te maken deze datum wordt na goedkeuring door de workflow gezet op -3 jaar na goedkeuring. Nu is er ook de standaard content approval kolom in SharePoint. Deze is niet te beïnvloeden en heeft geen status vervallen.
Het is een combinatie van de volgende scripts:
Hieronder is het eindresultaat te zien:
{
"$schema": "http://columnformatting.sharepointpnp.com/columnFormattingSchema.json",
"debugMode": true,
"elmType": "div",
"attributes": {
"class": {
"operator": "?",
"operands": [
{
"operator": "&&",
"operands": [
{
"operator": "!=",
"operands": [
"",
{
"operator": "toString()",
"operands": [
"[$Laatste%20reviewdatum]"
]
}
]
},
{
"operator": "<=",
"operands": [
"[$ Laatste%20reviewdatum]",
{
"operator": "-",
"operands": [
"@now",
94608000000
]
}
]
}
]
},
"sp-field-severity--blocked",
{
"operator": "?",
"operands": [
{
"operator": "||",
"operands": [
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Concept"
]
},
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Draft"
]
}
]
},
"sp-field-severity--warning",
{
"operator": "?",
"operands": [
{
"operator": "||",
"operands": [
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Goedgekeurd"
]
},
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Approved"
]
}
]
},
"sp-field-severity--good",
"sp-field-severity--blocked"
]
}
]
}
]
}
},
"children": [
{
"elmType": "span",
"style": {
"display": "inline-block",
"padding": "0 4px"
},
"attributes": {
"iconName": {
"operator": "?",
"operands": [
{
"operator": "&&",
"operands": [
{
"operator": "!=",
"operands": [
"",
{
"operator": "toString()",
"operands": [
"[$Laatste%20reviewdatum]"
]
}
]
},
{
"operator": "<=",
"operands": [
"[$Laatste%20reviewdatum]",
{
"operator": "-",
"operands": [
"@now",
94608000000
]
}
]
}
]
},
"ErrorBadge",
{
"operator": "?",
"operands": [
{
"operator": "||",
"operands": [
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Goedgekeurd"
]
},
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Approved"
]
}
]
},
"CheckMark",
{
"operator": "?",
"operands": [
{
"operator": "||",
"operands": [
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Concept"
]
},
{
"operator": "==",
"operands": [
{
"operator": "toString()",
"operands": [
"@currentField"
]
},
"Draft"
]
}
]
},
"Forward",
"ErrorBadge"
]
}
]
}
]
}
}
},
{
"elmType": "span",
"txtContent": {
"operator": "?",
"operands": [
{
"operator": "==",
"operands": [
"",
{
"operator": "toString()",
"operands": [
"[$Laatste%20reviewdatum]"
]
}
]
},
"@currentField",
{
"operator": "?",
"operands": [
{
"operator": "<=",
"operands": [
"[$Laatste%20reviewdatum]",
{
"operator": "-",
"operands": [
"@now",
94608000000
]
}
]
},
"Verlopen",
"@currentField"
]
}
]
}
}
]
}
Het probleem was vooral om te controleren wanneer er nog geen laatste reviewdatum is, dit hebben we als volgt opgelost:
"operator": "?", ß If statement in JSON
"operands": [
{
"operator": "&&", ß AND
"operands": [
{
"operator": "!=", ß Niet gelijk aan
"operands": [
"",
{
"operator": "toString()", ß omzetten naar een String van de laatste reviewdatum, we kunnen anders niet controleren of deze leeg is.
"operands": [
"[$Laatste%20reviewdatum]"
]
}
]
Zo ziet de hyperlink er zonder formatting uit met Flow, je kan de omschrijving nog niet rechtstreeks meenemen op een hyperlink veld in SharePoint.
Met het volgende script gebaseerd op: https://docs.microsoft.com/en-us/sharepoint/dev/declarative-customization/column-formatting#turn-field-values-into-hyperlinks-basic
Alleen zit hier weer de controle bij of de URL leeg is:
{
"$schema": "http://columnformatting.sharepointpnp.com/columnFormattingSchema.json",
"elmType": "a",
"txtContent": {
"operator": "?",
"operands": [
{
"operator": "==",
"operands": [
"",
{
"operator": "toString()",
"operands": [
"@currentField"
]
}
]
},
"@currentField",
"Flow geschiedenis"
]
}
,
"attributes": {
"target": "_blank",
"href": {
"operator": "+",
"operands": [
"",
"@currentField"
]
}
}
}
Zo dit ziet er al beter uit dan zonder de column formatting.
Je moet een heleboel stappen doorlopen voordat je een goedkeuringsworkflow gemaakt hebt. Nog niet alles kan met Flow of je hebt een heleboel stappen nodig om bijvoorbeeld parallel goed te keuren of een geschiedenislijst op te zetten.
Maar de eindgebruikers ervaring van de Approval taken uit Flow is veel beter dan de oude taken met SharePoint. Plus de zaken die je met de custom column formatter kunt doen leveren toegevoegde waarde voor de eindgebruiker.