Passer au contenu principal

Liste des API

API dans l'ordre d'importance

1) Liste des établissements - Données locales https://portail.ac-reunion.fr/swami/public/api/etablissements/

Importation du fichier vierge avec les têtes de colonne dans GRIST : Annuaire-ETAB-ACA-ALL.csv

Ce code permet d'ajouter, de corriger les établissements mis à jour.

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>Import Lycées La Réunion</title>
    <script src="https://docs.getgrist.com/grist-plugin-api.js"></script>
    <style>
        #importEtabBtn {
            margin: 10px;
            padding: 10px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-family: sans-serif;
            font-size: 14px;
            transition: background-color 0.3s;
        }
        #importEtabBtn:hover:not(:disabled) {
            background-color: #45a049;
        }
        #importEtabBtn:disabled {
            background-color: #cccccc;
            cursor: not-allowed;
        }
    </style>
</head>
<body>
    <div style="font-family: sans-serif; padding: 1em;">
        <h2>Import des établissements</h2>
        <p>Cliquez sur le bouton ci-dessous pour mettre à jour la table **"Annuaire_ETAB_ACA_ALL"**.</p>
        <button id="importEtabBtn">Mettre à jour l'annuaire</button>
        <p id="status" style="margin-top: 10px; color: #666;"></p>
    </div>

    <script>
        // Demande un accès complet pour lire et écrire
        grist.ready({ requiredAccess: 'full' });
        
        // Liste des noms de colonnes pour la cohérence
        const COLUMN_NAMES = [
            "uaj", "nom", "denominationOfficielle", "uajDenominationOfficielle",
            "type", "rue", "bassin", "code_postal", "ville", "tel", "fax", "mail", "lat", "lon"
        ];

        /**
         * Récupère les données d'établissements via l'API externe.
         */
        async function fetchEtab() {
            const apiUrl = "https://portail.ac-reunion.fr/swami/public/api/etablissements/";
            try {
                document.getElementById("status").textContent = "Récupération des données en cours...";
                const response = await fetch(apiUrl);
                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}`);
                }
                const data = await response.json();
                const results = data.data?.values || [];
                document.getElementById("status").textContent = `${results.length} établissements trouvés.`;
                return results;
            } catch (error) {
                document.getElementById("status").textContent = `Erreur : ${error.message}`;
                console.error("Erreur API :", error);
                return [];
            }
        }

        /**
         * Met à jour (UpdateRecord) ou insère (AddRecord) les enregistrements.
         */
        async function upsertIntoGristOptimized(etabs) {
            document.getElementById("status").textContent = "Préparation des mises à jour en cours...";
            const tableId = "Annuaire_ETAB_ACA_ALL";
            const uajColumn = "uaj";

            // 1. LECTURE : Récupération des enregistrements existants (docApi.fetchTable est fiable)
            const allRecords = await grist.docApi.fetchTable(tableId, ['id', uajColumn]);
            
            // Création de la Map de recherche rapide
            const uajToIdMap = new Map();
            if (allRecords[uajColumn]) {
                 allRecords[uajColumn].forEach((uaj, index) => {
                     uajToIdMap.set(uaj, allRecords.id[index]);
                 });
            }

            const actions = []; // Liste des actions à envoyer
            let createdCount = 0;
            let updatedCount = 0;

            for (const etab of etabs) {
                const recordId = uajToIdMap.get(etab.uaj);
                
                // Construction de l'objet d'enregistrement (format clé-valeur)
                const recordObject = {};
                COLUMN_NAMES.forEach(col => {
                    const value = etab[col];
                    // Assurer que les valeurs manquantes sont correctement traitées
                    if (value !== undefined && value !== null) {
                        recordObject[col] = value;
                    } else if (["rue", "bassin", "fax", "mail"].includes(col)) {
                        recordObject[col] = ""; // Les champs texte optionnels doivent être des chaînes vides
                    } else {
                        recordObject[col] = null; // Autres champs (nombre/lien) sont null
                    }
                });

                if (recordId) {
                    // MISE À JOUR (Action Ligne par Ligne)
                    // Format: ['UpdateRecord', TableID, RowID, RecordObject]
                    actions.push(
                        ['UpdateRecord', tableId, recordId, recordObject] 
                    );
                    updatedCount++;
                } else {
                    // CRÉATION (Action Ligne par Ligne)
                    // Format: ['AddRecord', TableID, RowID (null), RecordObject]
                    actions.push(
                        ['AddRecord', tableId, null, recordObject] 
                    );
                    createdCount++;
                }
            }
            
            // 2. ENVOI DES ACTIONS
            if (actions.length > 0) {
                document.getElementById("status").textContent = `Envoi de ${actions.length} opérations à Grist... (peut prendre du temps)`;
                // Envoi de toutes les actions (créations + mises à jour ligne par ligne)
                await grist.docApi.applyUserActions(actions);
            }

            return { created: createdCount, updated: updatedCount };
        }

        /**
         * Fonction principale déclenchée par le bouton.
         */
        async function importEtab() {
            const btn = document.getElementById("importEtabBtn");
            btn.disabled = true;
            btn.textContent = "Importation en cours...";

            try {
                const etabs = await fetchEtab();
                if (etabs.length > 0) {
                    document.getElementById("status").textContent = "Mise à jour de la base en cours...";
                    const result = await upsertIntoGristOptimized(etabs);
                    document.getElementById("status").textContent =
                        `✅ **${result.created}** établissements ajoutés, **${result.updated}** établissements mis à jour.`;
                } else {
                    document.getElementById("status").textContent = "Aucun établissement trouvé à traiter.";
                }
            } catch (error) {
                 document.getElementById("status").textContent = "❌ Une erreur critique est survenue. Vérifiez la console (F12) et l'accès.";
                 console.error("Erreur critique d'importation :", error);
            } finally {
                btn.disabled = false;
                btn.textContent = "Mettre à jour l'annuaire";
            }
        }

        document.getElementById("importEtabBtn").addEventListener("click", importEtab);
    </script>
</body>
</html>