feat: ajout de la gestion de la préparation d'un événement avec page permettant de le gérer
This commit is contained in:
@@ -62,10 +62,6 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
try {
|
||||
print('[EventAssignedEquipmentSection] Loading equipment and containers...');
|
||||
print('[EventAssignedEquipmentSection] assignedEquipment: ${widget.assignedEquipment.map((e) => e.equipmentId).toList()}');
|
||||
print('[EventAssignedEquipmentSection] assignedContainers: ${widget.assignedContainers}');
|
||||
|
||||
final equipmentProvider = context.read<EquipmentProvider>();
|
||||
final containerProvider = context.read<ContainerProvider>();
|
||||
|
||||
@@ -73,62 +69,40 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
final equipment = await equipmentProvider.equipmentStream.first;
|
||||
final containers = await containerProvider.containersStream.first;
|
||||
|
||||
print('[EventAssignedEquipmentSection] Available equipment count: ${equipment.length}');
|
||||
print('[EventAssignedEquipmentSection] Available containers count: ${containers.length}');
|
||||
|
||||
// Créer le cache des équipements
|
||||
for (var eq in widget.assignedEquipment) {
|
||||
print('[EventAssignedEquipmentSection] Looking for equipment: ${eq.equipmentId}');
|
||||
final equipmentItem = equipment.firstWhere(
|
||||
(e) {
|
||||
print('[EventAssignedEquipmentSection] Comparing "${e.id}" with "${eq.equipmentId}"');
|
||||
return e.id == eq.equipmentId;
|
||||
},
|
||||
orElse: () {
|
||||
print('[EventAssignedEquipmentSection] Equipment NOT FOUND: ${eq.equipmentId}');
|
||||
return EquipmentModel(
|
||||
id: eq.equipmentId,
|
||||
name: 'Équipement inconnu',
|
||||
category: EquipmentCategory.other,
|
||||
status: EquipmentStatus.available,
|
||||
parentBoxIds: [],
|
||||
maintenanceIds: [],
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
},
|
||||
(e) => e.id == eq.equipmentId,
|
||||
orElse: () => EquipmentModel(
|
||||
id: eq.equipmentId,
|
||||
name: 'Équipement inconnu',
|
||||
category: EquipmentCategory.other,
|
||||
status: EquipmentStatus.available,
|
||||
parentBoxIds: [],
|
||||
maintenanceIds: [],
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
_equipmentCache[eq.equipmentId] = equipmentItem;
|
||||
print('[EventAssignedEquipmentSection] Cached equipment: ${equipmentItem.id} (${equipmentItem.name})');
|
||||
}
|
||||
|
||||
// Créer le cache des conteneurs
|
||||
for (var containerId in widget.assignedContainers) {
|
||||
print('[EventAssignedEquipmentSection] Looking for container: $containerId');
|
||||
final container = containers.firstWhere(
|
||||
(c) {
|
||||
print('[EventAssignedEquipmentSection] Comparing "${c.id}" with "$containerId"');
|
||||
return c.id == containerId;
|
||||
},
|
||||
orElse: () {
|
||||
print('[EventAssignedEquipmentSection] Container NOT FOUND: $containerId');
|
||||
return ContainerModel(
|
||||
id: containerId,
|
||||
name: 'Conteneur inconnu',
|
||||
type: ContainerType.flightCase,
|
||||
status: EquipmentStatus.available,
|
||||
equipmentIds: [],
|
||||
updatedAt: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
},
|
||||
(c) => c.id == containerId,
|
||||
orElse: () => ContainerModel(
|
||||
id: containerId,
|
||||
name: 'Conteneur inconnu',
|
||||
type: ContainerType.flightCase,
|
||||
status: EquipmentStatus.available,
|
||||
equipmentIds: [],
|
||||
updatedAt: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
_containerCache[containerId] = container;
|
||||
print('[EventAssignedEquipmentSection] Cached container: ${container.id} (${container.name})');
|
||||
}
|
||||
|
||||
print('[EventAssignedEquipmentSection] Equipment cache: ${_equipmentCache.keys.toList()}');
|
||||
print('[EventAssignedEquipmentSection] Container cache: ${_containerCache.keys.toList()}');
|
||||
} catch (e) {
|
||||
print('[EventAssignedEquipmentSection] Error loading equipment/containers: $e');
|
||||
} finally {
|
||||
@@ -173,18 +147,16 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
}
|
||||
}
|
||||
|
||||
// Charger les équipements des conteneurs pour vérifier les conflits
|
||||
// Charger les équipements et conteneurs
|
||||
final containerProvider = context.read<ContainerProvider>();
|
||||
final equipmentProvider = context.read<EquipmentProvider>();
|
||||
|
||||
final allContainers = await containerProvider.containersStream.first;
|
||||
final allEquipment = await equipmentProvider.equipmentStream.first;
|
||||
|
||||
// Collecter TOUS les équipements à vérifier (directs + enfants des boîtes)
|
||||
final equipmentIds = newEquipment.map((e) => e.equipmentId).toList();
|
||||
final equipmentNames = <String, String>{};
|
||||
final allConflicts = <String, List<AvailabilityConflict>>{};
|
||||
|
||||
// Ajouter les équipements directs
|
||||
// 1. Vérifier les conflits pour les équipements directs
|
||||
for (var eq in newEquipment) {
|
||||
final equipment = allEquipment.firstWhere(
|
||||
(e) => e.id == eq.equipmentId,
|
||||
@@ -199,10 +171,51 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
equipmentNames[eq.equipmentId] = equipment.id;
|
||||
|
||||
// Pour les équipements quantifiables (consommables/câbles)
|
||||
if (equipment.hasQuantity) {
|
||||
// Vérifier la quantité disponible
|
||||
final availableQty = await _availabilityService.getAvailableQuantity(
|
||||
equipment: equipment,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
|
||||
// ⚠️ Ne créer un conflit QUE si la quantité demandée est supérieure à la quantité disponible
|
||||
if (eq.quantity > availableQty) {
|
||||
// Il y a vraiment un conflit de quantité
|
||||
final conflicts = await _availabilityService.checkEquipmentAvailabilityWithQuantity(
|
||||
equipment: equipment,
|
||||
requestedQuantity: eq.quantity,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
|
||||
// Ne garder que les conflits réels (quand il n'y a pas assez de stock)
|
||||
if (conflicts.isNotEmpty) {
|
||||
allConflicts[eq.equipmentId] = conflicts;
|
||||
}
|
||||
}
|
||||
// ✅ Sinon, pas de conflit : il y a assez de stock disponible
|
||||
} else {
|
||||
// Pour les équipements non quantifiables (vérification classique)
|
||||
final conflicts = await _availabilityService.checkEquipmentAvailability(
|
||||
equipmentId: equipment.id,
|
||||
equipmentName: equipment.name,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
|
||||
if (conflicts.isNotEmpty) {
|
||||
allConflicts[eq.equipmentId] = conflicts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ajouter les équipements des conteneurs (par composition)
|
||||
// 2. Vérifier les conflits pour les boîtes et leur contenu
|
||||
for (var containerId in newContainers) {
|
||||
final container = allContainers.firstWhere(
|
||||
(c) => c.id == containerId,
|
||||
@@ -217,76 +230,105 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
),
|
||||
);
|
||||
|
||||
// Ajouter tous les équipements enfants pour vérification
|
||||
for (var childEquipmentId in container.equipmentIds) {
|
||||
if (!equipmentIds.contains(childEquipmentId)) {
|
||||
equipmentIds.add(childEquipmentId);
|
||||
// Récupérer les équipements de la boîte
|
||||
final containerEquipment = container.equipmentIds
|
||||
.map((eqId) => allEquipment.firstWhere(
|
||||
(e) => e.id == eqId,
|
||||
orElse: () => EquipmentModel(
|
||||
id: eqId,
|
||||
name: 'Inconnu',
|
||||
category: EquipmentCategory.other,
|
||||
status: EquipmentStatus.available,
|
||||
parentBoxIds: [],
|
||||
maintenanceIds: [],
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
))
|
||||
.toList();
|
||||
|
||||
final equipment = allEquipment.firstWhere(
|
||||
(e) => e.id == childEquipmentId,
|
||||
orElse: () => EquipmentModel(
|
||||
id: childEquipmentId,
|
||||
name: 'Inconnu',
|
||||
category: EquipmentCategory.other,
|
||||
status: EquipmentStatus.available,
|
||||
parentBoxIds: [],
|
||||
maintenanceIds: [],
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
// Vérifier chaque équipement de la boîte individuellement
|
||||
final containerConflicts = <AvailabilityConflict>[];
|
||||
|
||||
for (var equipment in containerEquipment) {
|
||||
if (equipment.hasQuantity) {
|
||||
// Pour les consommables/câbles, vérifier la quantité disponible
|
||||
final availableQty = await _availabilityService.getAvailableQuantity(
|
||||
equipment: equipment,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
equipmentNames[childEquipmentId] = '${equipment.id} (dans ${container.name})';
|
||||
|
||||
// La boîte contient 1 unité de cet équipement
|
||||
// Si la quantité disponible est insuffisante, créer un conflit
|
||||
if (availableQty < 1) {
|
||||
final conflicts = await _availabilityService.checkEquipmentAvailability(
|
||||
equipmentId: equipment.id,
|
||||
equipmentName: equipment.name,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
containerConflicts.addAll(conflicts);
|
||||
}
|
||||
} else {
|
||||
// Pour les équipements non quantifiables
|
||||
final conflicts = await _availabilityService.checkEquipmentAvailability(
|
||||
equipmentId: equipment.id,
|
||||
equipmentName: equipment.name,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
containerConflicts.addAll(conflicts);
|
||||
}
|
||||
}
|
||||
|
||||
if (containerConflicts.isNotEmpty) {
|
||||
allConflicts[containerId] = containerConflicts;
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier les conflits pour TOUS les équipements (directs + enfants)
|
||||
final conflicts = await _availabilityService.checkMultipleEquipmentAvailability(
|
||||
equipmentIds: equipmentIds,
|
||||
equipmentNames: equipmentNames,
|
||||
startDate: widget.startDate!,
|
||||
endDate: widget.endDate!,
|
||||
excludeEventId: widget.eventId,
|
||||
);
|
||||
|
||||
if (conflicts.isNotEmpty) {
|
||||
if (allConflicts.isNotEmpty) {
|
||||
// Afficher le dialog de conflits
|
||||
final action = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => EquipmentConflictDialog(conflicts: conflicts),
|
||||
builder: (context) => EquipmentConflictDialog(conflicts: allConflicts),
|
||||
);
|
||||
|
||||
if (action == 'cancel') {
|
||||
return; // Annuler l'ajout
|
||||
} else if (action == 'force_removed') {
|
||||
// Identifier quels équipements retirer
|
||||
final removedIds = conflicts.keys.toSet();
|
||||
// Identifier quels équipements/conteneurs retirer
|
||||
final removedIds = allConflicts.keys.toSet();
|
||||
|
||||
// Retirer les équipements directs en conflit
|
||||
newEquipment.removeWhere((eq) => removedIds.contains(eq.equipmentId));
|
||||
|
||||
// Retirer les boîtes dont au moins un équipement enfant est en conflit
|
||||
final containersToRemove = <String>[];
|
||||
for (var containerId in newContainers) {
|
||||
final container = allContainers.firstWhere((c) => c.id == containerId);
|
||||
final hasConflict = container.equipmentIds.any((eqId) => removedIds.contains(eqId));
|
||||
// Retirer les boîtes en conflit
|
||||
newContainers.removeWhere((containerId) => removedIds.contains(containerId));
|
||||
|
||||
if (hasConflict) {
|
||||
containersToRemove.add(containerId);
|
||||
}
|
||||
}
|
||||
|
||||
for (var containerId in containersToRemove) {
|
||||
newContainers.remove(containerId);
|
||||
|
||||
// Informer l'utilisateur
|
||||
// Informer l'utilisateur des boîtes retirées
|
||||
for (var containerId in removedIds.where((id) => newContainers.contains(id))) {
|
||||
if (mounted) {
|
||||
final containerName = allContainers.firstWhere((c) => c.id == containerId).name;
|
||||
final container = allContainers.firstWhere(
|
||||
(c) => c.id == containerId,
|
||||
orElse: () => ContainerModel(
|
||||
id: containerId,
|
||||
name: 'Inconnu',
|
||||
type: ContainerType.flightCase,
|
||||
status: EquipmentStatus.available,
|
||||
equipmentIds: [],
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('La boîte "$containerName" a été retirée car elle contient du matériel en conflit.'),
|
||||
content: Text('La boîte "${container.name}" a été retirée en raison de conflits.'),
|
||||
backgroundColor: Colors.orange,
|
||||
duration: const Duration(seconds: 4),
|
||||
duration: const Duration(seconds: 3),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -299,8 +341,21 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
final updatedEquipment = [...widget.assignedEquipment];
|
||||
final updatedContainers = [...widget.assignedContainers];
|
||||
|
||||
// Pour chaque nouvel équipement
|
||||
for (var eq in newEquipment) {
|
||||
if (!updatedEquipment.any((e) => e.equipmentId == eq.equipmentId)) {
|
||||
final existingIndex = updatedEquipment.indexWhere((e) => e.equipmentId == eq.equipmentId);
|
||||
|
||||
if (existingIndex != -1) {
|
||||
// L'équipement existe déjà : mettre à jour la quantité
|
||||
updatedEquipment[existingIndex] = EventEquipment(
|
||||
equipmentId: eq.equipmentId,
|
||||
quantity: eq.quantity, // Utiliser la nouvelle quantité
|
||||
isPrepared: updatedEquipment[existingIndex].isPrepared,
|
||||
isReturned: updatedEquipment[existingIndex].isReturned,
|
||||
returnedQuantity: updatedEquipment[existingIndex].returnedQuantity,
|
||||
);
|
||||
} else {
|
||||
// L'équipement n'existe pas : l'ajouter
|
||||
updatedEquipment.add(eq);
|
||||
}
|
||||
}
|
||||
@@ -347,11 +402,6 @@ class _EventAssignedEquipmentSectionState extends State<EventAssignedEquipmentSe
|
||||
return true;
|
||||
}).toList();
|
||||
|
||||
print('[EventAssignedEquipmentSection] Removing container $containerId');
|
||||
if (container != null) {
|
||||
print('[EventAssignedEquipmentSection] Removing ${container.equipmentIds.length} children: ${container.equipmentIds}');
|
||||
}
|
||||
print('[EventAssignedEquipmentSection] Equipment before: ${widget.assignedEquipment.length}, after: ${updatedEquipment.length}');
|
||||
|
||||
// Notifier le changement avec les deux listes mises à jour
|
||||
widget.onChanged(updatedEquipment, updatedContainers);
|
||||
|
||||
Reference in New Issue
Block a user