# Langage de requête des widgets

Référence de la syntaxe texte qui décrit les données d’un widget : mesures, conditions, regroupements, période, tri et fonctions.

> **Accès :** droit de modification sur le tableau de bord. Voir [Configurer un widget](https://docs.cisapp.eu/pilotage/widgets) pour l’éditeur.

## Écrire une requête en texte

1. Dans l’éditeur du widget, repérez la ligne de requête (**a**, **b**…).
2. Basculez de **Formulaire** à **Code**.
3. Saisissez la requête. L’éditeur propose des **Suggestions** (mesures, données, clauses, champs, valeurs) et signale les erreurs avec leur position.

Le texte décrit toute la requête et équivaut au formulaire : vous passez de l’un à l’autre sans perte. La requête est appliquée dès qu’elle est valide. Le sélecteur **Plans d’action** se règle uniquement dans le formulaire.

```
count(ticket) where status IN (TODO, BLOCKED) by priority split assignee
```

## Structure

Une requête commence par `mesure(données)`, suivie de clauses, dans n’importe quel ordre et chacune au plus une fois.

| Clause | Sens | Exemple |
|---|---|---|
| `where …` | Conditions sur les éléments comptés. | `where status != DONE` |
| `of …` | Avec `percent` : part des éléments qui vérifient la condition. | `percent(riskMeasure) of status = VERIFIED` |
| `by champ` | Regrouper. Pour une date : `by champ:day`, `week`, `month`, `quarter` ou `year`. | `by createdAt:month` |
| `split champ` | Séparer par un second champ. | `split assignee` |
| `columns a, b` | Avec `list` : colonnes de la liste (8 maximum). | `columns title, owner` |
| `during …` | Période : `last7d`, `last30d`, `last90d`, `last12m`, `ytd`, `all`, ou `"2026-01-01" to "2026-03-31"`. | `during last12m` |
| `on champ` | Champ de date auquel s’applique la période. | `on dueDate` |
| `sort …` | Tri : `value` ou `key` pour un regroupement, un champ pour une liste, puis `asc` ou `desc`. | `sort value desc` |
| `limit n` | Nombre maximum de lignes ou de groupes (200 maximum). | `limit 10` |

## Mesures

| Mesure | Sens |
|---|---|
| `count(ticket)` | Nombre d’éléments. |
| `sum`, `avg`, `min`, `max`, `median` | Calcul sur un champ numérique : `avg(vendor.criticality)`. |
| `distinctCount(ticket.assignee)` | Nombre de valeurs distinctes. |
| `percent(ticket)` | Pourcentage, avec la clause `of`. |
| `list(ticket)` | Liste d’éléments, avec la clause `columns`. |

## Données

| Code | Données |
|---|---|
| `vendor` | Fournisseurs |
| `risk`, `riskMeasure` | Risques, mesures de traitement |
| `incident` | Incidents |
| `control`, `evidence` | Contrôles, preuves |
| `exemption` | Dérogations |
| `evaluation` | Évaluations |
| `asset`, `finding` | Actifs, vulnérabilités |
| `application` | Applications |
| `scope` | Activités |
| `processingActivity` | Traitements RGPD |
| `connector` | Connecteurs |
| `project`, `ticket` | Plans d’action, tâches |

Les données proposées dépendent des modules de votre offre.

## Conditions

Les clauses `where` et `of` contiennent des conditions, combinées par `AND`, `OR`, `NOT` et des parenthèses. `AND` est prioritaire sur `OR`.

```
criticality >= 3 AND status = ACTIVE AND (cf."SSO" = false OR cf."SSO" IS EMPTY)
```

| Opérateur | Sens | Exemple |
|---|---|---|
| `=` `!=` | Égal, différent. | `status = ACTIVE` |
| `>` `>=` `<` `<=` | Comparaison de nombres ou de dates. | `criticality >= 3` |
| `~` | Contient (texte). | `name ~ "bank"` |
| `IN (…)` `NOT IN (…)` | Parmi, pas parmi. | `status IN (ACTIVE, ONBOARDING)` |
| `ALL (…)` | Contient toutes les valeurs (champs à valeurs multiples). | `tags ALL ("critique", "UE")` |
| `BETWEEN … AND …` | Entre deux valeurs. | `dueDate BETWEEN 2026-01-01 AND 2026-03-31` |
| `IS EMPTY` `IS NOT EMPTY` | Vide, renseigné. | `assignee IS EMPTY` |

Les opérateurs disponibles dépendent du type de champ. Une requête compte au plus 20 conditions et 4 niveaux de parenthèses.

## Champs et valeurs

- **Champs** : utilisez le nom technique proposé par les suggestions (`status`, `criticality`, `assignee`, `dueDate`…). Un champ personnalisé s’écrit `cf."Nom du champ"`.
- **Texte** entre guillemets : `"Implémentation SSO"`.
- **Nombres** : `3`, `0.5`. **Booléens** : `true`, `false`. **Dates** : `2026-03-31`.
- **Valeurs fixes** (statut, type…) : le code ou le libellé ; les suggestions affichent le libellé.
- **Références** (utilisateur, équipe, plan d’action, fournisseur) : le nom entre guillemets, par exemple `project = "Implémentation SSO"`. CISAPP enregistre l’identifiant : le widget continue de fonctionner si l’élément est renommé.

## Fonctions

| Fonction | Valeur |
|---|---|
| `me()` | L’utilisateur qui consulte le tableau de bord. |
| `myTeams()` | Ses équipes. |
| `now()` | Maintenant ; `now(-30d)` il y a 30 jours (`d` jours, `w` semaines, `m` mois, `y` années). |
| `startOf(month)` | Début de la période : `day`, `week`, `month`, `quarter`, `year`. |

Avec `me()` ou `myTeams()`, chaque lecteur voit ses propres chiffres. Un tel widget ne peut pas suivre d’historique.

## Exemples

```
count(ticket) where assignee = me() AND status != DONE by priority
percent(riskMeasure) where status != PLANNED of dueDate < now()
avg(vendor.criticality) by createdAt:month during last12m
list(risk) columns title, owner, residualCriticality where open = true sort residualScore desc limit 10
count(ticket) where createdAt >= startOf(month)
```

## Résultat attendu

La requête est acceptée sans message d’erreur, l’aperçu du widget affiche les données attendues, et la bascule **Formulaire** montre les mêmes réglages.

## Difficultés courantes

| Message | Cause |
|---|---|
| Champ « x » inconnu | Faute de frappe, ou champ personnalisé supprimé. |
| Guillemet non fermé | Un texte entre guillemets n’est pas terminé. |
| Valeur « x » inconnue | La valeur n’existe pas pour ce champ. |
| Requête incomplète | La requête s’arrête au milieu d’une clause ou d’une condition. |
| Mesure « x » inconnue | La requête doit commencer par une mesure : `count(…)`, `avg(…)`… |
| Données « x » inconnues | Le nom entre parenthèses n’est pas une donnée de la liste ci-dessus. |
| … demande un champ | `sum`, `avg`, `min`, `max`, `median` et `distinctCount` portent sur un champ : `avg(vendor.criticality)`. |
| Le champ « x » n’est pas utilisable dans « by » | Ce champ ne peut pas servir à regrouper, séparer, trier ou afficher en colonne. |
| La clause « x » n’est pas disponible | `of` va avec `percent`, `columns` avec `list` ; une liste n’a ni `by` ni `split`. |
| La clause « x » apparaît deux fois | Chaque clause ne s’écrit qu’une fois. |
| L’opérateur … n’est pas disponible pour le champ … | Choisissez un opérateur adapté au type du champ. |
| Trop de conditions / Trop de parenthèses imbriquées | Au plus 20 conditions et 4 niveaux. |
