Add equipment management features (and qr generation support)
This commit is contained in:
		
							
								
								
									
										363
									
								
								em2rp/lib/services/event_preparation_service.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								em2rp/lib/services/event_preparation_service.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,363 @@ | ||||
| import 'package:cloud_firestore/cloud_firestore.dart'; | ||||
| import 'package:em2rp/models/event_model.dart'; | ||||
| import 'package:em2rp/models/equipment_model.dart'; | ||||
| import 'package:em2rp/services/equipment_service.dart'; | ||||
|  | ||||
| class EventPreparationService { | ||||
|   final FirebaseFirestore _firestore = FirebaseFirestore.instance; | ||||
|   final EquipmentService _equipmentService = EquipmentService(); | ||||
|  | ||||
|   // Collection references | ||||
|   CollectionReference get _eventsCollection => _firestore.collection('events'); | ||||
|   CollectionReference get _equipmentCollection => _firestore.collection('equipment'); | ||||
|  | ||||
|   // === PRÉPARATION === | ||||
|  | ||||
|    /// Valider un équipement individuel en préparation | ||||
|   Future<void> validateEquipmentPreparation(String eventId, String equipmentId) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Mettre à jour le statut de l'équipement dans la liste | ||||
|       final updatedEquipment = event.assignedEquipment.map((eq) { | ||||
|         if (eq.equipmentId == equipmentId) { | ||||
|           return eq.copyWith(isPrepared: true); | ||||
|         } | ||||
|         return eq; | ||||
|       }).toList(); | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|       }); | ||||
|     } catch (e) { | ||||
|       print('Error validating equipment preparation: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Valider tous les équipements en préparation | ||||
|   Future<void> validateAllPreparation(String eventId) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Marquer tous les équipements comme préparés | ||||
|       final updatedEquipment = event.assignedEquipment.map((eq) { | ||||
|         return eq.copyWith(isPrepared: true); | ||||
|       }).toList(); | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|         'preparationStatus': preparationStatusToString(PreparationStatus.completed), | ||||
|       }); | ||||
|  | ||||
|       // Mettre à jour le statut des équipements à "inUse" | ||||
|       for (var equipment in event.assignedEquipment) { | ||||
|         await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.inUse); | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error validating all preparation: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Finaliser la préparation avec des équipements manquants | ||||
|   Future<void> completePreparationWithMissing( | ||||
|     String eventId, | ||||
|     List<String> missingEquipmentIds, | ||||
|   ) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Marquer comme complété avec manquants | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'preparationStatus': preparationStatusToString(PreparationStatus.completedWithMissing), | ||||
|       }); | ||||
|  | ||||
|       // Mettre à jour le statut des équipements préparés à "inUse" | ||||
|       for (var equipment in event.assignedEquipment) { | ||||
|         if (equipment.isPrepared && !missingEquipmentIds.contains(equipment.equipmentId)) { | ||||
|           await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.inUse); | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error completing preparation with missing: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // === RETOUR === | ||||
|  | ||||
|  | ||||
|     /// Valider le retour d'un équipement individuel | ||||
|   Future<void> validateEquipmentReturn( | ||||
|     String eventId, | ||||
|     String equipmentId, { | ||||
|     int? returnedQuantity, | ||||
|   }) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Mettre à jour le statut de l'équipement dans la liste | ||||
|       final updatedEquipment = event.assignedEquipment.map((eq) { | ||||
|         if (eq.equipmentId == equipmentId) { | ||||
|           return eq.copyWith( | ||||
|             isReturned: true, | ||||
|             returnedQuantity: returnedQuantity, | ||||
|           ); | ||||
|         } | ||||
|         return eq; | ||||
|       }).toList(); | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|       }); | ||||
|  | ||||
|       // Mettre à jour le stock si c'est un consommable | ||||
|       if (returnedQuantity != null) { | ||||
|         final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); | ||||
|         if (equipmentDoc.exists) { | ||||
|           final equipment = EquipmentModel.fromMap( | ||||
|             equipmentDoc.data() as Map<String, dynamic>, | ||||
|             equipmentDoc.id, | ||||
|           ); | ||||
|  | ||||
|           if (equipment.hasQuantity) { | ||||
|             final currentAvailable = equipment.availableQuantity ?? 0; | ||||
|             await _equipmentCollection.doc(equipmentId).update({ | ||||
|               'availableQuantity': currentAvailable + returnedQuantity, | ||||
|             }); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error validating equipment return: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Valider tous les retours | ||||
|   Future<void> validateAllReturn(String eventId) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Marquer tous les équipements comme retournés | ||||
|       final updatedEquipment = event.assignedEquipment.map((eq) { | ||||
|         return eq.copyWith( | ||||
|           isReturned: true, | ||||
|           returnedQuantity: eq.returnedQuantity ?? eq.quantity, | ||||
|         ); | ||||
|       }).toList(); | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|         'returnStatus': returnStatusToString(ReturnStatus.completed), | ||||
|       }); | ||||
|  | ||||
|       // Mettre à jour le statut des équipements à "available" et gérer les stocks | ||||
|       for (var equipment in updatedEquipment) { | ||||
|         await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.available); | ||||
|  | ||||
|         // Restaurer le stock pour les consommables | ||||
|         final equipmentDoc = await _equipmentCollection.doc(equipment.equipmentId).get(); | ||||
|         if (equipmentDoc.exists) { | ||||
|           final equipmentData = EquipmentModel.fromMap( | ||||
|             equipmentDoc.data() as Map<String, dynamic>, | ||||
|             equipmentDoc.id, | ||||
|           ); | ||||
|  | ||||
|           if (equipmentData.hasQuantity && equipment.returnedQuantity != null) { | ||||
|             final currentAvailable = equipmentData.availableQuantity ?? 0; | ||||
|             await _equipmentCollection.doc(equipment.equipmentId).update({ | ||||
|               'availableQuantity': currentAvailable + equipment.returnedQuantity!, | ||||
|             }); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error validating all return: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Finaliser le retour avec des équipements manquants | ||||
|   Future<void> completeReturnWithMissing( | ||||
|     String eventId, | ||||
|     List<String> missingEquipmentIds, | ||||
|   ) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Marquer comme complété avec manquants | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'returnStatus': returnStatusToString(ReturnStatus.completedWithMissing), | ||||
|       }); | ||||
|  | ||||
|       // Mettre à jour le statut des équipements retournés à "available" | ||||
|       for (var equipment in event.assignedEquipment) { | ||||
|         if (equipment.isReturned && !missingEquipmentIds.contains(equipment.equipmentId)) { | ||||
|           await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.available); | ||||
|  | ||||
|           // Restaurer le stock pour les consommables | ||||
|           final equipmentDoc = await _equipmentCollection.doc(equipment.equipmentId).get(); | ||||
|           if (equipmentDoc.exists) { | ||||
|             final equipmentData = EquipmentModel.fromMap( | ||||
|               equipmentDoc.data() as Map<String, dynamic>, | ||||
|               equipmentDoc.id, | ||||
|             ); | ||||
|  | ||||
|             if (equipmentData.hasQuantity && equipment.returnedQuantity != null) { | ||||
|               final currentAvailable = equipmentData.availableQuantity ?? 0; | ||||
|               await _equipmentCollection.doc(equipment.equipmentId).update({ | ||||
|                 'availableQuantity': currentAvailable + equipment.returnedQuantity!, | ||||
|               }); | ||||
|             } | ||||
|           } | ||||
|         } else if (missingEquipmentIds.contains(equipment.equipmentId)) { | ||||
|           // Marquer comme perdu | ||||
|           await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.lost); | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error completing return with missing: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // === HELPERS === | ||||
|  | ||||
|   /// Mettre à jour le statut d'un équipement | ||||
|   Future<void> updateEquipmentStatus(String equipmentId, EquipmentStatus status) async { | ||||
|     try { | ||||
|       await _equipmentCollection.doc(equipmentId).update({ | ||||
|         'status': equipmentStatusToString(status), | ||||
|         'updatedAt': Timestamp.fromDate(DateTime.now()), | ||||
|       }); | ||||
|     } catch (e) { | ||||
|       print('Error updating equipment status: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Récupérer un événement | ||||
|   Future<EventModel?> _getEvent(String eventId) async { | ||||
|     try { | ||||
|       final doc = await _eventsCollection.doc(eventId).get(); | ||||
|       if (doc.exists) { | ||||
|         return EventModel.fromMap(doc.data() as Map<String, dynamic>, doc.id); | ||||
|       } | ||||
|       return null; | ||||
|     } catch (e) { | ||||
|       print('Error getting event: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Ajouter un équipement à un événement | ||||
|   Future<void> addEquipmentToEvent( | ||||
|     String eventId, | ||||
|     String equipmentId, { | ||||
|     int quantity = 1, | ||||
|   }) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       // Vérifier que l'équipement n'est pas déjà ajouté | ||||
|       final alreadyAdded = event.assignedEquipment.any((eq) => eq.equipmentId == equipmentId); | ||||
|       if (alreadyAdded) { | ||||
|         throw Exception('Equipment already added to event'); | ||||
|       } | ||||
|  | ||||
|       final newEquipment = EventEquipment( | ||||
|         equipmentId: equipmentId, | ||||
|         quantity: quantity, | ||||
|       ); | ||||
|  | ||||
|       final updatedEquipment = [...event.assignedEquipment, newEquipment]; | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|       }); | ||||
|  | ||||
|       // Décrémenter le stock pour les consommables | ||||
|       final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); | ||||
|       if (equipmentDoc.exists) { | ||||
|         final equipmentData = EquipmentModel.fromMap( | ||||
|           equipmentDoc.data() as Map<String, dynamic>, | ||||
|           equipmentDoc.id, | ||||
|         ); | ||||
|  | ||||
|         if (equipmentData.hasQuantity) { | ||||
|           final currentAvailable = equipmentData.availableQuantity ?? 0; | ||||
|           await _equipmentCollection.doc(equipmentId).update({ | ||||
|             'availableQuantity': currentAvailable - quantity, | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error adding equipment to event: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /// Retirer un équipement d'un événement | ||||
|   Future<void> removeEquipmentFromEvent(String eventId, String equipmentId) async { | ||||
|     try { | ||||
|       final event = await _getEvent(eventId); | ||||
|       if (event == null) { | ||||
|         throw Exception('Event not found'); | ||||
|       } | ||||
|  | ||||
|       final equipmentToRemove = event.assignedEquipment.firstWhere( | ||||
|         (eq) => eq.equipmentId == equipmentId, | ||||
|       ); | ||||
|  | ||||
|       final updatedEquipment = event.assignedEquipment | ||||
|           .where((eq) => eq.equipmentId != equipmentId) | ||||
|           .toList(); | ||||
|  | ||||
|       await _eventsCollection.doc(eventId).update({ | ||||
|         'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), | ||||
|       }); | ||||
|  | ||||
|       // Restaurer le stock pour les consommables | ||||
|       final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); | ||||
|       if (equipmentDoc.exists) { | ||||
|         final equipmentData = EquipmentModel.fromMap( | ||||
|           equipmentDoc.data() as Map<String, dynamic>, | ||||
|           equipmentDoc.id, | ||||
|         ); | ||||
|  | ||||
|         if (equipmentData.hasQuantity) { | ||||
|           final currentAvailable = equipmentData.availableQuantity ?? 0; | ||||
|           await _equipmentCollection.doc(equipmentId).update({ | ||||
|             'availableQuantity': currentAvailable + equipmentToRemove.quantity, | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     } catch (e) { | ||||
|       print('Error removing equipment from event: $e'); | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 ElPoyo
					ElPoyo