Migration complète du backend pour utiliser des Cloud Functions comme couche API sécurisée, en remplacement des appels directs à Firestore depuis le client.
**Backend (Cloud Functions):**
- **Centralisation CORS :** Ajout d'un middleware `withCors` et d'une configuration `httpOptions` pour gérer uniformément les en-têtes CORS et les requêtes `OPTIONS` sur toutes les fonctions.
- **Nouvelles Fonctions de Lecture (GET) :**
- `getEquipments`, `getContainers`, `getEvents`, `getUsers`, `getOptions`, `getEventTypes`, `getRoles`, `getMaintenances`, `getAlerts`.
- Ces fonctions gèrent les permissions côté serveur, masquant les données sensibles (ex: prix des équipements) pour les utilisateurs non-autorisés.
- `getEvents` retourne également une map des utilisateurs (`usersMap`) pour optimiser le chargement des données de la main d'œuvre.
- **Nouvelle Fonction de Recherche :**
- `getContainersByEquipment` : Endpoint dédié pour trouver efficacement tous les containers qui contiennent un équipement spécifique.
- **Nouvelles Fonctions d'Écriture (CRUD) :**
- Fonctions CRUD complètes pour `eventTypes` (`create`, `update`, `delete`), incluant la validation (unicité du nom, vérification des événements futurs avant suppression).
- **Mise à jour de Fonctions Existantes :**
- Toutes les fonctions CRUD existantes (`create/update/deleteEquipment`, `create/update/deleteContainer`, etc.) sont wrappées avec le nouveau gestionnaire CORS.
**Frontend (Flutter):**
- **Introduction du `DataService` :** Nouveau service centralisant tous les appels aux Cloud Functions, servant d'intermédiaire entre l'UI/Providers et l'API.
- **Refactorisation des Providers :**
- `EquipmentProvider`, `ContainerProvider`, `EventProvider`, `UsersProvider`, `MaintenanceProvider` et `AlertProvider` ont été refactorisés pour utiliser le `DataService` au lieu d'accéder directement à Firestore.
- Les `Stream` Firestore sont remplacés par des chargements de données via des méthodes `Future` (`loadEquipments`, `loadEvents`, etc.).
- **Gestion des Relations Équipement-Container :**
- Le modèle `EquipmentModel` ne stocke plus `parentBoxIds`.
- La relation est maintenant gérée par le `ContainerModel` qui contient `equipmentIds`.
- Le `ContainerEquipmentService` est introduit pour utiliser la nouvelle fonction `getContainersByEquipment`.
- L'affichage des boîtes parentes (`EquipmentParentContainers`) et le formulaire d'équipement (`EquipmentFormPage`) ont été mis à jour pour refléter ce nouveau modèle de données, synchronisant les ajouts/suppressions d'équipements dans les containers.
- **Amélioration de l'UI :**
- Nouveau widget `ParentBoxesSelector` pour une sélection améliorée et visuelle des boîtes parentes dans le formulaire d'équipement.
- Refonte visuelle de `EquipmentParentContainers` pour une meilleure présentation.
103 lines
2.7 KiB
Dart
103 lines
2.7 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
|
|
enum AlertType {
|
|
lowStock, // Stock faible
|
|
maintenanceDue, // Maintenance à venir
|
|
conflict, // Conflit disponibilité
|
|
lost // Équipement perdu
|
|
}
|
|
|
|
String alertTypeToString(AlertType type) {
|
|
switch (type) {
|
|
case AlertType.lowStock:
|
|
return 'LOW_STOCK';
|
|
case AlertType.maintenanceDue:
|
|
return 'MAINTENANCE_DUE';
|
|
case AlertType.conflict:
|
|
return 'CONFLICT';
|
|
case AlertType.lost:
|
|
return 'LOST';
|
|
}
|
|
}
|
|
|
|
AlertType alertTypeFromString(String? type) {
|
|
switch (type) {
|
|
case 'LOW_STOCK':
|
|
return AlertType.lowStock;
|
|
case 'MAINTENANCE_DUE':
|
|
return AlertType.maintenanceDue;
|
|
case 'CONFLICT':
|
|
return AlertType.conflict;
|
|
case 'LOST':
|
|
return AlertType.lost;
|
|
default:
|
|
return AlertType.conflict;
|
|
}
|
|
}
|
|
|
|
class AlertModel {
|
|
final String id; // ID généré automatiquement
|
|
final AlertType type; // Type d'alerte
|
|
final String message; // Message de l'alerte
|
|
final String? equipmentId; // ID de l'équipement concerné (optionnel)
|
|
final DateTime createdAt; // Date de création
|
|
final bool isRead; // Statut lu/non lu
|
|
|
|
AlertModel({
|
|
required this.id,
|
|
required this.type,
|
|
required this.message,
|
|
this.equipmentId,
|
|
required this.createdAt,
|
|
this.isRead = false,
|
|
});
|
|
|
|
factory AlertModel.fromMap(Map<String, dynamic> map, String id) {
|
|
// Fonction helper pour convertir Timestamp ou String ISO en DateTime
|
|
DateTime _parseDate(dynamic value) {
|
|
if (value == null) return DateTime.now();
|
|
if (value is Timestamp) return value.toDate();
|
|
if (value is String) return DateTime.tryParse(value) ?? DateTime.now();
|
|
return DateTime.now();
|
|
}
|
|
|
|
return AlertModel(
|
|
id: id,
|
|
type: alertTypeFromString(map['type']),
|
|
message: map['message'] ?? '',
|
|
equipmentId: map['equipmentId'],
|
|
createdAt: _parseDate(map['createdAt']),
|
|
isRead: map['isRead'] ?? false,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'type': alertTypeToString(type),
|
|
'message': message,
|
|
'equipmentId': equipmentId,
|
|
'createdAt': Timestamp.fromDate(createdAt),
|
|
'isRead': isRead,
|
|
};
|
|
}
|
|
|
|
AlertModel copyWith({
|
|
String? id,
|
|
AlertType? type,
|
|
String? message,
|
|
String? equipmentId,
|
|
DateTime? createdAt,
|
|
bool? isRead,
|
|
}) {
|
|
return AlertModel(
|
|
id: id ?? this.id,
|
|
type: type ?? this.type,
|
|
message: message ?? this.message,
|
|
equipmentId: equipmentId ?? this.equipmentId,
|
|
createdAt: createdAt ?? this.createdAt,
|
|
isRead: isRead ?? this.isRead,
|
|
);
|
|
}
|
|
}
|
|
|