7.0 KiB
csv-to-timemanager.py — Spécifications d'importation
Objectif
Le script csv-to-timemanager.py lit des fichiers CSV configurés dans config.json et envoie des requêtes vers l'API Nextcloud TimeManager pour créer ou mettre à jour :
- clients,
- projets,
- tâches,
- entrées de temps.
Il utilise aussi une base MySQL locale pour vérifier l'existence des objets et éviter les doublons.
Sources des données
Le script traite les entrées de chaque CSV listé sous config['calendars'].
Chaque entrée doit contenir au minimum :
csv_name: chemin du fichier CSV à importer,user_name: login Nextcloud utilisé pour authentifier les requêtes,api_password: mot de passe ou mot de passe d'application Nextcloud.
Colonnes CSV utilisées
Pour chaque ligne du CSV, le script utilise précisément ces colonnes :
Description→ nom du client TimeManagerCategories→ nom du projet TimeManagerTitre→ nom de la tâche TimeManagerDate debut→ date de début de l'entrée de tempsHeure debut→ heure de début de l'entrée de tempsDate fin→ date de fin de l'entrée de tempsHeure fin→ heure de fin de l'entrée de temps
Correspondance vers TimeManager
| Colonne CSV | Entité TimeManager | Champ TimeManager / usage |
|---|---|---|
Description |
client | name du client |
Categories |
project | name du projet |
Titre |
task | name de la tâche |
Date debut |
time entry | start (date + heure) |
Heure debut |
time entry | start (date + heure) |
Date fin |
time entry | end (date + heure) |
Heure fin |
time entry | end (date + heure) |
Traitements appliqués
-
Lecture du CSV
- Le fichier est lu avec
csv.reader(..., delimiter=';'). - La première ligne est traitée comme en-tête et sert à associer chaque colonne à une clé de dictionnaire.
- Le fichier est lu avec
-
Nettoyage des chaînes de texte
sanitize(chain):- retire tous les caractères sauf lettres, chiffres et espaces,
- applique
unidecodepour normaliser les accents, strip()pour enlever les espaces en début/fin,capitalize()pour mettre la première lettre en majuscule.
sanitize_date(chain):- conserve aussi les caractères
-et:supplémentaires (utile pour les dates/heures), - applique les mêmes normalisations que
sanitize.
- conserve aussi les caractères
-
Création / existence d'objets
- Chaque entité est créée indépendamment si elle n'existe pas :
- Si le client
Descriptionn'existe pas, il est créé viacreate_client(). - Si le projet
Categoriesn'existe pas (pour ce client), il est créé viacreate_project(). - Si la tâche
Titren'existe pas (pour ce projet), elle est créée viacreate_task().
- Si le client
- Les actions de création appellent l'API
updateObjectsavec un payload minimal contenant l'entité concernée.
- Chaque entité est créée indépendamment si elle n'existe pas :
-
Insertion d'une entrée de temps
- Le script construit
startetenden concaténantDate debut + Heure debutetDate fin + Heure fin. - Il envoie ensuite un objet
times.createdà l'APIupdateObjects.
- Le script construit
Validation et gestion des doublons
- Avant d'ajouter une entrée de temps, le script vérifie si une entrée identique existe déjà dans la base :
- il cherche d'abord une entrée avec les mêmes
user_id,start(date+heure début) etend(date+heure fin). - si une telle entrée existe, il valide que le
task, leprojectet leclientcorrespondent. - si tous les critères correspondent, l'import est ignoré pour éviter un doublon.
- il cherche d'abord une entrée avec les mêmes
- Important : deux entrées avec les mêmes client/projet/tâche mais à des heures différentes créent 2 entrées TimeManager distinctes (elles ne sont pas considérées comme des doublons).
Gestion des données manquantes
- Si
user_nameouapi_passwordmanque dans la configuration pour un calendrier, ce calendrier est ignoré. - Dans le CSV, si
client_name(Description) etproject_name(Categories) sont tous deux vides, la ligne est ignorée. - Si le client existe mais que son UUID ne peut pas être récupéré après création, le traitement de la ligne est abandonné avec un message d'erreur.
- Limitations actuelles (risque) : Le script ne valide pas que
Titre,Date debut,Heure debut,Date finouHeure finsont présents :- Si
Titreest vide, une tâche avec un nom vide peut être créée ou recherchée. - Si
Date debut,Heure debut,Date finouHeure finsont vides, une entrée de temps avecstartouendincomplet sera créée. - Ce comportement est indésirable et devrait être amélioré (voir
docs/todo.md).
- Si
Cas particuliers
- Pour l'existence d'un client/projet/tâche, la comparaison se fait avec les noms nettoyés (
sanitize) et uniquement les objets dontstatus != "deleted". create_client()retourne maintenant l'UUID extrait de la réponse API si disponible. Si la réponse ne contient pas d'UUID, le script effectue une seconde récupération via la base de données.create_project()etcreate_task()ne retournent pas d'UUID : ils comptent sur les recherches suivantes (get_project_uuid_by_name,get_task_uuid_by_name) pour retrouver l'objet créé.
Notes d'implémentation
- Les requêtes vers TimeManager utilisent toujours
POST /api/updateObjects. - Les objets envoyés contiennent des champs vides (
uuid,commit,created,changed) pour laisser le serveur les remplir si nécessaire. - Le script n'envoie pas de données de
deletedouupdated: il se contente de créer des objets danscreated.
Résumé rapide
Le script transforme chaque ligne CSV en un client/projet/tâche puis une entrée de temps, en appliquant un nettoyage de texte simple et en évitant le double-import des mêmes périodes.
Champs obligatoires pour créer une entrée de temps
Pour qu'une ligne CSV soit importée avec succès en tant qu'entrée de temps TimeManager, les champs suivants doivent être renseignés :
Description: non vide (nom du client) OUCategories: non vide (nom du projet) — au moins un des deux.Categories: non vide (nom du projet).Titre: non vide (nom de la tâche).Date debut: non vide et valide.Heure debut: non vide et valide.Date fin: non vide et valide.Heure fin: non vide et valide.
Note actuellement : le script ne valide pas strictement ces conditions. Il est recommandé d'améliorer ce point (voir docs/todo.md).
Le point clef est que seules les colonnes suivantes sont exploitées :
Description, Categories, Titre, Date debut, Heure debut, Date fin, Heure fin.