Questionnaires

Orienter le visiteur vers la réponse qui le concerne.

Chaque réponse porte des poids vers un ou plusieurs profils. Le profil dont le total est le plus élevé détermine la page de résultat affichée — une page composée dans l'éditeur, comme n'importe quelle autre.

Le mécanisme

Un questionnaire se compose de quatre objets. Les comprendre suffit à en construire n'importe lequel.

Le test

Son titre, son slug, sa page de présentation. Il naît inactif : un questionnaire à moitié construit rendrait des résultats faux.

Les profils

Les résultats possibles. Chacun désigne la page affichée à qui l'obtient, et peut aussi s'attribuer par score global.

Les questions

À choix unique ou multiple, ordonnées. Une question inactive reste modifiable mais n'est plus posée.

Les poids

Portés par chaque réponse, vers un ou plusieurs profils. C'est la seule matière du calcul.

1 — Créer le test

Il naît inactif. On l'active quand profils, questions et poids sont posés.

POST /api/agent/v1/questionnaires/creer/
{
  "titre": "Quel accompagnement vous correspond ?",
  "slug": "quel-accompagnement",
  "description": "Huit questions, deux minutes.",
  "page_de_presentation": 118
}

→ 201  { "questionnaire": { "id": 4, "actif": false } }

2 — Déclarer les profils

Chaque profil désigne la page affichée à qui l'obtient. Les deux premiers s'obtiennent par les poids ; le troisième par un score global, ce qui permet de rattraper les profils indécis.

POST /api/agent/v1/questionnaires/4/profils/
{ "nom": "Autonome", "slug": "autonome",
  "description": "Sait où il va, cherche un outil.",
  "page_de_resultat": 120 }

POST /api/agent/v1/questionnaires/4/profils/
{ "nom": "Accompagné", "slug": "accompagne",
  "page_de_resultat": 121 }

POST /api/agent/v1/questionnaires/4/profils/
{ "nom": "En réflexion", "slug": "en-reflexion",
  "page_de_resultat": 122,
  "attribue_par_score": true,
  "score_min": 0, "score_max": 6 }

3 — Poser une question et ses poids

Les poids sont la matière du calcul. Une réponse peut alimenter plusieurs profils, avec des intensités différentes — c'est ce qui évite les questionnaires binaires.

POST /api/agent/v1/questionnaires/4/questions/
{
  "texte": "Où en êtes-vous de votre site actuel ?",
  "type": "single",
  "rang": 1,
  "reponses": [
    { "texte": "Je n'en ai pas encore",
      "poids": { "accompagne": 3, "en-reflexion": 2 } },
    { "texte": "J'en ai un, il ne me convient plus",
      "poids": { "autonome": 2, "accompagne": 2 } },
    { "texte": "J'en ai un et je veux le piloter moi-même",
      "poids": { "autonome": 4 } }
  ]
}

4 — Une question à choix multiple

Les poids de toutes les réponses cochées s'additionnent. Utile pour les questions d'usage, où plusieurs réponses coexistent.

POST /api/agent/v1/questionnaires/4/questions/
{
  "texte": "Que devez-vous gérer ? (plusieurs réponses)",
  "type": "multiple",
  "rang": 2,
  "reponses": [
    { "texte": "Une boutique",
      "poids": { "autonome": 1, "accompagne": 2 } },
    { "texte": "Des rendez-vous",
      "poids": { "accompagne": 2 } },
    { "texte": "Des formations",
      "poids": { "accompagne": 3 } },
    { "texte": "Rien de tout cela pour l'instant",
      "poids": { "en-reflexion": 3 } }
  ]
}

5 — Arbitrer deux profils trop proches

Quand deux profils arrivent au coude à coude, le plus lourd ne dit pas toujours la bonne chose. Une combinaison décrit ce cas : « si l'écart entre Autonome et Accompagné est inférieur ou égal à 2, montrer Accompagné ».

POST /api/agent/v1/questionnaires/4/combinaisons/
{
  "titre": "Autonome ou accompagné",
  "profil_parent":     "autonome",
  "profil_prefere":    "accompagne",
  "profil_alternatif": "autonome",
  "criteres": [
    { "profil_a": "autonome",
      "profil_b": "accompagne",
      "comparaison": "~=",
      "tolerance": 2 }
  ]
}

→ « ~= » sans tolérance est REFUSÉ : le critère
   reviendrait à une égalité stricte

6 — Composer la page de résultat

La page de résultat est une page ordinaire. Les jetons y sont remplacés au moment du rendu par les valeurs du passage. Rien qui identifie le visiteur n'y est exposé : l'adresse d'un résultat circule par e-mail.

