feat: implement comprehensive Firebase Functions backend for equipment management and migrate core repository services
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
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});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user