cht-conf 6.1.0 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/lib/api.js +15 -12
- package/src/lib/compilation/validate-declarative-schema.js +1 -0
- package/src/lib/hierarchy-operations/delete-hierarchy.js +1 -1
- package/src/lib/hierarchy-operations/hierarchy-data-source.js +32 -20
- package/src/lib/hierarchy-operations/index.js +29 -14
- package/src/lib/parse-targets.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [6.2.0](https://github.com/medic/cht-conf/compare/v6.1.1...v6.2.0) (2026-04-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **#10240:** allow limit_count_to_goal in target configuration schema ([#800](https://github.com/medic/cht-conf/issues/800)) ([7c6ec4f](https://github.com/medic/cht-conf/commit/7c6ec4fffb1a4721b309e7510b86e8ac9a7e745d)), closes [#10240](https://github.com/medic/cht-conf/issues/10240) [medic/cht-core#10772](https://github.com/medic/cht-core/issues/10772)
|
|
7
|
+
|
|
8
|
+
## [6.1.1](https://github.com/medic/cht-conf/compare/v6.1.0...v6.1.1) (2026-04-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **#799:** batch contact IDs in move-contacts to avoid URI length errors ([#802](https://github.com/medic/cht-conf/issues/802)) ([08e92a5](https://github.com/medic/cht-conf/commit/08e92a568196bdcb3e68076a760fbd8a5b7ff461)), closes [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799) [#799](https://github.com/medic/cht-conf/issues/799)
|
|
14
|
+
|
|
1
15
|
# [6.1.0](https://github.com/medic/cht-conf/compare/v6.0.2...v6.1.0) (2026-04-02)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/lib/api.js
CHANGED
|
@@ -256,20 +256,23 @@ const api = {
|
|
|
256
256
|
}
|
|
257
257
|
},
|
|
258
258
|
|
|
259
|
-
async
|
|
259
|
+
async getReportsByFreetext (createdByIds, limit, bookmark) {
|
|
260
260
|
const queryString = createdByIds.map(id => `exact_match:"contact:${id}"`).join(' OR ');
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
261
|
+
const body = {
|
|
262
|
+
// sorting by this field ensures that the output are same with the clouseau views
|
|
263
|
+
// https://github.com/medic/cht-core/pull/9541
|
|
264
|
+
sort: 'reported_date',
|
|
265
|
+
q: queryString,
|
|
266
|
+
include_docs: true,
|
|
267
|
+
limit,
|
|
268
|
+
};
|
|
269
|
+
if (bookmark) {
|
|
270
|
+
body.bookmark = bookmark;
|
|
271
|
+
}
|
|
272
|
+
const res = await request.post(`${environment.apiUrl}/_design/medic/_nouveau/reports_by_freetext`, {
|
|
273
|
+
body, json: true
|
|
271
274
|
});
|
|
272
|
-
return res.hits.map(item => item.doc);
|
|
275
|
+
return { docs: res.hits.map(item => item.doc), bookmark: res.bookmark };
|
|
273
276
|
}
|
|
274
277
|
};
|
|
275
278
|
|
|
@@ -82,6 +82,7 @@ const TargetSchema = joi.array().items(
|
|
|
82
82
|
.optional()
|
|
83
83
|
.error(targetError('idType should be either "report" or "contact" or "function(contact, report)"')),
|
|
84
84
|
aggregate: joi.boolean().optional(),
|
|
85
|
+
limit_count_to_goal: joi.boolean().optional(),
|
|
85
86
|
})
|
|
86
87
|
)
|
|
87
88
|
.unique('id')
|
|
@@ -34,7 +34,7 @@ async function deleteReportsForContact(db, options, contact) {
|
|
|
34
34
|
let skip = 0;
|
|
35
35
|
let reportBatch;
|
|
36
36
|
do {
|
|
37
|
-
reportBatch = await DataSource.
|
|
37
|
+
reportBatch = await DataSource.fetchReportsBySubject(db, [contact._id], skip);
|
|
38
38
|
|
|
39
39
|
for (const report of reportBatch) {
|
|
40
40
|
JsDocs.deleteDoc(options, report);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const lineageManipulation = require('./lineage-manipulation');
|
|
2
|
-
const {getValidApiVersion} = require('../get-api-version');
|
|
2
|
+
const { getValidApiVersion } = require('../get-api-version');
|
|
3
3
|
const semver = require('semver');
|
|
4
4
|
const api = require('../api');
|
|
5
5
|
|
|
6
6
|
const HIERARCHY_ROOT = 'root';
|
|
7
7
|
const BATCH_SIZE = 10000;
|
|
8
|
+
const QUERY_IDS_BATCH_SIZE = 100;
|
|
8
9
|
const NOUVEAU_MIN_VERSION = '5.0.0';
|
|
9
10
|
const SUBJECT_IDS = ['patient_id', 'patient_uuid', 'place_id', 'place_uuid'];
|
|
10
11
|
|
|
@@ -71,18 +72,39 @@ const getFromDbView = async (db, view, keys, skip) => {
|
|
|
71
72
|
return res.rows.map(row => row.doc);
|
|
72
73
|
};
|
|
73
74
|
|
|
74
|
-
const
|
|
75
|
+
const useNouveauSearch = async () => {
|
|
76
|
+
const coreVersion = await getValidApiVersion();
|
|
77
|
+
return coreVersion && semver.gte(coreVersion, NOUVEAU_MIN_VERSION);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const fetchReportsByCreator = async (db, createdByIds, cursor, useNouveau) => {
|
|
75
81
|
if (createdByIds.length === 0) {
|
|
76
|
-
return [];
|
|
82
|
+
return { docs: [], cursor: null };
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return await api().getReportsByCreatedByIds(createdByIds, BATCH_SIZE, skip);
|
|
85
|
+
if (useNouveau) {
|
|
86
|
+
return await fetchAllReportsFromNouveau(createdByIds);
|
|
82
87
|
}
|
|
83
88
|
|
|
89
|
+
const skip = cursor || 0;
|
|
84
90
|
const createdByKeys = createdByIds.map(id => [`contact:${id}`]);
|
|
85
|
-
|
|
91
|
+
const docs = await getFromDbView(db, 'medic-client/reports_by_freetext', createdByKeys, skip);
|
|
92
|
+
return { docs, cursor: skip + docs.length };
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const fetchAllReportsFromNouveau = async (createdByIds) => {
|
|
96
|
+
const allDocs = [];
|
|
97
|
+
for (let i = 0; i < createdByIds.length; i += QUERY_IDS_BATCH_SIZE) {
|
|
98
|
+
const idsBatch = createdByIds.slice(i, i + QUERY_IDS_BATCH_SIZE);
|
|
99
|
+
let bookmark = null;
|
|
100
|
+
let batch;
|
|
101
|
+
do {
|
|
102
|
+
batch = await api().getReportsByFreetext(idsBatch, BATCH_SIZE, bookmark);
|
|
103
|
+
allDocs.push(...batch.docs);
|
|
104
|
+
bookmark = batch.bookmark;
|
|
105
|
+
} while (batch.docs.length >= BATCH_SIZE);
|
|
106
|
+
}
|
|
107
|
+
return { docs: allDocs, cursor: null };
|
|
86
108
|
};
|
|
87
109
|
|
|
88
110
|
const fetchReportsBySubject = async (db, createdAtIds, skip) => {
|
|
@@ -92,18 +114,6 @@ const fetchReportsBySubject = async (db, createdAtIds, skip) => {
|
|
|
92
114
|
return await getFromDbView(db, 'medic-client/reports_by_subject', createdAtIds, skip);
|
|
93
115
|
};
|
|
94
116
|
|
|
95
|
-
const getReportsForContacts = async (db, createdByIds, createdAtIds, skip) => {
|
|
96
|
-
const [creatorReports, subjectReports] = await Promise.all([
|
|
97
|
-
fetchReportsByCreator(db, createdByIds, skip),
|
|
98
|
-
fetchReportsBySubject(db, createdAtIds, skip)
|
|
99
|
-
]);
|
|
100
|
-
|
|
101
|
-
const allRows = [...creatorReports, ...subjectReports];
|
|
102
|
-
|
|
103
|
-
const docsWithId = allRows.map(( doc ) => [doc._id, doc]);
|
|
104
|
-
return Array.from(new Map(docsWithId).values());
|
|
105
|
-
};
|
|
106
|
-
|
|
107
117
|
async function getAncestorsOf(db, contactDoc) {
|
|
108
118
|
const ancestorIds = lineageManipulation.pluckIdsFromLineage(contactDoc.parent);
|
|
109
119
|
const ancestors = await db.allDocs({
|
|
@@ -130,5 +140,7 @@ module.exports = {
|
|
|
130
140
|
getContactWithDescendants,
|
|
131
141
|
getContact,
|
|
132
142
|
getContactsByIds,
|
|
133
|
-
|
|
143
|
+
useNouveauSearch,
|
|
144
|
+
fetchReportsByCreator,
|
|
145
|
+
fetchReportsBySubject,
|
|
134
146
|
};
|
|
@@ -74,24 +74,39 @@ function getPrimaryContactId(doc) {
|
|
|
74
74
|
|
|
75
75
|
async function updateReports(db, options, moveContext) {
|
|
76
76
|
const descendantIds = moveContext.descendantsAndSelf.map(contact => contact._id);
|
|
77
|
+
const createdAtIds = getReportsCreatedAtIds(moveContext);
|
|
77
78
|
|
|
78
|
-
let
|
|
79
|
-
|
|
80
|
-
do {
|
|
81
|
-
info(`Processing ${skip} to ${skip + DataSource.BATCH_SIZE} report docs`);
|
|
82
|
-
const createdAtIds = getReportsCreatedAtIds(moveContext);
|
|
83
|
-
reportDocsBatch = await DataSource.getReportsForContacts(db, descendantIds, createdAtIds, skip);
|
|
79
|
+
let totalCount = 0;
|
|
80
|
+
const useNouveau = await DataSource.useNouveauSearch();
|
|
84
81
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
let cursor = null;
|
|
83
|
+
let result;
|
|
84
|
+
do {
|
|
85
|
+
info(`Processing creator reports ${totalCount} to ${totalCount + DataSource.BATCH_SIZE}`);
|
|
86
|
+
result = await DataSource.fetchReportsByCreator(db, descendantIds, cursor, useNouveau);
|
|
87
|
+
processAndWriteReportBatch(result.docs, options, moveContext);
|
|
88
|
+
cursor = result.cursor;
|
|
89
|
+
totalCount += result.docs.length;
|
|
90
|
+
} while (result.cursor && result.docs.length >= DataSource.BATCH_SIZE);
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
let skip = 0;
|
|
93
|
+
let batch;
|
|
94
|
+
do {
|
|
95
|
+
info(`Processing subject reports ${skip} to ${skip + DataSource.BATCH_SIZE}`);
|
|
96
|
+
batch = await DataSource.fetchReportsBySubject(db, createdAtIds, skip);
|
|
97
|
+
processAndWriteReportBatch(batch, options, moveContext);
|
|
98
|
+
skip += batch.length;
|
|
99
|
+
totalCount += batch.length;
|
|
100
|
+
} while (batch.length >= DataSource.BATCH_SIZE);
|
|
101
|
+
|
|
102
|
+
return totalCount;
|
|
103
|
+
}
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
function processAndWriteReportBatch(batch, options, moveContext) {
|
|
106
|
+
const lineageUpdates = replaceLineageOfReportCreator(batch, moveContext);
|
|
107
|
+
const reassignUpdates = reassignReports(batch, moveContext);
|
|
108
|
+
const updatedReports = batch.filter(doc => lineageUpdates.has(doc._id) || reassignUpdates.has(doc._id));
|
|
109
|
+
minifyLineageAndWriteToDisk(options, updatedReports);
|
|
95
110
|
}
|
|
96
111
|
|
|
97
112
|
function getReportsCreatedAtIds(moveContext) {
|