feat: implement equipment and container loading rollback functionality with corresponding backend cloud functions
This commit is contained in:
+101
-19
@@ -190,14 +190,6 @@ exports.getEventWithDetails = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").getEventWithDetails(req, res);
|
||||
}));
|
||||
|
||||
exports.validateEquipmentPreparation = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateEquipmentPreparation(req, res);
|
||||
}));
|
||||
|
||||
exports.validateAllPreparation = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateAllPreparation(req, res);
|
||||
}));
|
||||
|
||||
exports.validateEquipmentLoading = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateEquipmentLoading(req, res);
|
||||
}));
|
||||
@@ -214,14 +206,6 @@ exports.validateAllUnloading = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateAllUnloading(req, res);
|
||||
}));
|
||||
|
||||
exports.validateEquipmentReturn = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateEquipmentReturn(req, res);
|
||||
}));
|
||||
|
||||
exports.validateAllReturn = onRequest(httpOptions, withCors((req, res) => {
|
||||
return require("./src/events").validateAllReturn(req, res);
|
||||
}));
|
||||
|
||||
// ============================================================================
|
||||
// MAINTENANCES
|
||||
// ============================================================================
|
||||
@@ -379,15 +363,19 @@ exports.aiEquipmentProposal = onRequest(aiHttpOptions, withCors((req, res) => {
|
||||
// CALLABLE EMAIL & VALIDATION (LEGACY LAZY WRAPPERS)
|
||||
// ============================================================================
|
||||
exports.sendAlertEmail = onCall({region: "europe-west9", cors: true}, (request) => {
|
||||
return require("./sendAlertEmail").sendAlertEmail(request);
|
||||
return require("./sendAlertEmail").handler(request);
|
||||
});
|
||||
|
||||
exports.createAlert = onCall({region: "europe-west9", cors: true}, (request) => {
|
||||
return require("./createAlert").createAlert(request);
|
||||
return require("./createAlert").handler(request);
|
||||
});
|
||||
|
||||
exports.processEquipmentValidation = onCall({region: "europe-west9", cors: true}, (request) => {
|
||||
return require("./processEquipmentValidation").processEquipmentValidation(request);
|
||||
return require("./processEquipmentValidation").handler(request);
|
||||
});
|
||||
|
||||
exports.rollbackEventStep = onCall({region: "europe-west9", cors: true}, (request) => {
|
||||
return require("./rollbackEventStep").handler(request);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
@@ -515,3 +503,97 @@ exports.onAlertCreated = onDocumentCreated({
|
||||
logger.error("[onAlertCreated] Erreur:", error);
|
||||
}
|
||||
});
|
||||
|
||||
exports.onEventReturnCompleted = onDocumentUpdated({
|
||||
document: "events/{eventId}",
|
||||
region: "europe-west9",
|
||||
}, async (event) => {
|
||||
const before = event.data.before.data();
|
||||
const after = event.data.after.data();
|
||||
const eventId = event.params.eventId;
|
||||
|
||||
try {
|
||||
const beforeReturnStatus = (before.returnStatus || "").toString().toUpperCase();
|
||||
const afterReturnStatus = (after.returnStatus || "").toString().toUpperCase();
|
||||
|
||||
if (afterReturnStatus === "COMPLETED" && beforeReturnStatus !== "COMPLETED") {
|
||||
logger.info(`[onEventReturnCompleted] Event ${eventId} returnStatus completed. Resetting assigned equipments...`);
|
||||
|
||||
const eventRef = db.collection("events").doc(eventId);
|
||||
|
||||
await db.runTransaction(async (transaction) => {
|
||||
const currentEventDoc = await transaction.get(eventRef);
|
||||
if (!currentEventDoc.exists) {
|
||||
logger.warn(`[onEventReturnCompleted] Event doc ${eventId} not found during transaction.`);
|
||||
return;
|
||||
}
|
||||
const currentEventData = currentEventDoc.data();
|
||||
if (currentEventData.stocksRestored === true) {
|
||||
logger.info(`[onEventReturnCompleted] Stocks already restored for event ${eventId}, skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const assignedEquipment = currentEventData.assignedEquipment || [];
|
||||
if (assignedEquipment.length === 0) {
|
||||
logger.info(`[onEventReturnCompleted] No assigned equipment for event ${eventId}.`);
|
||||
transaction.update(eventRef, {
|
||||
stocksRestored: true,
|
||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch all unique equipment docs in the transaction
|
||||
const equipmentIds = Array.from(new Set(assignedEquipment.map((eq) => eq.equipmentId).filter(Boolean)));
|
||||
const equipmentDocsMap = {};
|
||||
|
||||
for (const eqId of equipmentIds) {
|
||||
const eqRef = db.collection("equipments").doc(eqId);
|
||||
const eqDoc = await transaction.get(eqRef);
|
||||
if (eqDoc.exists) {
|
||||
equipmentDocsMap[eqId] = eqDoc.data();
|
||||
}
|
||||
}
|
||||
|
||||
// Update equipment statuses and quantities
|
||||
for (const eq of assignedEquipment) {
|
||||
const eqId = eq.equipmentId;
|
||||
const equipmentData = equipmentDocsMap[eqId];
|
||||
if (!equipmentData) continue;
|
||||
|
||||
const hasQuantity = equipmentData.hasQuantity === true ||
|
||||
equipmentData.category === "CABLE" ||
|
||||
equipmentData.category === "CONSUMABLE";
|
||||
|
||||
const eqRef = db.collection("equipments").doc(eqId);
|
||||
if (!hasQuantity) {
|
||||
// Non-consumable: reset to AVAILABLE
|
||||
transaction.update(eqRef, {
|
||||
status: "AVAILABLE",
|
||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||
});
|
||||
logger.info(`[onEventReturnCompleted] Set status to AVAILABLE for equipment ${eqId}`);
|
||||
} else if (hasQuantity && eq.quantityAtReturn !== undefined && eq.quantityAtReturn !== null) {
|
||||
// Consumable: increment availableQuantity
|
||||
const currentAvailable = Number(equipmentData.availableQuantity) || 0;
|
||||
const returnedQty = Number(eq.quantityAtReturn) || 0;
|
||||
transaction.update(eqRef, {
|
||||
availableQuantity: currentAvailable + returnedQty,
|
||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||
});
|
||||
logger.info(`[onEventReturnCompleted] Restored ${returnedQty} items for consumable ${eqId} (new available: ${currentAvailable + returnedQty})`);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark event as stocksRestored
|
||||
transaction.update(eventRef, {
|
||||
stocksRestored: true,
|
||||
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
||||
});
|
||||
});
|
||||
logger.info(`[onEventReturnCompleted] Transaction completed successfully for event ${eventId}`);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[onEventReturnCompleted] Error resetting equipment statuses for event ${eventId}:`, error);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user