mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 12:41:54 +00:00
feat(r3.2): bibliothèque de documents (FileStorage réel) + analytics
- FileStorage : putObject/getObjectStream/removeObject, bucket créé au démarrage — MinIO confiné à son implémentation (règle ESLint intacte) - documents : upload multipart (PDF/JPG/PNG, 20 Mo max, rattachement appareil OU OT requis, permission d'édition sur la CIBLE), liste filtrable, téléchargement STREAMÉ par l'API (MinIO jamais exposé), suppression ; e2e : octets téléchargés identiques aux octets envoyés - analytics : GET /analytics/summary dérivé du réel — coûts/mois (mouvements + main-d'œuvre figés), pannes par organe (bilans codés), taux de préventif, durée moyenne de résolution, top équipements - générateur OpenAPI : query params, multipart, réponse binaire (71 ops) - CI : service MinIO (bitnami) sur les jobs api et e2e - test de régression du tri « Interventions récentes » rendu déterministe (positions absolues instables sous 12 suites parallèles) ; 58 tests, 6 runs complets consécutifs verts Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,20 @@ Trace chronologique des sessions (la plus récente en premier). Le **playbook**
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-16 — Pr. Daaif (+ Claude) — R3.2 : bibliothèque de documents + analytics
|
||||
|
||||
**Actions**
|
||||
|
||||
- **`FileStorage` gagne ses vraies opérations** (put/stream/remove ; bucket créé au démarrage — aucune étape manuelle au déploiement) ; MinIO reste confiné à son implémentation (règle ESLint).
|
||||
- **Bibliothèque** : upload multipart (PDF/JPG/PNG, 20 Mo max, rattachement appareil OU OT **requis**, permission d'édition sur la cible), liste filtrable, **téléchargement streamé par l'API** (MinIO jamais exposé — topologie du runbook respectée), suppression. Test e2e : les octets téléchargés sont IDENTIQUES aux octets envoyés.
|
||||
- **Analytics** (`GET /analytics/summary`, permission ANALYTICS) : tout est dérivé du réel — coûts par mois depuis les mouvements/main-d'œuvre figés, **pannes par organe depuis les bilans codés**, taux de préventif (grilles terminées/générées), durée moyenne de résolution, top équipements en coût.
|
||||
- Générateur OpenAPI étendu (query params, multipart, réponse binaire) — 71 opérations. **CI : service MinIO ajouté** (jobs api + e2e, image bitnami).
|
||||
- **58 tests verts** (92 % / 73,9 %) ; test de régression du tri des « Interventions récentes » rendu **déterministe** (les positions absolues étaient instables sous 12 suites parallèles) — 6 runs complets consécutifs verts.
|
||||
|
||||
**Prochaine étape** : R3.3 — écrans web (stock, fiche pièce, BC, coûts sur fiche OT, statistiques, tiers, bibliothèque, taux dans Personnes), puis recette R3 + déploiement + tag.
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-16 — Pr. Daaif (+ Claude) — R3.1 : socle backend de la gestion
|
||||
|
||||
**Actions**
|
||||
|
||||
@@ -956,6 +956,205 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/documents": {
|
||||
"get": {
|
||||
"operationId": "listDocuments",
|
||||
"summary": "Bibliothèque (filtrable par appareil ou OT)",
|
||||
"tags": [
|
||||
"documents"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "assetId",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "workOrderId",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kind",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Liste",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/DocumentsResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"operationId": "uploadDocument",
|
||||
"summary": "Téléverser (PDF/JPG/PNG, 20 Mo max, rattachement appareil OU OT requis)",
|
||||
"tags": [
|
||||
"documents"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string"
|
||||
},
|
||||
"assetId": {
|
||||
"type": "string"
|
||||
},
|
||||
"workOrderId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"file"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Document rangé",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Document"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Type/taille refusé ou rattachement manquant"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/documents/{id}/download": {
|
||||
"get": {
|
||||
"operationId": "downloadDocument",
|
||||
"summary": "Télécharger — streamé par l’API (MinIO jamais exposé)",
|
||||
"tags": [
|
||||
"documents"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Fichier"
|
||||
},
|
||||
"404": {
|
||||
"description": "Inconnu"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/documents/{id}": {
|
||||
"delete": {
|
||||
"operationId": "deleteDocument",
|
||||
"summary": "Supprimer (permission d’édition sur la cible)",
|
||||
"tags": [
|
||||
"documents"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Supprimé"
|
||||
},
|
||||
"404": {
|
||||
"description": "Inconnu"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/analytics/summary": {
|
||||
"get": {
|
||||
"operationId": "getAnalyticsSummary",
|
||||
"summary": "Le tableau de la direction : coûts, pannes par organe (bilans), préventif, top équipements",
|
||||
"tags": [
|
||||
"analytics"
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Synthèse",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/AnalyticsSummary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/partners": {
|
||||
"get": {
|
||||
"operationId": "listPartners",
|
||||
@@ -4344,6 +4543,314 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"DocumentsResponse": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"documents": {
|
||||
"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)$"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NOTICE",
|
||||
"CERTIFICATE",
|
||||
"PHOTO",
|
||||
"OTHER"
|
||||
]
|
||||
},
|
||||
"fileName": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"contentType": {
|
||||
"type": "string"
|
||||
},
|
||||
"assetReference": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"workOrderReference": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uploadedByName": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"kind",
|
||||
"fileName",
|
||||
"size",
|
||||
"contentType",
|
||||
"assetReference",
|
||||
"workOrderReference",
|
||||
"uploadedByName",
|
||||
"createdAt"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"documents"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"Document": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"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)$"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"NOTICE",
|
||||
"CERTIFICATE",
|
||||
"PHOTO",
|
||||
"OTHER"
|
||||
]
|
||||
},
|
||||
"fileName": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"contentType": {
|
||||
"type": "string"
|
||||
},
|
||||
"assetReference": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"workOrderReference": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uploadedByName": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"kind",
|
||||
"fileName",
|
||||
"size",
|
||||
"contentType",
|
||||
"assetReference",
|
||||
"workOrderReference",
|
||||
"uploadedByName",
|
||||
"createdAt"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AnalyticsSummary": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"monthCost": {
|
||||
"type": "number"
|
||||
},
|
||||
"previousMonthCost": {
|
||||
"type": "number"
|
||||
},
|
||||
"closed12m": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"preventive": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"total",
|
||||
"preventive"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"preventiveRate": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"avgResolutionDays": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"failuresByComponent": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"count": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"label",
|
||||
"count"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"costsByMonth": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"month": {
|
||||
"type": "string"
|
||||
},
|
||||
"total": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"month",
|
||||
"total"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"topAssets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reference": {
|
||||
"type": "string"
|
||||
},
|
||||
"siteName": {
|
||||
"type": "string"
|
||||
},
|
||||
"correctives": {
|
||||
"type": "integer",
|
||||
"minimum": -9007199254740991,
|
||||
"maximum": 9007199254740991
|
||||
},
|
||||
"partsCost": {
|
||||
"type": "number"
|
||||
},
|
||||
"laborCost": {
|
||||
"type": "number"
|
||||
},
|
||||
"total": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"reference",
|
||||
"siteName",
|
||||
"correctives",
|
||||
"partsCost",
|
||||
"laborCost",
|
||||
"total"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"monthCost",
|
||||
"previousMonthCost",
|
||||
"closed12m",
|
||||
"preventiveRate",
|
||||
"avgResolutionDays",
|
||||
"failuresByComponent",
|
||||
"costsByMonth",
|
||||
"topAssets"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"PartnersResponse": {
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "object",
|
||||
|
||||
Reference in New Issue
Block a user