PUT /api/agent/v1/blocs/604/contenu/
{
  "type": "TEXT",
  "texte": "

[%profil%]

[%profil_description%]

Score obtenu : [%score%]

" } Jetons disponibles : [%profil%] nom du profil obtenu [%profil_description%] sa description [%profil_prefere%] profil retenu par arbitrage [%score%] score global [%test%] titre du questionnaire

7 — Activer, une fois seulement

L'activation est un geste séparé et volontaire. Un questionnaire actif dont les poids sont incomplets ne signale rien : il répond, et il répond faux.

PATCH /api/agent/v1/questionnaires/4/
{ "actif": true }

Relecture complète avant activation :
GET /api/agent/v1/questionnaires/4/
→ profils, questions, réponses, poids et
   combinaisons, d'un seul appel

Ce que l'API refuse

Un questionnaire mal construit ne provoque aucune erreur : il répond, et il répond faux. Trois refus ferment les cas que la base accepterait — un poids dirigé vers le profil d'un autre test, un intervalle de score inversé qu'aucune valeur ne pourrait satisfaire, et une comparaison de proximité sans tolérance.

Trois formes, un même moteur

Le calcul est toujours le même — des poids qui s'accumulent — mais la manière dont on en tire un résultat distingue trois usages. Ils se combinent : rien n'interdit d'attribuer certains profils par poids et d'autres par tranche de score.

Orientation par profils

Le profil dont le total est le plus élevé l'emporte. C'est la forme la plus courante : on ne cherche pas à noter le répondant, mais à le diriger vers la réponse qui le concerne. Un questionnaire de qualification commerciale, une aide au choix entre plusieurs offres.

POST /api/agent/v1/questionnaires/4/profils/
{ "nom": "Autonome", "slug": "autonome",
  "page_de_resultat": 120 }

POST /api/agent/v1/questionnaires/4/questions/
{ "texte": "Comment travaillez-vous aujourd'hui ?",
  "type": "single",
  "reponses": [
    { "texte": "Seul, avec mes propres outils",
      "poids": { "autonome": 4 } },
    { "texte": "Avec un prestataire",
      "poids": { "accompagne": 4 } }
  ] }

→ le total le plus élevé désigne la page affichée

Évaluation par score global

Le total est comparé à des tranches. Le profil n'est plus une catégorie mais un NIVEAU : maturité numérique, degré de préparation, exposition à un risque. Les tranches doivent couvrir l'intervalle sans se chevaucher — un score qui n'appartient à aucune ne désignerait aucune page.

POST /api/agent/v1/questionnaires/5/profils/
{ "nom": "Niveau initial", "slug": "initial",
  "attribue_par_score": true,
  "score_min": 0, "score_max": 10,
  "page_de_resultat": 130 }

POST /api/agent/v1/questionnaires/5/profils/
{ "nom": "Niveau confirmé", "slug": "confirme",
  "attribue_par_score": true,
  "score_min": 11, "score_max": 25,
  "page_de_resultat": 131 }

→ un intervalle inversé est REFUSÉ : aucun score
   ne pourrait l'atteindre

Arbitrage entre profils proches

Quand deux totaux se tiennent, le plus élevé ne dit pas toujours la bonne chose : un écart d'un point sur vingt relève du bruit, pas d'une préférence. Une combinaison décrit ce cas et impose le profil à retenir. C'est ce qui distingue un questionnaire honnête d'un questionnaire qui tranche au hasard.

POST /api/agent/v1/questionnaires/4/combinaisons/
{
  "titre": "Autonome ou accompagné",
  "profil_parent":     "autonome",
  "profil_prefere":    "accompagne",
  "profil_alternatif": "autonome",
  "criteres": [
    { "profil_a": "autonome",
      "profil_b": "accompagne",
      "comparaison": "~=",
      "tolerance": 2 }
  ]
}

Comparaisons : >  <  >=  <=  ==  ~=
« ~= » exige une tolérance — sans elle, le
critère reviendrait à une égalité stricte,
et n'arbitrerait jamais rien

Types de question

Deux, et le choix n'est pas cosmétique : en choix multiple les poids de toutes les réponses cochées s'additionnent, ce qui change l'échelle des totaux. Un questionnaire mêlant les deux demande des poids calibrés en conséquence.

  • single — une seule réponse. Les poids de cette réponse sont ajoutés
  • multiple — plusieurs réponses. Les poids de chacune s'additionnent, et le total d'une question peut donc dépasser celui d'une question à choix unique

Une question inactive reste modifiable mais n'est plus posée. C'est la manière de retirer une question d'un questionnaire en service sans fausser les passages déjà enregistrés.