diff --git a/src/lib/hierarchy-operations/backend.js b/src/lib/hierarchy-operations/backend.js index 5a27882c..30990d8b 100644 --- a/src/lib/hierarchy-operations/backend.js +++ b/src/lib/hierarchy-operations/backend.js @@ -53,7 +53,7 @@ async function descendantsOf(db, contactId) { } async function reportsCreatedByOrAt(db, createdByIds, createdAtId, skip) { - const createdByKeys = createdByIds.map(descendantId => [`contact:${descendantId}`]); + const createdByKeys = createdByIds.map(id => [`contact:${id}`]); const createdAtKeys = createdAtId ? [ [`patient_id:${createdAtId}`], [`patient_uuid:${createdAtId}`], diff --git a/src/lib/hierarchy-operations/index.js b/src/lib/hierarchy-operations/index.js index 62014d15..e4d4fc4d 100644 --- a/src/lib/hierarchy-operations/index.js +++ b/src/lib/hierarchy-operations/index.js @@ -6,7 +6,7 @@ const JsDocs = require('./jsdocFolder'); const Backend = require('./backend'); const HierarchyOperations = (options) => { - const move = async (sourceIds, destinationId, db) => { + async function move(sourceIds, destinationId, db) { JsDocs.prepareFolder(options); trace(`Fetching contact details: ${destinationId}`); const constraints = await LineageConstraints(db, options); @@ -55,10 +55,9 @@ const HierarchyOperations = (options) => { } info(`Staged changes to lineage information for ${affectedContactCount} contact(s) and ${affectedReportCount} report(s).`); - }; + } - - const moveReports = async (db, descendantsAndSelf, replacementLineage, sourceId, destinationId) => { + async function moveReports(db, descendantsAndSelf, replacementLineage, sourceId, destinationId) { const descendantIds = descendantsAndSelf.map(contact => contact._id); let skip = 0; @@ -71,28 +70,7 @@ const HierarchyOperations = (options) => { const updatedReports = replaceLineageInReports(reportDocsBatch, replacementLineage, sourceId); if (options.merge) { - reportDocsBatch.forEach(report => { - let updated = false; - const subjectIds = ['patient_id', 'patient_uuid', 'place_id', 'place_uuid']; - for (const subjectId of subjectIds) { - if (report[subjectId] === sourceId) { - report[subjectId] = destinationId; - updated = true; - } - - if (report.fields[subjectId] === sourceId) { - report.fields[subjectId] = destinationId; - updated = true; - } - - if (updated) { - const isAlreadyUpdated = !!updatedReports.find(updated => updated._id === report._id); - if (!isAlreadyUpdated) { - updatedReports.push(report); - } - } - } - }); + reassignReports(reportDocsBatch, sourceId, destinationId, updatedReports); } minifyLineageAndWriteToDisk(updatedReports); @@ -101,51 +79,82 @@ const HierarchyOperations = (options) => { } while (reportDocsBatch.length >= Backend.BATCH_SIZE); return skip; - }; + } + + function reassignReports(reports, sourceId, destinationId, updatedReports) { + reports.forEach(report => { + let updated = false; + const subjectIds = ['patient_id', 'patient_uuid', 'place_id', 'place_uuid']; + for (const subjectId of subjectIds) { + if (report[subjectId] === sourceId) { + report[subjectId] = destinationId; + updated = true; + } + + if (report.fields[subjectId] === sourceId) { + report.fields[subjectId] = destinationId; + updated = true; + } + + if (updated) { + const isAlreadyUpdated = !!updatedReports.find(updated => updated._id === report._id); + if (!isAlreadyUpdated) { + updatedReports.push(report); + } + } + } + }); + } - const minifyLineageAndWriteToDisk = (docs) => { + function minifyLineageAndWriteToDisk(docs) { docs.forEach(doc => { lineageManipulation.minifyLineagesInDoc(doc); JsDocs.writeDoc(options, doc); }); - }; - - const replaceLineageInReports = (reportsCreatedByDescendants, replaceWith, startingFromIdInLineage) => reportsCreatedByDescendants.reduce((agg, doc) => { - if (lineageManipulation.replaceLineage(doc, 'contact', replaceWith, startingFromIdInLineage, options)) { - agg.push(doc); - } - return agg; - }, []); - - const replaceLineageInAncestors = (descendantsAndSelf, ancestors) => ancestors.reduce((agg, ancestor) => { - let result = agg; - const primaryContact = descendantsAndSelf.find(descendant => ancestor.contact && descendant._id === ancestor.contact._id); - if (primaryContact) { - ancestor.contact = lineageManipulation.createLineageFromDoc(primaryContact); - result = [ancestor, ...result]; - } - - return result; - }, []); + } - const replaceLineageInContacts = (descendantsAndSelf, replacementLineage, destinationId) => descendantsAndSelf.reduce((agg, doc) => { - const startingFromIdInLineage = options.merge ? destinationId : - doc._id === destinationId ? undefined : destinationId; + function replaceLineageInReports(reportsCreatedByDescendants, replaceWith, startingFromIdInLineage) { + return reportsCreatedByDescendants.reduce((agg, doc) => { + if (lineageManipulation.replaceLineage(doc, 'contact', replaceWith, startingFromIdInLineage, options)) { + agg.push(doc); + } + return agg; + }, []); + } + + function replaceLineageInAncestors(descendantsAndSelf, ancestors) { + return ancestors.reduce((agg, ancestor) => { + let result = agg; + const primaryContact = descendantsAndSelf.find(descendant => ancestor.contact && descendant._id === ancestor.contact._id); + if (primaryContact) { + ancestor.contact = lineageManipulation.createLineageFromDoc(primaryContact); + result = [ancestor, ...result]; + } - // skip top-level because it will be deleted - if (options.merge) { - if (doc._id === destinationId) { - return agg; + return result; + }, []); + } + + function replaceLineageInContacts(descendantsAndSelf, replacementLineage, destinationId) { + return descendantsAndSelf.reduce((agg, doc) => { + const startingFromIdInLineage = options.merge ? destinationId : + doc._id === destinationId ? undefined : destinationId; + + // skip top-level because it will be deleted + if (options.merge) { + if (doc._id === destinationId) { + return agg; + } } - } - const parentWasUpdated = lineageManipulation.replaceLineage(doc, 'parent', replacementLineage, startingFromIdInLineage, options); - const contactWasUpdated = lineageManipulation.replaceLineage(doc, 'contact', replacementLineage, destinationId, options); - if (parentWasUpdated || contactWasUpdated) { - agg.push(doc); - } - return agg; - }, []); + const parentWasUpdated = lineageManipulation.replaceLineage(doc, 'parent', replacementLineage, startingFromIdInLineage, options); + const contactWasUpdated = lineageManipulation.replaceLineage(doc, 'contact', replacementLineage, destinationId, options); + if (parentWasUpdated || contactWasUpdated) { + agg.push(doc); + } + return agg; + }, []); + } return { move }; }; @@ -155,3 +164,4 @@ module.exports = options => ({ move: HierarchyOperations({ ...options, merge: false }).move, merge: HierarchyOperations({ ...options, merge: true }).move, }); + diff --git a/test/mock-hierarchies.spec.js b/test/mock-hierarchies.spec.js index c8a21933..3177a717 100644 --- a/test/mock-hierarchies.spec.js +++ b/test/mock-hierarchies.spec.js @@ -84,6 +84,7 @@ describe('mocks', () => { _id: 'report_1', type: 'data_record', form: 'foo', + fields: {}, contact: { _id: 'health_center_1_contact', parent: {