423 lines
14 KiB
Dart
423 lines
14 KiB
Dart
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('equipments');
|
|
|
|
// === 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();
|
|
|
|
// Vérifier si tous les équipements sont préparés
|
|
final allPrepared = updatedEquipment.every((eq) => eq.isPrepared);
|
|
|
|
final updateData = <String, dynamic>{
|
|
'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(),
|
|
};
|
|
|
|
// Mettre à jour le statut selon la complétion
|
|
if (allPrepared) {
|
|
updateData['preparationStatus'] = preparationStatusToString(PreparationStatus.completed);
|
|
} else {
|
|
updateData['preparationStatus'] = preparationStatusToString(PreparationStatus.inProgress);
|
|
}
|
|
|
|
await _eventsCollection.doc(eventId).update(updateData);
|
|
} 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" (seulement pour les équipements qui existent)
|
|
for (var equipment in event.assignedEquipment) {
|
|
// Vérifier si l'équipement existe avant de mettre à jour son statut
|
|
final doc = await _equipmentCollection.doc(equipment.equipmentId).get();
|
|
if (doc.exists) {
|
|
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)) {
|
|
// Vérifier si l'équipement existe avant de mettre à jour son statut
|
|
final doc = await _equipmentCollection.doc(equipment.equipmentId).get();
|
|
if (doc.exists) {
|
|
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();
|
|
|
|
// Vérifier si tous les équipements sont retournés
|
|
final allReturned = updatedEquipment.every((eq) => eq.isReturned);
|
|
|
|
final updateData = <String, dynamic>{
|
|
'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(),
|
|
};
|
|
|
|
// Mettre à jour le statut selon la complétion
|
|
if (allReturned) {
|
|
updateData['returnStatus'] = returnStatusToString(ReturnStatus.completed);
|
|
} else {
|
|
updateData['returnStatus'] = returnStatusToString(ReturnStatus.inProgress);
|
|
}
|
|
|
|
await _eventsCollection.doc(eventId).update(updateData);
|
|
|
|
// 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, [
|
|
Map<String, int>? returnedQuantities,
|
|
]) 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) {
|
|
final returnedQty = returnedQuantities?[eq.equipmentId] ??
|
|
eq.returnedQuantity ??
|
|
eq.quantity;
|
|
return eq.copyWith(
|
|
isReturned: true,
|
|
returnedQuantity: returnedQty,
|
|
);
|
|
}).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) {
|
|
// Vérifier si le document existe
|
|
final equipmentDoc = await _equipmentCollection.doc(equipment.equipmentId).get();
|
|
if (equipmentDoc.exists) {
|
|
final equipmentData = EquipmentModel.fromMap(
|
|
equipmentDoc.data() as Map<String, dynamic>,
|
|
equipmentDoc.id,
|
|
);
|
|
|
|
// Mettre à jour le statut uniquement pour les équipements non quantifiables
|
|
if (!equipmentData.hasQuantity) {
|
|
await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.available);
|
|
}
|
|
|
|
// Restaurer le stock pour les consommables
|
|
if (equipmentData.hasQuantity && equipment.returnedQuantity != null) {
|
|
final currentAvailable = equipmentData.availableQuantity ?? 0;
|
|
await _equipmentCollection.doc(equipment.equipmentId).update({
|
|
'availableQuantity': currentAvailable + equipment.returnedQuantity!,
|
|
'updatedAt': Timestamp.fromDate(DateTime.now()),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} 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) {
|
|
// Vérifier si le document existe
|
|
final equipmentDoc = await _equipmentCollection.doc(equipment.equipmentId).get();
|
|
if (!equipmentDoc.exists) {
|
|
continue; // Passer cet équipement s'il n'existe pas
|
|
}
|
|
|
|
final equipmentData = EquipmentModel.fromMap(
|
|
equipmentDoc.data() as Map<String, dynamic>,
|
|
equipmentDoc.id,
|
|
);
|
|
|
|
if (equipment.isReturned && !missingEquipmentIds.contains(equipment.equipmentId)) {
|
|
// Mettre à jour le statut uniquement pour les équipements non quantifiables
|
|
if (!equipmentData.hasQuantity) {
|
|
await updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.available);
|
|
}
|
|
|
|
// Restaurer le stock pour les consommables
|
|
if (equipmentData.hasQuantity && equipment.returnedQuantity != null) {
|
|
final currentAvailable = equipmentData.availableQuantity ?? 0;
|
|
await _equipmentCollection.doc(equipment.equipmentId).update({
|
|
'availableQuantity': currentAvailable + equipment.returnedQuantity!,
|
|
'updatedAt': Timestamp.fromDate(DateTime.now()),
|
|
});
|
|
}
|
|
} else if (missingEquipmentIds.contains(equipment.equipmentId)) {
|
|
// Marquer comme perdu uniquement pour les équipements non quantifiables
|
|
if (!equipmentData.hasQuantity) {
|
|
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 {
|
|
// Vérifier que le document existe avant de le mettre à jour
|
|
final doc = await _equipmentCollection.doc(equipmentId).get();
|
|
if (!doc.exists) {
|
|
print('Warning: Equipment document $equipmentId does not exist, skipping status update');
|
|
return;
|
|
}
|
|
|
|
await _equipmentCollection.doc(equipmentId).update({
|
|
'status': equipmentStatusToString(status),
|
|
'updatedAt': Timestamp.fromDate(DateTime.now()),
|
|
});
|
|
} catch (e) {
|
|
print('Error updating equipment status for $equipmentId: $e');
|
|
// Ne pas rethrow pour ne pas bloquer le processus si un équipement n'existe pas
|
|
}
|
|
}
|
|
|
|
/// 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;
|
|
}
|
|
}
|
|
}
|