Comment planifier des inspections d’installation récurrentes dans Workforce for ArcGIS

April 8, 2020

Workforce for ArcGIS est une application formidable pour répartir les tâches sur le terrain ainsi que pour faire le suivi en temps réel de l’emplacement du personnel et de l’avancement des affectations. Dans cet article, je vous explique comment faire en sorte que vos affectations se répètent automatiquement à une fréquence déterminée à l’aide de quelques personnalisations.

Workforce for ArcGIS permet aux utilisateurs de créer des affectations au bureau et de les envoyer au personnel de terrain, qui peut ensuite les réaliser sur place. L’application comprend une interface utilisateur conçue pour fournir en temps réel un maximum de renseignements sur l’état d’avancement des affectations et l’emplacement des utilisateurs. Il est également possible d’intégrer des affectations Workforce à d’autres applications ArcGIS comme Collector et Survey123, qui servent alors de base pour effectuer un large éventail de tâches sur le terrain.

Dans cet article, je vous explique comment effectuer de petites personnalisations pour faire en sorte que vos affectations Workforce se répètent automatiquement à une fréquence facile à configurer. Imaginons que vous êtes superviseur d’une équipe chargée d’effectuer plusieurs inspections récurrentes sur des installations municipales.

Type d’inspection Fréquence
Inspection des installations 6 mois
Inspection des systèmes de chauffage, de ventilation et de climatisation 12 mois (printemps)
Inspection des chaudières 12 mois (automne)
Inspection de sécurité 3 mois

Même si ces tâches peuvent être configurées manuellement selon les besoins de l’équipe, vous amélioriez l’efficacité et la fiabilité de vos activités en automatisant la création de ces affectations récurrentes. Voici les étapes nécessaires pour y arriver.

Étape 1 – créer un projet Workforce

Créez un projet Workforce comme vous le feriez habituellement et configurez-le selon vos besoins (par exemple, ajoutez votre couche de bâtiments à la carte web de répartition).

Étape 2 – créer des types d’affectation

Ensuite, créez les types d’affectation en suivant le processus habituel présenté à l’onglet Assignment Types (types d’affectation) de la page Workforce Configuration (configuration Workforce). Si vous prévoyez ajouter des affectations planifiées automatiquement et des affectations créées manuellement à votre projet, il est recommandé de configurer des types d’affectation et de leur attribuer une description afin de faciliter la sélection et la gestion des tâches.

Étape 3 – créer des affectations

Créez le premier ensemble d’affectations pour chacune des installations. La date d’échéance de chaque affectation correspond à la date d’échéance de l’inspection à venir.

Étape 4 – créer des champs pour gérer la fréquence

Nous devons maintenant ajouter deux nouveaux champs à la couche d’affectations que vous avez créée dans le projet Workforce (cliquez ici pour en savoir plus sur le modèle de données de Workforce). Le premier champ (cycle) permettra de désigner les affectations à répéter à une fréquence déterminée. Le deuxième champ (cycleFrequency) correspondra à la fréquence en jours.

Étape 5 – définir la fréquence du cycle

Une fois ces deux champs ajoutés, inscrivez la valeur 1 au champ « cycle » afin de désigner les affectations récurrentes et précisez la fréquence en jours au champ « cycleFrequency ».

Étape 6 – exécuter le script

Nous devons maintenant employer un script Python, qui sera exécuté sur un serveur en arrière-plan, afin de répéter les affectations récurrentes au fur et à mesure qu’elles sont effectuées sur le terrain. Heureusement pour nous, nous n’avons pas à créer de script, car nous pouvons réutiliser le script « Create Workforce assignments » fourni dans la solution ArcGIS permettant aux citoyens de signaler des problèmes. Ce script est conçu pour générer des affectations Workforce basées sur les demandes transmises par le public à partir du modèle Citizen Problem Reporter. Il suffit de consulter la documentation détaillée pour configurer le script et l’exécuter à une fréquence déterminée à l’aide du Planificateur de tâches de Windows. Puisqu’il s’agit en fait de créer des affectations Workforce à partir d’une couche d’entités en ligne, nous pouvons réutiliser ce script pour concevoir des affectations Workforce basées sur... la même couche d’affectations Workforce.

Vous pouvez suivre la documentation fournie au lien ci-dessus pour configurer les paramètres de base du script. Voici quelques recommandations pour créer des affectations récurrentes :

  • ‘source url’ et ‘target url’ – ces deux champs doivent faire référence à la même couche d’affectations Workforce;

  • ‘query’ – entrez l’expression SQL suivante : ‘status=3 AND cycle=1’. Cette configuration permet de déterminer les affectations Workforce terminées (status=3) qui doivent être répétées (cycle=1);

  • ‘fields’ – ces paires de champs définissent les données qui seront copiées de l’affectation terminée vers l’affectation à créer. Comme nous voulons nous assurer que l’affectation est répétée à une fréquence déterminée, il faut que la valeur des champs « assignmentType », « cycle », « cycleFrequency » et « location » soit transférée à la prochaine affectation;

  • ‘update field’ – la valeur de ce champ correspond à celle du champ « cycle »;

  • ‘update value’ – la valeur doit être 2. De cette façon, les affectations à répéter sont désignées par le chiffre 1 et celles ayant été déjà répétées, par le chiffre 2.

