On the following snippet inside the forEach loop, I'm executing a function called
saveCandidatesData({ screeningNumbers, pruneScreeningNumbers: prune })
The function generally is about saving some data in batches not to overload the request.
My issue is that the function saveCandidatesData need to be executed for every batch but the part called pruneScreeningNumbers needs to be executed only on the first batch iteration.
For example
If you have 3 batches then request saveCandidatesData should be executed 3 times.
screeningNumbers - data for batch 1 + pruneScreeningNumbers
screeningNumbers - data for batch 2 (no prune)
screeningNumbers - data for batch 3 (no prune)
I don't know how to implement this in the following code
const screeningNumbersCalculations = async (data, batches) => {
console.log('batches: ', batches);
const results = {};
const mappedDateId = dateIdMap(data);
batches.map(b => {
b.forEach(t => {
const matchingStatusesTime = Object.values(mappedDateId).filter(s => {
return new Date(s.statusFrom) < endOfDay(t) && (s.statusTo === null || new Date(t) <= new Date(s.statusTo));
});
matchingStatusesTime.forEach(ms => {
const label = assignLabel(ms.statusType, ms.eligible);
const key = `${t}${ms.studyId}${ms.siteId}${label}`;
if (!results[key]) {
results[key] = {
days: [t],
studyId: ms.studyId,
siteId: ms.siteId,
screeningStage: 'SELF_ASSESSMENT',
label,
total: 0,
};
}
results[key].total += 1;
});
const screeningNumbers = Object.values(results);
const cnt = saveCandidatesData({ screeningNumbers, pruneScreeningNumbers: prune });
log.info('Replay screening numbers completed in %d', cnt);
});
return Promise.resolve();
});
};
Right now the prune is executed every time and I need to change that to be only on the first batch iteration.
I have no clue how to fix that
This is a working snippet of a simplified version of the above snippet but without the function at the moment. However, you can have an idea on how it works
const mockData = [{
id: "C10-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "INCOMPLETE",
statusFrom: "2020-12-05T01:00:00.000Z",
statusTo: "2020-12-05T02:00:00.000Z"
},
{
id: "C10-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "DROPOUT_PRESCREENER",
eligible: true,
statusFrom: "2020-12-05T02:00:00.000Z",
statusTo: "2020-12-05T03:00:00.000Z"
},
{
id: "C10-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "INCOMPLETE",
statusFrom: "2020-12-05T03:00:00.000Z",
statusTo: null
}
];
function endOfDay(time) {
const date = new Date(time);
date.setUTCHours(23, 59, 59, 999);
return date;
}
const assignLabel = (statusType, eligible) => {
if (statusType === "INCOMPLETE") return "pending";
if (statusType === "REJECTED_PRESCREENER") return "ineligible";
if (statusType === "DROPOUT_PRESCREENER" && eligible) return "eligible";
if (statusType === "DROPOUT_PRESCREENER" && !eligible) return "abandoned";
return "completed";
};
// This dates are generated from a fuction bases on which dates range we need
// In this cas is just one day
const batches = ["2020-12-05T00:00:00.000Z"];
const screeningNumbersCalculations = () => {
const results = {}; // Dont use array since you are using it as dictionary Object.
// Putting latest records at end so we can confidently overwrite with records of same day in next step
mockData.sort((a, b) => endOfDay(a).getTime() - endOfDay(b).getTime());
const dateidMap = mockData.reduce((accum, item) => {
accum[`${endOfDay(item).getTime()}.${item.id}`] = item;
return accum;
}, {});
console.log(dateidMap)
batches.forEach((t) => {
// or filter matching times first and generate dateidMap later.
const matchingStatusesTime = Object.values(dateidMap).filter((s) => {
return (
new Date(s.statusFrom) < endOfDay(t) &&
(s.statusTo === null || new Date(t) <= new Date(s.statusTo))
);
});
matchingStatusesTime.forEach((ms) => {
const key = `${t}${ms.studyId}${ms.siteId}${assignLabel(
ms.statusType,
ms.eligible
)}`;
if (!results[key]) {
results[key] = {
days: [t],
studyId: ms.studyId,
siteId: ms.siteId,
screeningStage: "SELF_ASSESSMENT",
label: assignLabel(ms.statusType, ms.eligible),
total: 0
};
}
results[key].total++;
});
});
return Object.values(results);
};
const screeningNumbers = screeningNumbersCalculations();
console.log(JSON.stringify(screeningNumbers, null, 2));