Story OP-015: Backend import UI passthrough (POST/GET /imports)¶
Module: operator-console
Slice: Architecture §11 OP-004d + US-OP-01
Side: [BACKEND]
Version target: V0.0.3
Priority: 16
Depends on: OP-000 (RBAC, audit), ING (ImportService.start, ImportService.findById)
Can develop concurrently with: OP-012, OP-013, OP-014
Merge order: Before OP-019 (frontend imports page)
Estimated complexity: S
PRD User Stories: US-OP-01 AC1+AC2+AC3+AC4
Wireframe: N/A — backend only
Objective¶
Exposer 2 endpoints OP qui délèguent à ING (start import + read status), avec audit IMPORT_TRIGGERED côté OP. Cette story permet au frontend (OP-019) de pilotter l'import sans appeler directement le namespace ING (encapsulation + audit trail OP).
Backend Scope¶
Service Layer¶
ImportsController:POST /api/operator/imports(RBAC : agency_operator + cabinet_admin) — body multipart :file(CSV ou XLSX),agencyId(requis pour cabinet_admin/supervisor).- Délègue à
ImportService.start(tenantId, agencyId, fileStream, fileName, operatorId)du module ING. - ING calcule le hash SHA-256, détecte doublon, lance le job d'ingestion async.
- Retour :
200 { importId, status:"EN_COURS", duplicateOfImportId?:"uuid", duplicateDetectedAt?:"timestamp" }. - Si
duplicateOfImportIdprésent → le frontend affiche la warning « Ce fichier a déjà été importé le {date}. Continuer quand même ? » (US-OP-01 AC4). Si le user confirme, le frontend rappellePOST /imports?forceDuplicate=true. - Audit OP
IMPORT_TRIGGERED {importId, fileName, fileSizeBytes, sha256, agencyId, operatorId}.
- Délègue à
GET /api/operator/imports/{id}(RBAC : tous OP) — délègue àImportService.findById(tenantId, importId).- Retour :
{ importId, status:"EN_COURS|TERMINÉ|ÉCHEC", startedAt, completedAt?, validCount, errorCount, anomalyCount, fileName, agencyId, agencyName, operatorId }.
- Retour :
GET /api/operator/imports?cursor=&pageSize=20— liste paginée des imports récents.
API Endpoints¶
| Method | Path | Request | Response | Auth |
|---|---|---|---|---|
POST |
/api/operator/imports (multipart) |
file, agencyId? |
200 import status |
agency_operator + cabinet_admin |
GET |
/api/operator/imports/{id} |
— | import details | Tous OP |
GET |
/api/operator/imports?cursor=&pageSize=20 |
— | liste | Tous OP |
Validation Rules¶
file: MIMEtext/csv | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; taille ≤ 20 Mo (sinon 413).agencyIdrequis pour cabinet_admin/supervisor.forceDuplicatequery param boolean.
Multi-Tenant Considerations¶
- Scope
tenant_id. agency_id: agency_operator force son agence ; cabinet_admin choisit.
Audit & Logging¶
IMPORT_TRIGGEREDà chaque POST réussi.- Pas d'audit sur GET.
Acceptance Criteria¶
AC-001: POST /imports lance ingestion et audit (US-OP-01 AC1)
Given un fichier CSV valide 2.3 Mo
When agency_operator POST /imports (multipart)
Then 200 { importId, status:"EN_COURS" }
And IMPORT_TRIGGERED audit avec fileName + sha256.
AC-002: Doublon détecté → warning dans la réponse (US-OP-01 AC4)
Given un fichier déjà importé (même SHA-256)
When POST /imports
Then 200 { importId, status:"EN_COURS", duplicateOfImportId, duplicateDetectedAt }
And le frontend peut afficher la warning.
AC-003: GET /imports/{id} retourne le résultat (US-OP-01 AC2)
Given un import TERMINÉ
When GET /imports/{id}
Then 200 { status:"TERMINÉ", validCount=412, errorCount=3, anomalyCount=12, ... }.
AC-004: Fichier > 20 Mo → 413
Given un fichier 25 Mo
When POST /imports
Then 413 Payload Too Large message "Le fichier dépasse la taille maximale (20 Mo)."
Compliance Rules¶
- US-OP-01 : delegate à ING ; OP audit en sus.
VÉRIFIÉ.
Standards & Conventions¶
docs/standards/api-guidelines.md— multipart upload, 413.docs/standards/java-spring-guidelines.md—MultipartFile, streaming.
Testing Requirements¶
Unit Tests¶
- Validation taille + MIME.
Integration Tests¶
ImportPassthroughITAC-001..AC-004 avec ING fixture (mock ImportService).
What QA Will Validate¶
- Upload bout-en-bout avec petit CSV de test.
- Doublon réel détecté.
Out of Scope¶
- Frontend page Imports → OP-019.
- Édition champ d'import → ING (déjà géré côté ING).
Definition of Done¶
- [ ] Les 3 endpoints retournent 200/413 conformes
- [ ] AC-001..AC-004 passent
- [ ] IMPORT_TRIGGERED audité
- [ ] Multipart streaming (pas de chargement complet en mémoire)
- [ ] Tests verts