Améliorations diverses
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# Power Query — exemples de connexion à l'API v1
|
||||
|
||||
Exemples de requêtes [Power Query](https://learn.microsoft.com/fr-fr/power-query/) (Excel)
|
||||
pour interroger le portefeuille crowdlending depuis un classeur Excel, en s'appuyant sur
|
||||
la même API v1 (lecture seule) que le [serveur MCP](../mcp-server/README.md).
|
||||
|
||||
Aucune écriture : ces requêtes ne font que lire des données, comme le serveur MCP.
|
||||
|
||||
## Prérequis
|
||||
|
||||
- Une clé API générée dans l'app : **Mon compte → Clés API → Nouvelle clé**
|
||||
- Le backend accessible (en local `http://localhost:4000`, ou l'URL de votre instance en
|
||||
production, ex. `https://crowdlending.croguennec.net`)
|
||||
- Excel avec Power Query (Excel 365 / 2016+ sous Windows ou Mac — Power Query est intégré
|
||||
nativement, rien à installer)
|
||||
|
||||
## Option 1 — Classeur prêt à l'emploi (`crowdlending-powerquery-exemple.xlsb`)
|
||||
|
||||
Le plus rapide : ouvrez `crowdlending-powerquery-exemple.xlsb` directement dans Excel.
|
||||
|
||||
> **Pourquoi un `.xlsb` et pas un `.xlsx` ?** Le format binaire d'Excel (`.xlsb`) est celui
|
||||
> à partir duquel ce classeur a pu être construit et vérifié de façon fiable en dehors
|
||||
> d'Excel. Il s'ouvre et se comporte exactement comme un `.xlsx` — Power Query, tableaux,
|
||||
> actualisation, tout fonctionne à l'identique. Si vous préférez un `.xlsx`, ouvrez le
|
||||
> fichier puis **Fichier → Enregistrer sous** et changez le format ; les requêtes suivent.
|
||||
|
||||
Le classeur contient :
|
||||
|
||||
| Requête | Rôle |
|
||||
|---|---|
|
||||
| `ApiBaseUrl` | URL de l'API à interroger (à modifier) |
|
||||
| `ApiKey` | Votre clé API (à modifier — voir ci-dessous) |
|
||||
| `fnApiGet` | Fonction utilitaire partagée (appel HTTP + parsing JSON), utilisée par toutes les requêtes de données |
|
||||
| `Investisseur` | Profil investisseur (ou liste des membres si clé « Famille et entreprises ») |
|
||||
| `Dashboard` | KPIs du portefeuille (capital investi, capital en risque, intérêts, cash), au format « Indicateur / Valeur » |
|
||||
| `Investissements` | Liste des investissements |
|
||||
| `Remboursements` | Historique des remboursements |
|
||||
| `DepotsRetraits` | Historique des mouvements de cash |
|
||||
| `fnDetailInvestissement` | Fonction avancée : détail + remboursements d'un investissement par id |
|
||||
| `Test` | Table d'instructions (« À lire avant de commencer ») — pas une donnée métier |
|
||||
|
||||
Étapes :
|
||||
|
||||
1. Ouvrez le classeur. La feuille affiche par défaut un exemple mis en cache (pas encore
|
||||
vos données) — c'est normal, Excel n'a pas encore appelé l'API.
|
||||
2. **Données → Requêtes et connexions**. Repérez `ApiKey` dans le volet à droite.
|
||||
3. Clic droit sur `ApiKey` → **Modifier**. Dans l'éditeur, remplacez
|
||||
`"clk_live_VOTRE_CLE_API"` par votre vraie clé (entre guillemets), puis
|
||||
**Fermer et charger**.
|
||||
4. Vérifiez `ApiBaseUrl` de la même façon : `http://localhost:4000/api/v1` en local, ou
|
||||
`https://crowdlending.croguennec.net/api/v1` en production (adaptez à votre domaine).
|
||||
5. **Données → Actualiser tout** (ou Ctrl+Alt+F5). La table « Test » se met à jour avec les
|
||||
instructions, signe que la connexion fonctionne.
|
||||
6. Pour chaque requête de données qui vous intéresse (`Investissements`, `Remboursements`…) :
|
||||
clic droit dans le volet **Requêtes et connexions** → **Charger dans…** → choisissez
|
||||
Tableau (ou Tableau croisé dynamique) et la feuille de destination.
|
||||
|
||||
## Option 2 — Coller les requêtes manuellement (`queries/*.pq`)
|
||||
|
||||
Utile si vous préférez tout construire vous-même dans un classeur existant, ou si une
|
||||
requête du classeur ne s'affiche pas correctement chez vous.
|
||||
|
||||
Pour chaque fichier, dans l'ordre ci-dessous : **Données → Obtenir des données → À partir
|
||||
d'autres sources → Requête vide**, renommez la requête (volet de droite, ou après double-clic
|
||||
sur son nom) avec **exactement** le nom du fichier (sans `.pq`), puis **Accueil → Éditeur
|
||||
avancé**, effacez le contenu par défaut, collez le contenu du fichier, **Terminé**.
|
||||
|
||||
Ordre à respecter (chaque requête réutilise les précédentes par leur nom) :
|
||||
|
||||
1. `ApiBaseUrl.pq` — modifiez l'URL avant de coller si besoin
|
||||
2. `ApiKey.pq` — remplacez `VOTRE_CLE_API` par votre clé avant de coller
|
||||
3. `fnApiGet.pq`
|
||||
4. `Investisseur.pq`, `Dashboard.pq`, `Investissements.pq`, `Remboursements.pq`,
|
||||
`DepotsRetraits.pq` — dans l'ordre que vous voulez
|
||||
5. `fnDetailInvestissement.pq` (optionnel, usage avancé — voir plus bas)
|
||||
|
||||
Une fois `fnApiGet` créée, **Fermer et charger** chaque requête de données individuellement
|
||||
(clic droit → Charger dans…) pour l'ajouter comme tableau.
|
||||
|
||||
## Filtres
|
||||
|
||||
Les requêtes `Dashboard`, `Investissements` et `Remboursements` acceptent des filtres côté
|
||||
API (année, statut, période). Par défaut elles ramènent tout (`null`). Pour filtrer,
|
||||
ouvrez la requête dans l'éditeur avancé et remplacez `null` par le paramètre indiqué en
|
||||
commentaire en tête du fichier `.pq` correspondant, par exemple :
|
||||
|
||||
```
|
||||
Source = fnApiGet("/investissements", [statut = "rembourse"])
|
||||
```
|
||||
|
||||
Statuts possibles : `en_cours`, `rembourse`, `en_retard`, `procedure`, `cloture`.
|
||||
|
||||
## Usage avancé — détail d'un investissement par ligne
|
||||
|
||||
`fnDetailInvestissement` permet de ramener, pour chaque ligne de la table `Investissements`,
|
||||
le détail complet (dont les remboursements) sans requête séparée : sur la table
|
||||
`Investissements`, **Ajout de colonne → Colonne personnalisée**, formule
|
||||
`= fnDetailInvestissement([id])`. Attention : ceci déclenche un appel API par ligne — à
|
||||
réserver à un nombre raisonnable d'investissements (quelques dizaines).
|
||||
|
||||
## Dépannage
|
||||
|
||||
- **`Impossible de se connecter au service distant`** — le backend n'est pas démarré, ou
|
||||
`ApiBaseUrl` est incorrecte (vérifiez le port et le suffixe `/api/v1`).
|
||||
- **`Erreur API (401)` / `Clé API invalide ou révoquée`** — régénérez une clé dans
|
||||
Mon compte → Clés API et remplacez la valeur de `ApiKey`.
|
||||
- **Une requête du classeur n'apparaît pas dans le volet, ou affiche une erreur au premier
|
||||
chargement** — repartez de l'Option 2 pour cette requête précise : créez une requête
|
||||
vide portant son nom et collez le contenu du `.pq` correspondant.
|
||||
- **Avertissement de sécurité / niveau de confidentialité au premier chargement** — normal
|
||||
pour toute nouvelle source Web dans Power Query ; choisissez « Organisationnel » ou
|
||||
« Public » selon votre contexte, ce n'est pas spécifique à ce classeur.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -0,0 +1,3 @@
|
||||
// URL de base de l'API v1. En local : http://localhost:4000/api/v1
|
||||
// En production : https://votre-domaine/api/v1
|
||||
"http://localhost:4000/api/v1"
|
||||
@@ -0,0 +1,2 @@
|
||||
// Clé API générée dans l'app : Mon compte > Clés API > Nouvelle clé
|
||||
"clk_live_VOTRE_CLE_API"
|
||||
@@ -0,0 +1,14 @@
|
||||
let
|
||||
// Pour filtrer sur une année, remplacez null par [annee = "2026"]
|
||||
Source = fnApiGet("/dashboard", null),
|
||||
VersLignes = (enregistrement as record, nomSection as text) =>
|
||||
Table.AddColumn(Record.ToTable(enregistrement), "Section", each nomSection),
|
||||
Combine = Table.Combine({
|
||||
VersLignes(Source[investissements], "Investissements"),
|
||||
VersLignes(Source[interets], "Interets"),
|
||||
VersLignes(Source[cash], "Cash")
|
||||
}),
|
||||
Reordonne = Table.ReorderColumns(Combine, {"Section", "Name", "Value"}),
|
||||
Resultat = Table.RenameColumns(Reordonne, {{"Name", "Indicateur"}, {"Value", "Valeur"}})
|
||||
in
|
||||
Resultat
|
||||
@@ -0,0 +1,5 @@
|
||||
let
|
||||
Source = fnApiGet("/depots-retraits", null),
|
||||
Resultat = Table.FromRecords(Source)
|
||||
in
|
||||
Resultat
|
||||
@@ -0,0 +1,7 @@
|
||||
let
|
||||
// Pour filtrer par statut, remplacez null par [statut = "rembourse"]
|
||||
// Statuts possibles : en_cours, rembourse, en_retard, procedure, cloture
|
||||
Source = fnApiGet("/investissements", null),
|
||||
Resultat = Table.FromRecords(Source)
|
||||
in
|
||||
Resultat
|
||||
@@ -0,0 +1,6 @@
|
||||
let
|
||||
Source = fnApiGet("/investisseur", null),
|
||||
// Clé "Famille et entreprises" -> liste ; clé mono-investisseur -> objet unique
|
||||
Resultat = if Value.Is(Source, type list) then Table.FromRecords(Source) else Table.FromRecords({Source})
|
||||
in
|
||||
Resultat
|
||||
@@ -0,0 +1,6 @@
|
||||
let
|
||||
// Pour filtrer par période, remplacez null par [date_debut = "2026-01-01", date_fin = "2026-12-31"]
|
||||
Source = fnApiGet("/remboursements", null),
|
||||
Resultat = Table.FromRecords(Source)
|
||||
in
|
||||
Resultat
|
||||
@@ -0,0 +1,19 @@
|
||||
(chemin as text, optional parametres as nullable record) as any =>
|
||||
let
|
||||
parametresBruts = if parametres = null then [] else parametres,
|
||||
champsUtiles = List.Select(
|
||||
Record.FieldNames(parametresBruts),
|
||||
each Record.Field(parametresBruts, _) <> null and Record.Field(parametresBruts, _) <> ""
|
||||
),
|
||||
parametresNettoyes = Record.SelectFields(parametresBruts, champsUtiles),
|
||||
reponse = Web.Contents(
|
||||
ApiBaseUrl,
|
||||
[
|
||||
RelativePath = chemin,
|
||||
Headers = [#"X-API-Key" = ApiKey, #"Accept" = "application/json"],
|
||||
Query = parametresNettoyes
|
||||
]
|
||||
),
|
||||
resultat = Json.Document(reponse)
|
||||
in
|
||||
resultat
|
||||
@@ -0,0 +1,5 @@
|
||||
// Astuce avancée : sur la table Investissements, colonne personnalisée
|
||||
// "= fnDetailInvestissement([id])" pour ramener le détail + les remboursements
|
||||
// de chaque prêt (Ajout de colonne > Colonne personnalisée).
|
||||
(id as number) as record =>
|
||||
fnApiGet("/investissements/" & Text.From(id), null)
|
||||
Reference in New Issue
Block a user