/** * Helpers pour la manipulation de données Firestore */ const admin = require("firebase-admin"); /** * Convertit les Timestamps Firestore en ISO strings pour JSON */ function serializeTimestamps(data) { if (!data) return data; // Éviter la récursion sur les types Firestore spéciaux if (data._firestore || data._path || data._converter) { // C'est un objet Firestore interne, ne pas le traiter if (data.id && data.path) { // C'est une DocumentReference return data.path; } return null; } const result = {...data}; for (const key in result) { const value = result[key]; if (!value) { continue; } // Gérer les Timestamps Firestore if (value.toDate && typeof value.toDate === "function") { result[key] = value.toDate().toISOString(); } // Gérer les DocumentReference else if (value.path && value.id && typeof value.path === "string") { result[key] = value.path; } // Gérer les GeoPoint else if (value.latitude !== undefined && value.longitude !== undefined) { result[key] = { latitude: value.latitude, longitude: value.longitude, }; } // Gérer les tableaux else if (Array.isArray(value)) { result[key] = value.map((item) => { if (!item || typeof item !== "object") return item; // DocumentReference dans un tableau if (item.path && item.id) { return item.path; } // Timestamp dans un tableau if (item.toDate && typeof item.toDate === "function") { return item.toDate().toISOString(); } // Objet normal return serializeTimestamps(item); }); } // Gérer les objets imbriqués (mais pas les objets Firestore) else if (typeof value === "object" && !value._firestore && !value._path) { result[key] = serializeTimestamps(value); } } return result; } /** * Convertit les ISO strings en Timestamps Firestore */ function deserializeTimestamps(data, timestampFields = []) { if (!data) return data; const result = {...data}; for (const field of timestampFields) { if (result[field] && typeof result[field] === "string") { result[field] = admin.firestore.Timestamp.fromDate(new Date(result[field])); } } return result; } /** * Convertit les références DocumentReference en IDs */ function serializeReferences(data) { if (!data) return data; const result = {...data}; for (const key in result) { if (result[key] && result[key].path && typeof result[key].path === "string") { // C'est une DocumentReference result[key] = result[key].id; } else if (Array.isArray(result[key])) { result[key] = result[key].map((item) => { if (item && item.path && typeof item.path === "string") { return item.id; } return item; }); } } return result; } /** * Masque les champs sensibles selon les permissions */ function maskSensitiveFields(data, canViewSensitive) { if (canViewSensitive) return data; const masked = {...data}; // Masquer les prix si pas de permission manage_equipment delete masked.purchasePrice; delete masked.rentalPrice; return masked; } /** * Pagination helper */ function paginate(query, limit = 50, startAfter = null) { let paginatedQuery = query.limit(limit); if (startAfter) { paginatedQuery = paginatedQuery.startAfter(startAfter); } return paginatedQuery; } /** * Filtre les événements annulés */ function filterCancelledEvents(events) { return events.filter((event) => event.status !== "CANCELLED"); } /** * Convertit les IDs en DocumentReference pour maintenir la compatibilité avec l'ancien format * @param {Object} data - Données de l'événement * @return {Object} - Données avec DocumentReference */ function convertIdsToReferences(data) { if (!data) return data; const result = {...data}; // Convertir EventType (ID → DocumentReference) if (result.EventType && typeof result.EventType === "string" && !result.EventType.includes("/")) { result.EventType = admin.firestore().collection("eventTypes").doc(result.EventType); } // Convertir customer (ID → DocumentReference) if (result.customer && typeof result.customer === "string" && !result.customer.includes("/")) { result.customer = admin.firestore().collection("customers").doc(result.customer); } // Convertir workforce (IDs → DocumentReference) if (Array.isArray(result.workforce)) { result.workforce = result.workforce.map((item) => { if (typeof item === "string" && !item.includes("/")) { return admin.firestore().collection("users").doc(item); } return item; }); } return result; } module.exports = { serializeTimestamps, deserializeTimestamps, serializeReferences, maskSensitiveFields, paginate, filterCancelledEvents, convertIdsToReferences, };