feat(r3.4): corrections de recette (8 écarts) + recherche globale ⌘K

Arbitrage du référent sur la revue pixel : tout corriger, activer la
recherche.

- Stock : filtre fournisseur, sous-seuil en tête, « Entrée de stock »
  depuis la liste ; fiche pièce : fournisseur → lien Tiers.
- Statistiques : période 3/6/12 mois (paramètre months au contrat).
- Tiers : rattachements syndic→site (migration r3_recette_fixes,
  Location.partnerId gardé CLIENT), éditable sur la fiche site, seedé.
- Bibliothèque : filtre « Rattaché à » + glisser-déposer (modale
  préremplie, rattachement toujours requis).
- Recherche globale : GET /search (73 opérations) — familles OT/
  ascenseurs/sites filtrées par la matrice, « voir autre » respecté ;
  topbar ⌘K, debounce, résultats groupés, navigation clavier.

74 tests API (8 nouveaux sur le scoping de la recherche), 14/14
Playwright dont un parcours « recette corrigée », 18/18 contrôles en
navigateur réel, zéro erreur console.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pr-daaif
2026-07-17 02:14:43 +01:00
parent c46a97ed08
commit 460ef4a80e
38 changed files with 1318 additions and 65 deletions

View File

@@ -4,6 +4,25 @@ Trace chronologique des sessions (la plus récente en premier). Le **playbook**
---
## 2026-07-17 — Pr. Daaif (+ Claude) — R3.4 : revue pixel, corrections de recette, recherche globale
**Actions**
- **Revue pixel R3** (artefact partagé, captures maquette ↔ appli côte à côte, 1440 px, thème clair) : 7/7 écrans structurellement fidèles, 8 écarts relevés. **Arbitrage du référent : tout corriger + activer la recherche.**
- **Stock** : filtre Fournisseur, « Entrée de stock » depuis la liste (choix de la pièce dans la modale), pièces sous le seuil en tête. **Fiche pièce** : fournisseur → lien vers Tiers. **Statistiques** : « Période » devient un vrai sélecteur 3/6/12 mois (`months` au contrat, libellés et barres suivent). **Tiers** : les syndics affichent leurs sites — nouveau lien site→client/syndic (migration `r3_recette_fixes`, `Location.partnerId`, garde « CLIENT seulement »), éditable sur la fiche site, seedé (Tour Atlas, Résidence Al Manar). **Bibliothèque** : filtre « Rattaché à » + zone de glisser-déposer (la modale s'ouvre préremplie, le rattachement reste obligatoire).
- **Recherche globale ⌘K active** : `GET /search` (73e opération au contrat) — chaque famille (OT/ascenseurs/sites) n'est interrogée que si le rôle a la permission `view` du domaine, les OT respectent « voir autre » ; topbar avec debounce 200 ms, résultats groupés, navigation flèches + Entrée. 8 tests API dédiés (scoping vérifié rôle par rôle).
- Écart « regroupement des tiers » retiré : le tri type-puis-nom existait déjà (constat d'écran, pas de code).
- Vérifié : 18/18 contrôles en navigateur réel (zéro erreur console), **14/14 Playwright** (dont nouveau parcours « recette corrigée »), **74 tests API** (13 suites). Artefact de revue mis à jour (statut « corrigé », captures fraîches).
**Décisions**
- « Bons de commande » reste dans l'entête du Stock **en plus** de la maquette : c'est le seul accès à l'écran BC — à entériner en recette (ou déplacer si le référent préfère).
- La liste des tiers restant sous `PURCHASE_ORDERS.view`, le champ syndic de la fiche site n'est éditable que si le rôle voit les tiers (sinon lecture seule).
**Prochaine étape** : validation finale du référent sur l'artefact → déploiement Dokploy → tag `release/r3` → R4 Mobile (design d'abord).
---
## 2026-07-16 — Pr. Daaif (+ Claude) — R3.3+ : aperçu et ouverture des documents (retour de pré-recette)
**Actions**

View File

@@ -1136,6 +1136,16 @@
"tags": [
"analytics"
],
"parameters": [
{
"name": "months",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"security": [
{
"bearerAuth": []
@@ -1155,6 +1165,42 @@
}
}
},
"/search": {
"get": {
"operationId": "globalSearch",
"summary": "Recherche globale (OT, ascenseurs, sites) — chaque famille filtrée par la matrice",
"tags": [
"search"
],
"parameters": [
{
"name": "q",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
}
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Résultats (5 max par famille)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchResponse"
}
}
}
}
}
}
},
"/partners": {
"get": {
"operationId": "listPartners",
@@ -3239,6 +3285,28 @@
}
]
},
"partnerId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"partnerName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"assetCount": {
"type": "integer",
"minimum": -9007199254740991,
@@ -3255,6 +3323,8 @@
"guardianPhone",
"latitude",
"longitude",
"partnerId",
"partnerName",
"assetCount"
],
"additionalProperties": false
@@ -3350,6 +3420,28 @@
}
]
},
"partnerId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"partnerName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"assetCount": {
"type": "integer",
"minimum": -9007199254740991,
@@ -3366,6 +3458,8 @@
"guardianPhone",
"latitude",
"longitude",
"partnerId",
"partnerName",
"assetCount"
],
"additionalProperties": false
@@ -3409,6 +3503,18 @@
"type": "number",
"minimum": -180,
"maximum": 180
},
"partnerId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
}
},
"required": [
@@ -3455,6 +3561,18 @@
"type": "number",
"minimum": -180,
"maximum": 180
},
"partnerId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
@@ -4715,13 +4833,18 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"months": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"monthCost": {
"type": "number"
},
"previousMonthCost": {
"type": "number"
},
"closed12m": {
"closed": {
"type": "object",
"properties": {
"total": {
@@ -4840,9 +4963,10 @@
}
},
"required": [
"months",
"monthCost",
"previousMonthCost",
"closed12m",
"closed",
"preventiveRate",
"avgResolutionDays",
"failuresByComponent",
@@ -4851,6 +4975,126 @@
],
"additionalProperties": false
},
"SearchResponse": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"workOrders": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"reference": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"OPEN",
"IN_PROGRESS",
"ON_HOLD",
"DONE",
"CANCELLED"
]
}
},
"required": [
"id",
"reference",
"title",
"status"
],
"additionalProperties": false
}
},
"assets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"reference": {
"type": "string"
},
"brand": {
"type": "string"
},
"model": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"siteName": {
"type": "string"
}
},
"required": [
"id",
"reference",
"brand",
"model",
"siteName"
],
"additionalProperties": false
}
},
"sites": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"city": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"city"
],
"additionalProperties": false
}
}
},
"required": [
"workOrders",
"assets",
"sites"
],
"additionalProperties": false
},
"PartnersResponse": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
@@ -4922,6 +5166,12 @@
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"siteNames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
@@ -4933,7 +5183,8 @@
"email",
"city",
"isActive",
"openOrders"
"openOrders",
"siteNames"
],
"additionalProperties": false
}
@@ -5010,6 +5261,12 @@
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"siteNames": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
@@ -5021,7 +5278,8 @@
"email",
"city",
"isActive",
"openOrders"
"openOrders",
"siteNames"
],
"additionalProperties": false
},