Une fois les affectations Workforce créées dans le script, nous devons faire en sorte que la date d’échéance de la prochaine affectation soit déterminée en fonction de la date d’achèvement de l’affectation en cours. Pour ce faire, il faut d’abord configurer un paramètre « nextDueDate » et utiliser sa valeur comme date d’échéance de l’affectation suivante.

nextDueDate = row.attributes['completedDate']+(row.attributes['cycleFrequency']*3600000)                    
attributes = {'status': 0,
'priority': 0,
'dueDate': nextDueDate}

Vous trouverez ci-dessous un exemple de script configuré selon les recommandations ci-dessus. En utilisant cette approche, vous pouvez définir vos affectations récurrentes avec vos fréquences directement à partir de la couche d’entités. Tant que les champs « cycle » et « cycleFrequency » sont remplis, le script répétera les affectations au fur et à mesure qu’elles sont réalisées.

# ------------------------------------------------------------------------------
# Name:        create_workforce_assignments.py
# Purpose:     generates identifiers for features

# Copyright 2017 Esri

#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

# ------------------------------------------------------------------------------

from datetime import datetime as dt
from os import path, sys
from arcgis.gis import GIS
from arcgis.features import FeatureLayer

orgURL = 'https://XXXXX.maps.arcgis.com/'     # URL to ArcGIS Online organization or ArcGIS Portal
username = 'XXXXX'   # Username of an account in the org/portal that can access and edit all services listed below
password = 'XXXXX'   # Password corresponding to the username provided above

services = [{'source url': 'https://services9.arcgis.com/Yu2UzT0Yprgwp7dx/arcgis/rest/services/assignments_839f4e6983a148fd9307b0a48053fe6b/FeatureServer/0',
             'target url': 'https://services9.arcgis.com/Yu2UzT0Yprgwp7dx/arcgis/rest/services/assignments_839f4e6983a148fd9307b0a48053fe6b/FeatureServer/0',
             'query': 'status=3 AND cycle=1',
             'fields': {
                 'assignmentType': 'assignmentType',
				 'cycleFrequency':'cycleFrequency',
				 'cycle':'cycle',
                 'location':'location'},
             'update field': 'cycle',
             'update value': '2'
             }]

def main():
    # Create log file
    with open(path.join(sys.path[0], 'attr_log.log'), 'a') as log:
        log.write('\n{}\n'.format(dt.now()))

        # connect to org/portal
        gis = GIS(orgURL, username, password)

        for service in services:
            try:
                # Connect to source and target layers
                fl_source = FeatureLayer(service['source url'], gis)
                fl_target = FeatureLayer(service['target url'], gis)

                # get field map
                fields = [[key, service['fields'][key]] for key in service['fields'].keys()]

                # Get source rows to copy
                rows = fl_source.query(service['query'])
                adds = []
                updates = []

                for row in rows:
                    # Build dictionary of attributes & geometry in schema of target layer
                    # Default status and priority values can be overwritten if those fields are mapped to reporter layer
                    nextDueDate = row.attributes['completedDate']+(row.attributes['cycleFrequency']*86400000)                    
                    attributes = {'status': 0,
                                  'priority': 0,
                                  'dueDate': nextDueDate}

                    for field in fields:
                        attributes[field[1]] = row.attributes[field[0]]

                    new_request = {'attributes': attributes,
                                   'geometry': {'x': row.geometry['x'],
                                                'y': row.geometry['y']}}
                    adds.append(new_request)

                    # update row to indicate record has been copied
                    if service['update field']:
                        row.attributes[service['update field']] = service['update value']
                        updates.append(row)

                # add records to target layer
                if adds:
                    add_result = fl_target.edit_features(adds=adds)
                    for result in add_result['updateResults']:
                        if not result['success']:
                            raise Exception('error {}: {}'.format(result['error']['code'],
                                                                  result['error']['description']))

                # update records:
                if updates:
                    update_result = fl_source.edit_features(updates=updates)
                    for result in update_result['updateResults']:
                        if not result['success']:
                            raise Exception('error {}: {}'.format(result['error']['code'],
                                                                  result['error']['description']))

            except Exception as ex:
                msg = 'Failed to copy feature from layer {}'.format(service['url'])
                print(ex)
                print(msg)
                log.write('{}\n{}\n'.format(msg, ex))

if __name__ == '__main__':
    main()

Ce billet a été écrit en anglais par Chaim Schwartz et peut être consulté ici.

Article précédent
Soutenir les travaux publics et leur personnel pendant la pandémie de COVID-19
Soutenir les travaux publics et leur personnel pendant la pandémie de COVID-19

Cet article passe en revue les méthodes et les outils que les travaux publics peuvent utiliser pour protége...

Article suivant
Analyse des bris de conduites d’aqueduc dans la région de Peel
Analyse des bris de conduites d’aqueduc dans la région de Peel

Ce billet montre comment l’analyse de plus de 10 ans de données sur les bris de conduites d’aqueduc a permi...