I want to create a function where it generate report every 2 hours. For now the schedule I fixed it for testing purposes. I am currently facing the problem of getting all of the data of transactions from shops in order to calculate and generate a record in reports collection. The below code return error message of TypeError: Cannot read property 'map' of undefined.
exports.generateReport = functions.pubsub.schedule('25 14 * * *').onRun(async (context) => {
const shopSnapshot = await db.collection("shops").get();
const shopDoc = shopSnapshot.docs.map(doc => doc.data());
console.log(shopDoc);
for(var i=0; i<shopDoc.length; i++){
console.log(shopDoc[i].id);
if(shopDoc[i].id !== "" || shopDoc[i].id !== null){
console.log("Enter if:"+shopDoc[i].id);
let transactionSnapshot = db.collection("shops").doc(shopDoc[i].id).collection("transactions").get();
let transactionDoc = transactionSnapshot.docs.map(document => document.data());
console.log(transactionDoc);
}
}

You should use Promise.all() to wait that all the asynchronous get() operations are completed before you proceed.
You could do as follows:
exports.generateReport = functions.pubsub.schedule('25 14 * * *').onRun(async (context) => {
const shopSnapshot = await db.collection("shops").get();
const shopDoc = shopSnapshot.docs.map(doc => doc.data());
console.log(shopDoc);
const promises = [];
for(var i=0; i<shopDoc.length; i++){
console.log(shopDoc[i].id);
if(shopDoc[i].id !== "" || shopDoc[i].id !== null){
promises.push(db.collection("shops").doc(shopDoc[i].id).collection("transactions").get());
}
}
const snapshotArrays = await Promise.all(promises);
// snapshotArrays contains an array of arrays of QueryDocumentSnapshots
snapshotArrays.forEach(snapArray => {
snapArray.forEach(snap => {
// Proceed here with the snap (DocumentSnapshot)
//E.g. sum up the amount or points values
}))
})
});
//Or call map on snapshotArrays.docs
// ....
return null; // or return the promise returned by an asynchronous method
Note that you may need to do this calculation in a Transaction, within your Cloud Function, to avoid a new transaction document is added while you are calculating.
The Admin SDK for Node.js includes the getAll() method, which "retrieves multiple documents from Firestore and holds a pessimistic lock on all returned documents."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With