329 lines
11 KiB
JavaScript
329 lines
11 KiB
JavaScript
const admin = require("firebase-admin");
|
|
const db = admin.firestore();
|
|
const logger = require("firebase-functions/logger");
|
|
const auth = require("../utils/auth");
|
|
const helpers = require("../utils/helpers");
|
|
|
|
// Créer une maintenance
|
|
exports.createMaintenance = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
const hasAccess = await auth.hasPermission(decodedToken.uid, "manage_maintenances");
|
|
|
|
if (!hasAccess) {
|
|
res.status(403).json({error: "Forbidden: Requires manage_maintenances permission"});
|
|
return;
|
|
}
|
|
|
|
const maintenanceData = req.body.data;
|
|
|
|
const dataToSave = helpers.deserializeTimestamps(maintenanceData, [
|
|
"scheduledDate", "completedDate", "createdAt", "updatedAt",
|
|
]);
|
|
|
|
const docRef = await db.collection("maintenances").add(dataToSave);
|
|
const maintenanceId = docRef.id;
|
|
|
|
if (maintenanceData.equipmentIds && Array.isArray(maintenanceData.equipmentIds)) {
|
|
for (const equipmentId of maintenanceData.equipmentIds) {
|
|
try {
|
|
const equipmentDoc = await db.collection("equipments").doc(equipmentId).get();
|
|
if (equipmentDoc.exists) {
|
|
const equipmentData = equipmentDoc.data();
|
|
const maintenanceIds = equipmentData.maintenanceIds || [];
|
|
if (!maintenanceIds.includes(maintenanceId)) {
|
|
maintenanceIds.push(maintenanceId);
|
|
await db.collection("equipments").doc(equipmentId).update({
|
|
maintenanceIds: maintenanceIds,
|
|
});
|
|
}
|
|
}
|
|
|
|
if (maintenanceData.scheduledDate) {
|
|
const scheduledDate = maintenanceData.scheduledDate.toDate ?
|
|
maintenanceData.scheduledDate.toDate() :
|
|
new Date(maintenanceData.scheduledDate);
|
|
const sevenDaysFromNow = new Date();
|
|
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7);
|
|
|
|
if (scheduledDate <= sevenDaysFromNow) {
|
|
const existingAlerts = await db.collection("alerts")
|
|
.where("equipmentId", "==", equipmentId)
|
|
.where("type", "==", "maintenanceDue")
|
|
.where("isRead", "==", false)
|
|
.get();
|
|
|
|
let alertExists = false;
|
|
for (const alertDoc of existingAlerts.docs) {
|
|
const alertData = alertDoc.data();
|
|
if (alertData.message && alertData.message.includes(maintenanceData.name || "")) {
|
|
alertExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!alertExists) {
|
|
const equipmentName = equipmentDoc.exists ?
|
|
(equipmentDoc.data().name || equipmentId) :
|
|
equipmentId;
|
|
|
|
const daysUntil = Math.ceil((scheduledDate - new Date()) / (1000 * 60 * 60 * 24));
|
|
|
|
await db.collection("alerts").add({
|
|
type: "maintenanceDue",
|
|
message: `Maintenance "${maintenanceData.name || "Sans nom"}" prévue dans ${daysUntil} jour(s) pour ${equipmentName}`,
|
|
equipmentId: equipmentId,
|
|
createdAt: admin.firestore.Timestamp.now(),
|
|
isRead: false,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
logger.error(`Error updating equipment ${equipmentId} for maintenance:`, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
res.status(201).json({id: maintenanceId, message: "Maintenance created successfully"});
|
|
} catch (error) {
|
|
logger.error("Error creating maintenance:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|
|
|
|
// Mettre à jour une maintenance
|
|
exports.updateMaintenance = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
const hasAccess = await auth.hasPermission(decodedToken.uid, "manage_maintenances");
|
|
|
|
if (!hasAccess) {
|
|
res.status(403).json({error: "Forbidden: Requires manage_maintenances permission"});
|
|
return;
|
|
}
|
|
|
|
const {maintenanceId, data} = req.body.data;
|
|
|
|
if (!maintenanceId) {
|
|
res.status(400).json({error: "Maintenance ID is required"});
|
|
return;
|
|
}
|
|
|
|
delete data.id;
|
|
data.updatedAt = admin.firestore.Timestamp.now();
|
|
|
|
const dataToSave = helpers.deserializeTimestamps(data, [
|
|
"scheduledDate", "completedDate",
|
|
]);
|
|
|
|
await db.collection("maintenances").doc(maintenanceId).update(dataToSave);
|
|
|
|
res.status(200).json({message: "Maintenance updated successfully"});
|
|
} catch (error) {
|
|
logger.error("Error updating maintenance:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|
|
|
|
// Récupérer toutes les maintenances
|
|
exports.getMaintenances = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
const {equipmentId} = req.body.data || {};
|
|
|
|
const canView = await auth.hasPermission(decodedToken.uid, "view_equipment");
|
|
|
|
if (!canView) {
|
|
res.status(403).json({error: "Forbidden: Requires equipment permissions"});
|
|
return;
|
|
}
|
|
|
|
let query = db.collection("maintenances");
|
|
|
|
if (equipmentId) {
|
|
query = query.where("equipmentIds", "array-contains", equipmentId);
|
|
}
|
|
|
|
const snapshot = await query.get();
|
|
const maintenances = snapshot.docs.map((doc) => {
|
|
const data = doc.data();
|
|
return {
|
|
id: doc.id,
|
|
...helpers.serializeTimestamps(data, ["scheduledDate", "completedDate", "createdAt", "updatedAt"]),
|
|
};
|
|
});
|
|
|
|
res.status(200).json({maintenances});
|
|
} catch (error) {
|
|
logger.error("Error fetching maintenances:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|
|
|
|
// Supprimer une maintenance
|
|
exports.deleteMaintenance = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
|
|
const canManage = await auth.hasPermission(decodedToken.uid, "manage_equipment");
|
|
if (!canManage) {
|
|
res.status(403).json({error: "Forbidden: Requires manage_equipment permission"});
|
|
return;
|
|
}
|
|
|
|
const maintenanceId = req.body.data?.maintenanceId;
|
|
if (!maintenanceId) {
|
|
res.status(400).json({error: "maintenanceId is required"});
|
|
return;
|
|
}
|
|
|
|
const maintenanceDoc = await db.collection("maintenances").doc(maintenanceId).get();
|
|
if (maintenanceDoc.exists) {
|
|
const maintenance = maintenanceDoc.data();
|
|
|
|
if (maintenance.equipmentIds) {
|
|
for (const equipmentId of maintenance.equipmentIds) {
|
|
const equipmentDoc = await db.collection("equipments").doc(equipmentId).get();
|
|
if (equipmentDoc.exists) {
|
|
const equipmentData = equipmentDoc.data();
|
|
const maintenanceIds = (equipmentData.maintenanceIds || []).filter((id) => id !== maintenanceId);
|
|
await db.collection("equipments").doc(equipmentId).update({maintenanceIds});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
await db.collection("maintenances").doc(maintenanceId).delete();
|
|
|
|
res.status(200).json({success: true});
|
|
} catch (error) {
|
|
logger.error("Error deleting maintenance:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Vérifier les maintenances à venir et créer des alertes
|
|
*/
|
|
exports.checkUpcomingMaintenances = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
const hasAccess = await auth.hasPermission(decodedToken.uid, "manage_equipment");
|
|
|
|
if (!hasAccess) {
|
|
res.status(403).json({error: "Forbidden: Requires manage_equipment permission"});
|
|
return;
|
|
}
|
|
|
|
const sevenDaysFromNow = new Date();
|
|
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7);
|
|
|
|
const now = admin.firestore.Timestamp.now();
|
|
const sevenDaysTimestamp = admin.firestore.Timestamp.fromDate(sevenDaysFromNow);
|
|
|
|
// Récupérer les maintenances planifiées dans les 7 prochains jours
|
|
const maintenancesSnapshot = await db.collection("maintenances")
|
|
.where("scheduledDate", "<=", sevenDaysTimestamp)
|
|
.where("scheduledDate", ">=", now)
|
|
.get();
|
|
|
|
const alertsCreated = [];
|
|
|
|
for (const doc of maintenancesSnapshot.docs) {
|
|
const maintenance = doc.data();
|
|
|
|
// Vérifier si une alerte existe déjà pour cette maintenance
|
|
const existingAlertSnapshot = await db.collection("alerts")
|
|
.where("type", "==", "MAINTENANCE_DUE")
|
|
.where("relatedMaintenanceId", "==", doc.id)
|
|
.get();
|
|
|
|
if (existingAlertSnapshot.empty) {
|
|
// Créer une nouvelle alerte
|
|
const alertData = {
|
|
type: "MAINTENANCE_DUE",
|
|
title: `Maintenance à venir`,
|
|
message: `Une maintenance est prévue pour ${maintenance.equipmentIds?.length || 0} équipement(s)`,
|
|
severity: "MEDIUM",
|
|
isRead: false,
|
|
relatedMaintenanceId: doc.id,
|
|
createdAt: admin.firestore.Timestamp.now(),
|
|
};
|
|
|
|
const alertRef = await db.collection("alerts").add(alertData);
|
|
alertsCreated.push({id: alertRef.id, ...alertData});
|
|
}
|
|
}
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
alertsCreated: alertsCreated.length,
|
|
alerts: alertsCreated,
|
|
});
|
|
} catch (error) {
|
|
logger.error("Error checking upcoming maintenances:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Compléter une maintenance
|
|
*/
|
|
exports.completeMaintenance = async (req, res) => {
|
|
try {
|
|
const decodedToken = await auth.authenticateUser(req);
|
|
const hasAccess = await auth.hasPermission(decodedToken.uid, "manage_equipment");
|
|
|
|
if (!hasAccess) {
|
|
res.status(403).json({error: "Forbidden: Requires manage_equipment permission"});
|
|
return;
|
|
}
|
|
|
|
const {maintenanceId, performedBy, cost} = req.body.data;
|
|
|
|
if (!maintenanceId) {
|
|
res.status(400).json({error: "maintenanceId is required"});
|
|
return;
|
|
}
|
|
|
|
const now = admin.firestore.Timestamp.now();
|
|
const updateData = {
|
|
completedDate: now,
|
|
updatedAt: now,
|
|
};
|
|
|
|
if (performedBy) {
|
|
updateData.performedBy = performedBy;
|
|
}
|
|
|
|
if (cost !== undefined && cost !== null) {
|
|
updateData.cost = cost;
|
|
}
|
|
|
|
// Mettre à jour la maintenance
|
|
await db.collection("maintenances").doc(maintenanceId).update(updateData);
|
|
|
|
// Récupérer la maintenance pour mettre à jour les équipements
|
|
const maintenanceDoc = await db.collection("maintenances").doc(maintenanceId).get();
|
|
const maintenanceData = maintenanceDoc.data();
|
|
|
|
// Mettre à jour la date de dernière maintenance des équipements
|
|
if (maintenanceData && maintenanceData.equipmentIds) {
|
|
const updatePromises = maintenanceData.equipmentIds.map((equipmentId) =>
|
|
db.collection("equipments").doc(equipmentId).update({
|
|
lastMaintenanceDate: now,
|
|
updatedAt: now,
|
|
}),
|
|
);
|
|
|
|
await Promise.all(updatePromises);
|
|
}
|
|
|
|
res.status(200).json({success: true});
|
|
} catch (error) {
|
|
logger.error("Error completing maintenance:", error);
|
|
res.status(500).json({error: error.message});
|
|
}
|
|
};
|