feat: implement equipment and container loading rollback functionality with corresponding backend cloud functions
This commit is contained in:
@@ -470,7 +470,7 @@ exports.findAlternativeEquipment = async (req, res) => {
|
||||
const alternatives = [];
|
||||
equipmentsSnapshot.docs.forEach((doc) => {
|
||||
const data = doc.data();
|
||||
if (!conflictingEquipmentIds.has(doc.id) && data.status === "available") {
|
||||
if (!conflictingEquipmentIds.has(doc.id) && data.status === "AVAILABLE") {
|
||||
alternatives.push({
|
||||
id: doc.id,
|
||||
...helpers.serializeTimestamps(data, ["purchaseDate", "nextMaintenanceDate", "lastMaintenanceDate", "createdAt", "updatedAt"]),
|
||||
@@ -560,15 +560,15 @@ exports.calculateEquipmentStatuses = async (req, res) => {
|
||||
let calculatedStatus = equipmentData.status;
|
||||
|
||||
// Si l'équipement est perdu ou HS, garder ce statut
|
||||
if (equipmentData.status === "lost" || equipmentData.status === "outOfService") {
|
||||
if (equipmentData.status === "LOST" || equipmentData.status === "OUT_OF_SERVICE") {
|
||||
calculatedStatus = equipmentData.status;
|
||||
} else if (equipmentIdsInUse.has(equipmentId)) {
|
||||
calculatedStatus = "inUse";
|
||||
} else if (equipmentData.status === "maintenance" ||
|
||||
equipmentData.status === "rented") {
|
||||
calculatedStatus = "IN_USE";
|
||||
} else if (equipmentData.status === "MAINTENANCE" ||
|
||||
equipmentData.status === "RENTED") {
|
||||
calculatedStatus = equipmentData.status;
|
||||
} else {
|
||||
calculatedStatus = "available";
|
||||
calculatedStatus = "AVAILABLE";
|
||||
}
|
||||
|
||||
statuses[equipmentId] = calculatedStatus;
|
||||
|
||||
@@ -651,121 +651,7 @@ exports.getEventWithDetails = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Helper: Mettre à jour le statut d'un équipement
|
||||
async function updateEquipmentStatus(equipmentId, status) {
|
||||
try {
|
||||
const doc = await db.collection("equipments").doc(equipmentId).get();
|
||||
if (!doc.exists) {
|
||||
logger.warn(`Equipment ${equipmentId} does not exist, skipping status update`);
|
||||
return;
|
||||
}
|
||||
|
||||
await db.collection("equipments").doc(equipmentId).update({
|
||||
status: status,
|
||||
updatedAt: admin.firestore.Timestamp.now(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(`Error updating equipment status for ${equipmentId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Valider un équipement individuel en préparation
|
||||
exports.validateEquipmentPreparation = async (req, res) => {
|
||||
try {
|
||||
const decodedToken = await auth.authenticateUser(req);
|
||||
const canManage = await auth.hasPermission(decodedToken.uid, "manage_events");
|
||||
if (!canManage) {
|
||||
res.status(403).json({error: "Forbidden: Requires manage_events permission"});
|
||||
return;
|
||||
}
|
||||
|
||||
const {eventId, equipmentId} = req.body.data;
|
||||
if (!eventId || !equipmentId) {
|
||||
res.status(400).json({error: "eventId and equipmentId are required"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventDoc = await db.collection("events").doc(eventId).get();
|
||||
if (!eventDoc.exists) {
|
||||
res.status(404).json({error: "Event not found"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventData = eventDoc.data();
|
||||
const assignedEquipment = eventData.assignedEquipment || [];
|
||||
|
||||
// Mettre à jour le statut de l'équipement
|
||||
const updatedEquipment = assignedEquipment.map((eq) => {
|
||||
if (eq.equipmentId === equipmentId) {
|
||||
return {...eq, isPrepared: true};
|
||||
}
|
||||
return eq;
|
||||
});
|
||||
|
||||
// Vérifier si tous sont préparés
|
||||
const allPrepared = updatedEquipment.every((eq) => eq.isPrepared);
|
||||
|
||||
const updateData = {
|
||||
assignedEquipment: updatedEquipment,
|
||||
preparationStatus: allPrepared ? "completed" : "inProgress",
|
||||
};
|
||||
|
||||
await db.collection("events").doc(eventId).update(updateData);
|
||||
|
||||
res.status(200).json({success: true, allPrepared});
|
||||
} catch (error) {
|
||||
logger.error("Error validating equipment preparation:", error);
|
||||
res.status(500).json({error: error.message});
|
||||
}
|
||||
};
|
||||
|
||||
// Valider tous les équipements en préparation
|
||||
exports.validateAllPreparation = async (req, res) => {
|
||||
try {
|
||||
const decodedToken = await auth.authenticateUser(req);
|
||||
const canManage = await auth.hasPermission(decodedToken.uid, "manage_events");
|
||||
if (!canManage) {
|
||||
res.status(403).json({error: "Forbidden: Requires manage_events permission"});
|
||||
return;
|
||||
}
|
||||
|
||||
const {eventId} = req.body.data;
|
||||
if (!eventId) {
|
||||
res.status(400).json({error: "eventId is required"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventDoc = await db.collection("events").doc(eventId).get();
|
||||
if (!eventDoc.exists) {
|
||||
res.status(404).json({error: "Event not found"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventData = eventDoc.data();
|
||||
const assignedEquipment = eventData.assignedEquipment || [];
|
||||
|
||||
// Marquer tous comme préparés
|
||||
const updatedEquipment = assignedEquipment.map((eq) => ({
|
||||
...eq,
|
||||
isPrepared: true,
|
||||
}));
|
||||
|
||||
await db.collection("events").doc(eventId).update({
|
||||
assignedEquipment: updatedEquipment,
|
||||
preparationStatus: "completed",
|
||||
});
|
||||
|
||||
// Mettre à jour le statut des équipements à "inUse"
|
||||
for (const equipment of assignedEquipment) {
|
||||
await updateEquipmentStatus(equipment.equipmentId, "inUse");
|
||||
}
|
||||
|
||||
res.status(200).json({success: true});
|
||||
} catch (error) {
|
||||
logger.error("Error validating all preparation:", error);
|
||||
res.status(500).json({error: error.message});
|
||||
}
|
||||
};
|
||||
|
||||
// Valider un équipement individuel pour le chargement
|
||||
exports.validateEquipmentLoading = async (req, res) => {
|
||||
@@ -947,136 +833,4 @@ exports.validateAllUnloading = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Valider un équipement individuel pour le retour
|
||||
exports.validateEquipmentReturn = async (req, res) => {
|
||||
try {
|
||||
const decodedToken = await auth.authenticateUser(req);
|
||||
const canManage = await auth.hasPermission(decodedToken.uid, "manage_events");
|
||||
if (!canManage) {
|
||||
res.status(403).json({error: "Forbidden: Requires manage_events permission"});
|
||||
return;
|
||||
}
|
||||
|
||||
const {eventId, equipmentId, returnedQuantity} = req.body.data;
|
||||
if (!eventId || !equipmentId) {
|
||||
res.status(400).json({error: "eventId and equipmentId are required"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventDoc = await db.collection("events").doc(eventId).get();
|
||||
if (!eventDoc.exists) {
|
||||
res.status(404).json({error: "Event not found"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventData = eventDoc.data();
|
||||
const assignedEquipment = eventData.assignedEquipment || [];
|
||||
|
||||
const updatedEquipment = assignedEquipment.map((eq) => {
|
||||
if (eq.equipmentId === equipmentId) {
|
||||
return {
|
||||
...eq,
|
||||
isReturned: true,
|
||||
returnedQuantity: returnedQuantity !== undefined ? returnedQuantity : eq.returnedQuantity,
|
||||
};
|
||||
}
|
||||
return eq;
|
||||
});
|
||||
|
||||
const allReturned = updatedEquipment.every((eq) => eq.isReturned);
|
||||
|
||||
const updateData = {
|
||||
assignedEquipment: updatedEquipment,
|
||||
returnStatus: allReturned ? "completed" : "inProgress",
|
||||
};
|
||||
|
||||
await db.collection("events").doc(eventId).update(updateData);
|
||||
|
||||
// Mettre à jour le stock si c'est un consommable
|
||||
if (returnedQuantity !== undefined) {
|
||||
const equipmentDoc = await db.collection("equipments").doc(equipmentId).get();
|
||||
if (equipmentDoc.exists) {
|
||||
const equipmentData = equipmentDoc.data();
|
||||
if (equipmentData.hasQuantity) {
|
||||
const currentAvailable = equipmentData.availableQuantity || 0;
|
||||
await db.collection("equipments").doc(equipmentId).update({
|
||||
availableQuantity: currentAvailable + returnedQuantity,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({success: true, allReturned});
|
||||
} catch (error) {
|
||||
logger.error("Error validating equipment return:", error);
|
||||
res.status(500).json({error: error.message});
|
||||
}
|
||||
};
|
||||
|
||||
// Valider tous les retours
|
||||
exports.validateAllReturn = async (req, res) => {
|
||||
try {
|
||||
const decodedToken = await auth.authenticateUser(req);
|
||||
const canManage = await auth.hasPermission(decodedToken.uid, "manage_events");
|
||||
if (!canManage) {
|
||||
res.status(403).json({error: "Forbidden: Requires manage_events permission"});
|
||||
return;
|
||||
}
|
||||
|
||||
const {eventId, returnedQuantities} = req.body.data;
|
||||
if (!eventId) {
|
||||
res.status(400).json({error: "eventId is required"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventDoc = await db.collection("events").doc(eventId).get();
|
||||
if (!eventDoc.exists) {
|
||||
res.status(404).json({error: "Event not found"});
|
||||
return;
|
||||
}
|
||||
|
||||
const eventData = eventDoc.data();
|
||||
const assignedEquipment = eventData.assignedEquipment || [];
|
||||
|
||||
const updatedEquipment = assignedEquipment.map((eq) => {
|
||||
const returnedQty = returnedQuantities?.[eq.equipmentId] || eq.returnedQuantity || eq.quantity;
|
||||
return {
|
||||
...eq,
|
||||
isReturned: true,
|
||||
returnedQuantity: returnedQty,
|
||||
};
|
||||
});
|
||||
|
||||
await db.collection("events").doc(eventId).update({
|
||||
assignedEquipment: updatedEquipment,
|
||||
returnStatus: "completed",
|
||||
});
|
||||
|
||||
// Mettre à jour le statut des équipements à "available" et gérer les stocks
|
||||
for (const equipment of updatedEquipment) {
|
||||
const equipmentDoc = await db.collection("equipments").doc(equipment.equipmentId).get();
|
||||
if (equipmentDoc.exists) {
|
||||
const equipmentData = equipmentDoc.data();
|
||||
|
||||
// Mettre à jour le statut uniquement pour les équipements non quantifiables
|
||||
if (!equipmentData.hasQuantity) {
|
||||
await updateEquipmentStatus(equipment.equipmentId, "available");
|
||||
}
|
||||
|
||||
// Restaurer le stock pour les consommables
|
||||
if (equipmentData.hasQuantity && equipment.returnedQuantity) {
|
||||
const currentAvailable = equipmentData.availableQuantity || 0;
|
||||
await db.collection("equipments").doc(equipment.equipmentId).update({
|
||||
availableQuantity: currentAvailable + equipment.returnedQuantity,
|
||||
updatedAt: admin.firestore.Timestamp.now(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({success: true});
|
||||
} catch (error) {
|
||||
logger.error("Error validating all return:", error);
|
||||
res.status(500).json({error: error.message});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user