Files
EM2_ERP/em2rp/lib/models/equipment_model.dart

280 lines
9.2 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
enum EquipmentStatus {
available, // Disponible
inUse, // En prestation
rented, // Loué
lost, // Perdu
outOfService, // HS
maintenance, // En maintenance
}
String equipmentStatusToString(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return 'AVAILABLE';
case EquipmentStatus.inUse:
return 'IN_USE';
case EquipmentStatus.rented:
return 'RENTED';
case EquipmentStatus.lost:
return 'LOST';
case EquipmentStatus.outOfService:
return 'OUT_OF_SERVICE';
case EquipmentStatus.maintenance:
return 'MAINTENANCE';
}
}
EquipmentStatus equipmentStatusFromString(String? status) {
switch (status) {
case 'AVAILABLE':
return EquipmentStatus.available;
case 'IN_USE':
return EquipmentStatus.inUse;
case 'RENTED':
return EquipmentStatus.rented;
case 'LOST':
return EquipmentStatus.lost;
case 'OUT_OF_SERVICE':
return EquipmentStatus.outOfService;
case 'MAINTENANCE':
return EquipmentStatus.maintenance;
default:
return EquipmentStatus.available;
}
}
enum EquipmentCategory {
lighting, // Lumière
sound, // Son
video, // Vidéo
effect, // Effets spéciaux
structure, // Structure
consumable, // Consommable
cable, // Câble
other // Autre
}
String equipmentCategoryToString(EquipmentCategory category) {
switch (category) {
case EquipmentCategory.lighting:
return 'LIGHTING';
case EquipmentCategory.sound:
return 'SOUND';
case EquipmentCategory.video:
return 'VIDEO';
case EquipmentCategory.structure:
return 'STRUCTURE';
case EquipmentCategory.consumable:
return 'CONSUMABLE';
case EquipmentCategory.cable:
return 'CABLE';
case EquipmentCategory.other:
return 'OTHER';
case EquipmentCategory.effect:
return 'EFFECT';
}
}
EquipmentCategory equipmentCategoryFromString(String? category) {
switch (category) {
case 'LIGHTING':
return EquipmentCategory.lighting;
case 'SOUND':
return EquipmentCategory.sound;
case 'VIDEO':
return EquipmentCategory.video;
case 'STRUCTURE':
return EquipmentCategory.structure;
case 'CONSUMABLE':
return EquipmentCategory.consumable;
case 'CABLE':
return EquipmentCategory.cable;
case 'EFFECT':
return EquipmentCategory.effect;
case 'OTHER':
default:
return EquipmentCategory.other;
}
}
class EquipmentModel {
final String id; // Identifiant unique (clé)
final String name; // Nom de l'équipement
final String? brand; // Marque (indexé)
final String? model; // Modèle (indexé)
final EquipmentCategory category; // Catégorie
final EquipmentStatus status; // Statut actuel
// Prix (visible uniquement avec manage_equipment)
final double? purchasePrice; // Prix d'achat
final double? rentalPrice; // Prix de location
// Quantité (pour consommables/câbles)
final int? totalQuantity; // Quantité totale
final int? availableQuantity; // Quantité disponible
final int? criticalThreshold; // Seuil critique pour alerte
// Boîtes parentes (plusieurs possibles)
final List<String> parentBoxIds; // IDs des boîtes contenant cet équipement
// Dates & maintenance
final DateTime? purchaseDate; // Date d'achat
final DateTime? lastMaintenanceDate; // Dernière maintenance
final DateTime? nextMaintenanceDate; // Prochaine maintenance prévue
// Maintenances (références)
final List<String> maintenanceIds; // IDs des opérations de maintenance
// Image
final String? imageUrl; // URL de l'image (Storage /materiel)
// Métadonnées
final String? notes; // Notes additionnelles
final DateTime createdAt; // Date de création
final DateTime updatedAt; // Date de mise à jour
EquipmentModel({
required this.id,
required this.name,
this.brand,
this.model,
required this.category,
this.status = EquipmentStatus.available,
this.purchasePrice,
this.rentalPrice,
this.totalQuantity,
this.availableQuantity,
this.criticalThreshold,
this.parentBoxIds = const [],
this.purchaseDate,
this.lastMaintenanceDate,
this.nextMaintenanceDate,
this.maintenanceIds = const [],
this.imageUrl,
this.notes,
required this.createdAt,
required this.updatedAt,
});
factory EquipmentModel.fromMap(Map<String, dynamic> map, String id) {
// Gestion des listes
final List<dynamic> parentBoxIdsRaw = map['parentBoxIds'] ?? [];
final List<String> parentBoxIds = parentBoxIdsRaw.map((e) => e.toString()).toList();
final List<dynamic> maintenanceIdsRaw = map['maintenanceIds'] ?? [];
final List<String> maintenanceIds = maintenanceIdsRaw.map((e) => e.toString()).toList();
return EquipmentModel(
id: id,
name: map['name'] ?? '',
brand: map['brand'],
model: map['model'],
category: equipmentCategoryFromString(map['category']),
status: equipmentStatusFromString(map['status']),
purchasePrice: map['purchasePrice']?.toDouble(),
rentalPrice: map['rentalPrice']?.toDouble(),
totalQuantity: map['totalQuantity']?.toInt(),
availableQuantity: map['availableQuantity']?.toInt(),
criticalThreshold: map['criticalThreshold']?.toInt(),
parentBoxIds: parentBoxIds,
purchaseDate: (map['purchaseDate'] as Timestamp?)?.toDate(),
nextMaintenanceDate: (map['nextMaintenanceDate'] as Timestamp?)?.toDate(),
maintenanceIds: maintenanceIds,
imageUrl: map['imageUrl'],
notes: map['notes'],
createdAt: (map['createdAt'] as Timestamp?)?.toDate() ?? DateTime.now(),
updatedAt: (map['updatedAt'] as Timestamp?)?.toDate() ?? DateTime.now(),
);
}
Map<String, dynamic> toMap() {
return {
'name': name,
'brand': brand,
'model': model,
'category': equipmentCategoryToString(category),
'status': equipmentStatusToString(status),
'purchasePrice': purchasePrice,
'rentalPrice': rentalPrice,
'totalQuantity': totalQuantity,
'availableQuantity': availableQuantity,
'criticalThreshold': criticalThreshold,
'parentBoxIds': parentBoxIds,
'lastMaintenanceDate': lastMaintenanceDate != null ? Timestamp.fromDate(lastMaintenanceDate!) : null,
'purchaseDate': purchaseDate != null ? Timestamp.fromDate(purchaseDate!) : null,
'nextMaintenanceDate': nextMaintenanceDate != null ? Timestamp.fromDate(nextMaintenanceDate!) : null,
'maintenanceIds': maintenanceIds,
'imageUrl': imageUrl,
'notes': notes,
'createdAt': Timestamp.fromDate(createdAt),
'updatedAt': Timestamp.fromDate(updatedAt),
};
}
EquipmentModel copyWith({
String? id,
String? brand,
String? name,
String? model,
EquipmentCategory? category,
EquipmentStatus? status,
double? purchasePrice,
double? rentalPrice,
int? totalQuantity,
int? availableQuantity,
int? criticalThreshold,
List<String>? parentBoxIds,
DateTime? purchaseDate,
DateTime? lastMaintenanceDate,
DateTime? nextMaintenanceDate,
List<String>? maintenanceIds,
String? imageUrl,
String? notes,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return EquipmentModel(
id: id ?? this.id,
brand: brand ?? this.brand,
name: name ?? this.name,
model: model ?? this.model,
category: category ?? this.category,
status: status ?? this.status,
purchasePrice: purchasePrice ?? this.purchasePrice,
rentalPrice: rentalPrice ?? this.rentalPrice,
totalQuantity: totalQuantity ?? this.totalQuantity,
availableQuantity: availableQuantity ?? this.availableQuantity,
criticalThreshold: criticalThreshold ?? this.criticalThreshold,
parentBoxIds: parentBoxIds ?? this.parentBoxIds,
lastMaintenanceDate: lastMaintenanceDate ?? this.lastMaintenanceDate,
purchaseDate: purchaseDate ?? this.purchaseDate,
nextMaintenanceDate: nextMaintenanceDate ?? this.nextMaintenanceDate,
maintenanceIds: maintenanceIds ?? this.maintenanceIds,
imageUrl: imageUrl ?? this.imageUrl,
notes: notes ?? this.notes,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
// Helper pour vérifier si c'est un consommable/câble avec quantité
bool get hasQuantity => category == EquipmentCategory.consumable || category == EquipmentCategory.cable;
// Helper pour vérifier si le stock est critique
bool get isCriticalStock {
if (!hasQuantity || criticalThreshold == null || availableQuantity == null) {
return false;
}
return availableQuantity! <= criticalThreshold!;
}
// Helper pour vérifier si la maintenance est à venir
bool get isMaintenanceDue {
if (nextMaintenanceDate == null) return false;
return nextMaintenanceDate!.isBefore(DateTime.now().add(const Duration(days: 7)));
}
}