fhirsmith 0.7.6 → 0.8.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 +26 -0
- package/library/languages.js +10 -0
- package/package.json +1 -1
- package/packages/package-crawler.js +2 -2
- package/publisher/publisher.js +1 -1
- package/registry/registry.js +2 -2
- package/root-bare-template.html +1 -2
- package/server.js +100 -70
- package/stats.js +37 -6
- package/tx/cs/cs-loinc.js +14 -2
- package/tx/cs/cs-rxnorm.js +14 -10
- package/tx/cs/cs-snomed.js +166 -5
- package/tx/html/dash-metrics.liquid +147 -0
- package/tx/importers/import-rxnorm.module.js +4 -30
- package/tx/library/canonical-resource.js +8 -0
- package/tx/library/conceptmap.js +3 -1
- package/tx/library/designations.js +4 -8
- package/tx/library/renderer.js +9 -9
- package/tx/ocl/cm-ocl.cjs +185 -65
- package/tx/ocl/cs-ocl.cjs +69 -50
- package/tx/ocl/jobs/background-queue.cjs +0 -8
- package/tx/ocl/mappers/concept-mapper.cjs +13 -3
- package/tx/ocl/shared/patches.cjs +1 -0
- package/tx/ocl/vs-ocl.cjs +137 -157
- package/tx/operation-context.js +3 -3
- package/tx/provider.js +2 -2
- package/tx/sct/structures.js +5 -0
- package/tx/tx.fhir.org.yml +1 -1
- package/tx/vs/vs-database.js +107 -23
- package/tx/vs/vs-vsac.js +66 -19
- package/tx/workers/search.js +2 -1
- package/tx/workers/translate.js +39 -14
- package/tx/workers/validate.js +3 -3
- package/xig/xig.js +171 -9
package/tx/vs/vs-database.js
CHANGED
|
@@ -33,12 +33,31 @@ class ValueSetDatabase {
|
|
|
33
33
|
db.all("PRAGMA table_info(valuesets)", [], (err, cols) => {
|
|
34
34
|
if (err) { reject(err); return; }
|
|
35
35
|
const hasCol = cols.some(c => c.name === 'date_first_seen');
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
const migrations = [];
|
|
37
|
+
if (!hasCol) {
|
|
38
|
+
migrations.push(new Promise((res, rej) => {
|
|
39
|
+
db.run(
|
|
40
|
+
"ALTER TABLE valuesets ADD COLUMN date_first_seen INTEGER DEFAULT 0",
|
|
41
|
+
[],
|
|
42
|
+
(err) => err ? rej(err) : res()
|
|
43
|
+
);
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
// Ensure vsac_runs table exists
|
|
47
|
+
migrations.push(new Promise((res, rej) => {
|
|
48
|
+
db.run(`
|
|
49
|
+
CREATE TABLE IF NOT EXISTS vsac_runs (
|
|
50
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
51
|
+
started_at INTEGER NOT NULL,
|
|
52
|
+
finished_at INTEGER,
|
|
53
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
54
|
+
error_message TEXT,
|
|
55
|
+
total_fetched INTEGER,
|
|
56
|
+
total_new INTEGER
|
|
57
|
+
)
|
|
58
|
+
`, [], (err) => err ? rej(err) : res());
|
|
59
|
+
}));
|
|
60
|
+
Promise.all(migrations).then(() => resolve()).catch(reject);
|
|
42
61
|
});
|
|
43
62
|
});
|
|
44
63
|
}
|
|
@@ -204,6 +223,19 @@ class ValueSetDatabase {
|
|
|
204
223
|
)
|
|
205
224
|
`);
|
|
206
225
|
|
|
226
|
+
// Run tracking table
|
|
227
|
+
db.run(`
|
|
228
|
+
CREATE TABLE vsac_runs (
|
|
229
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
230
|
+
started_at INTEGER NOT NULL,
|
|
231
|
+
finished_at INTEGER,
|
|
232
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
233
|
+
error_message TEXT,
|
|
234
|
+
total_fetched INTEGER,
|
|
235
|
+
total_new INTEGER
|
|
236
|
+
)
|
|
237
|
+
`);
|
|
238
|
+
|
|
207
239
|
// Create indexes for better search performance
|
|
208
240
|
db.run('CREATE INDEX idx_valuesets_url ON valuesets(url, version)');
|
|
209
241
|
db.run('CREATE INDEX idx_valuesets_version ON valuesets(version)');
|
|
@@ -231,6 +263,58 @@ class ValueSetDatabase {
|
|
|
231
263
|
});
|
|
232
264
|
}
|
|
233
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Record the start of a VSAC sync run
|
|
268
|
+
* @returns {Promise<number>} The run ID
|
|
269
|
+
*/
|
|
270
|
+
async startRun() {
|
|
271
|
+
const db = await this._getWriteConnection();
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
db.run(
|
|
274
|
+
`INSERT INTO vsac_runs (started_at, status) VALUES (strftime('%s','now'), 'running')`,
|
|
275
|
+
[],
|
|
276
|
+
function(err) { err ? reject(err) : resolve(this.lastID); }
|
|
277
|
+
);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Record the successful completion of a VSAC sync run
|
|
283
|
+
* @param {number} id - The run ID from startRun()
|
|
284
|
+
* @param {number} totalFetched - Total value sets fetched
|
|
285
|
+
* @param {number} totalNew - Number of new value sets found
|
|
286
|
+
* @returns {Promise<void>}
|
|
287
|
+
*/
|
|
288
|
+
async finishRun(id, totalFetched, totalNew) {
|
|
289
|
+
const db = await this._getWriteConnection();
|
|
290
|
+
return new Promise((resolve, reject) => {
|
|
291
|
+
db.run(
|
|
292
|
+
`UPDATE vsac_runs SET finished_at = strftime('%s','now'), status = 'ok',
|
|
293
|
+
total_fetched = ?, total_new = ? WHERE id = ?`,
|
|
294
|
+
[totalFetched, totalNew, id],
|
|
295
|
+
err => err ? reject(err) : resolve()
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Record a failed VSAC sync run
|
|
302
|
+
* @param {number} id - The run ID from startRun()
|
|
303
|
+
* @param {string} errorMessage - The error message
|
|
304
|
+
* @returns {Promise<void>}
|
|
305
|
+
*/
|
|
306
|
+
async failRun(id, errorMessage) {
|
|
307
|
+
const db = await this._getWriteConnection();
|
|
308
|
+
return new Promise((resolve, reject) => {
|
|
309
|
+
db.run(
|
|
310
|
+
`UPDATE vsac_runs SET finished_at = strftime('%s','now'), status = 'error',
|
|
311
|
+
error_message = ? WHERE id = ?`,
|
|
312
|
+
[errorMessage, id],
|
|
313
|
+
err => err ? reject(err) : resolve()
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
234
318
|
/**
|
|
235
319
|
* Insert or update a single ValueSet in the database
|
|
236
320
|
* @param {Object} valueSet - The ValueSet resource
|
|
@@ -270,23 +354,23 @@ class ValueSetDatabase {
|
|
|
270
354
|
|
|
271
355
|
db.run(`
|
|
272
356
|
INSERT INTO valuesets (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
357
|
+
id, url, version, date, description, effectivePeriod_start, effectivePeriod_end,
|
|
358
|
+
expansion_identifier, name, publisher, status, title, content, last_seen, date_first_seen
|
|
359
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s', 'now'), strftime('%s', 'now'))
|
|
360
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
361
|
+
url=excluded.url,
|
|
362
|
+
version=excluded.version,
|
|
363
|
+
date=excluded.date,
|
|
364
|
+
description=excluded.description,
|
|
365
|
+
effectivePeriod_start=excluded.effectivePeriod_start,
|
|
366
|
+
effectivePeriod_end=excluded.effectivePeriod_end,
|
|
367
|
+
expansion_identifier=excluded.expansion_identifier,
|
|
368
|
+
name=excluded.name,
|
|
369
|
+
publisher=excluded.publisher,
|
|
370
|
+
status=excluded.status,
|
|
371
|
+
title=excluded.title,
|
|
372
|
+
content=excluded.content,
|
|
373
|
+
last_seen=strftime('%s', 'now')
|
|
290
374
|
`, [
|
|
291
375
|
valueSet.id,
|
|
292
376
|
valueSet.url,
|
package/tx/vs/vs-vsac.js
CHANGED
|
@@ -98,6 +98,7 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
98
98
|
try {
|
|
99
99
|
await this.refreshValueSets();
|
|
100
100
|
} catch (error) {
|
|
101
|
+
debugLog(error);
|
|
101
102
|
this.log.error(error, 'Error during scheduled refresh:');
|
|
102
103
|
}
|
|
103
104
|
}, intervalMs);
|
|
@@ -126,6 +127,7 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
126
127
|
this.queue = [];
|
|
127
128
|
|
|
128
129
|
this.isRefreshing = true;
|
|
130
|
+
const runId = await this.database.startRun();
|
|
129
131
|
|
|
130
132
|
try {
|
|
131
133
|
// phase 1: list all value sets
|
|
@@ -202,10 +204,15 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
202
204
|
|
|
203
205
|
// Reload map with fresh data
|
|
204
206
|
await this._reloadMap();
|
|
205
|
-
|
|
207
|
+
let msg = `VSAC refresh completed. Total: ${tracking.totalFetched} ValueSets, Deleted: ${tracking.deletedCount}`;
|
|
208
|
+
this.stats.taskDone('VSAC Sync', msg);
|
|
209
|
+
console.log(msg);
|
|
210
|
+
|
|
211
|
+
await this.database.finishRun(runId, tracking.totalFetched, tracking.totalNew);
|
|
206
212
|
} catch (error) {
|
|
207
213
|
debugLog(error, 'Error during VSAC refresh:');
|
|
208
|
-
this.stats.
|
|
214
|
+
this.stats.taskError('VSAC Sync', `Error (${error.message})`);
|
|
215
|
+
await this.database.failRun(runId, error.message);
|
|
209
216
|
throw error;
|
|
210
217
|
} finally {
|
|
211
218
|
this.isRefreshing = false;
|
|
@@ -265,7 +272,6 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
265
272
|
}
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
|
|
269
275
|
/**
|
|
270
276
|
* Fetch a FHIR Bundle from the server
|
|
271
277
|
* @param {string} url - Relative URL to fetch
|
|
@@ -511,7 +517,6 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
511
517
|
let logMsg = `VSAC (${tracking.count} of ${length}) ${q}: ${vcount} versions`;
|
|
512
518
|
console.log(logMsg);
|
|
513
519
|
this.stats.task('VSAC Sync', logMsg);
|
|
514
|
-
|
|
515
520
|
}
|
|
516
521
|
|
|
517
522
|
name() {
|
|
@@ -523,35 +528,77 @@ class VSACValueSetProvider extends AbstractValueSetProvider {
|
|
|
523
528
|
}
|
|
524
529
|
|
|
525
530
|
async info() {
|
|
531
|
+
const escape = require('escape-html');
|
|
526
532
|
const db = await this.database._getReadConnection();
|
|
533
|
+
|
|
527
534
|
const rows = await new Promise((resolve, reject) => {
|
|
528
535
|
db.all(
|
|
529
|
-
`SELECT
|
|
536
|
+
`SELECT 'vs' AS kind,
|
|
537
|
+
url,
|
|
538
|
+
version,
|
|
539
|
+
date_first_seen AS ts,
|
|
540
|
+
NULL AS status,
|
|
541
|
+
NULL AS error_message,
|
|
542
|
+
NULL AS finished_at,
|
|
543
|
+
NULL AS total_fetched,
|
|
544
|
+
NULL AS total_new
|
|
530
545
|
FROM valuesets
|
|
531
546
|
WHERE date_first_seen > 0
|
|
532
|
-
|
|
533
|
-
|
|
547
|
+
UNION ALL
|
|
548
|
+
SELECT 'run' AS kind,
|
|
549
|
+
NULL,
|
|
550
|
+
NULL,
|
|
551
|
+
started_at AS ts,
|
|
552
|
+
status,
|
|
553
|
+
error_message,
|
|
554
|
+
finished_at,
|
|
555
|
+
total_fetched,
|
|
556
|
+
total_new
|
|
557
|
+
FROM vsac_runs
|
|
558
|
+
ORDER BY ts DESC
|
|
559
|
+
LIMIT 200`,
|
|
534
560
|
[],
|
|
535
561
|
(err, rows) => err ? reject(err) : resolve(rows)
|
|
536
562
|
);
|
|
537
563
|
});
|
|
538
564
|
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
565
|
+
const fmt = ts => ts
|
|
566
|
+
? new Date(ts * 1000).toISOString().replace('T', ' ').substring(0, 19) + ' UTC'
|
|
567
|
+
: '—';
|
|
568
|
+
|
|
569
|
+
let html = '<h3>VSAC Sync History</h3>';
|
|
542
570
|
html += '<table class="grid">';
|
|
543
|
-
html += '<thead><tr><th>
|
|
571
|
+
html += '<thead><tr><th>Time</th><th>Event</th><th>Detail</th></tr></thead>';
|
|
544
572
|
html += '<tbody>';
|
|
573
|
+
|
|
545
574
|
for (const row of rows) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
575
|
+
if (row.kind === 'run') {
|
|
576
|
+
const duration = row.finished_at ? `${row.finished_at - row.ts}s` : 'in progress';
|
|
577
|
+
let detail, colour;
|
|
578
|
+
if (row.status === 'ok') {
|
|
579
|
+
detail = `${row.total_fetched} fetched, ${row.total_new} new, ${duration}`;
|
|
580
|
+
colour = 'green';
|
|
581
|
+
} else if (row.status === 'error') {
|
|
582
|
+
detail = `Failed: ${escape(row.error_message || '')} (${duration})`;
|
|
583
|
+
colour = 'red';
|
|
584
|
+
} else {
|
|
585
|
+
detail = `Running... (started ${fmt(row.ts)})`;
|
|
586
|
+
colour = 'orange';
|
|
587
|
+
}
|
|
588
|
+
html += `<tr style="background:#f0f0f0">`;
|
|
589
|
+
html += `<td>${escape(fmt(row.ts))}</td>`;
|
|
590
|
+
html += `<td><strong style="color:${colour}">Sync run</strong></td>`;
|
|
591
|
+
html += `<td>${detail}</td>`;
|
|
592
|
+
html += `</tr>`;
|
|
593
|
+
} else {
|
|
594
|
+
html += `<tr>`;
|
|
595
|
+
html += `<td>${escape(fmt(row.ts))}</td>`;
|
|
596
|
+
html += `<td>New value set</td>`;
|
|
597
|
+
html += `<td>${escape(row.url || '')}#${escape(row.version || '')}</td>`;
|
|
598
|
+
html += `</tr>`;
|
|
599
|
+
}
|
|
554
600
|
}
|
|
601
|
+
|
|
555
602
|
html += '</tbody></table>';
|
|
556
603
|
return html;
|
|
557
604
|
}
|
package/tx/workers/search.js
CHANGED
|
@@ -35,7 +35,8 @@ class SearchWorker extends TerminologyWorker {
|
|
|
35
35
|
'_offset', '_count', '_elements', '_sort', '_summary', '_total', '_format',
|
|
36
36
|
'url', 'version', 'content-mode', 'date', 'description',
|
|
37
37
|
'supplements', 'identifier', 'jurisdiction', 'name',
|
|
38
|
-
'publisher', 'status', 'system', 'title', 'text'
|
|
38
|
+
'publisher', 'status', 'system', 'title', 'text',
|
|
39
|
+
'source-system', 'target-system'
|
|
39
40
|
];
|
|
40
41
|
|
|
41
42
|
// Summary elements for _summary=true (marked elements per resource type)
|
package/tx/workers/translate.js
CHANGED
|
@@ -115,8 +115,12 @@ class TranslateWorker extends TerminologyWorker {
|
|
|
115
115
|
let targetSystem = null;
|
|
116
116
|
|
|
117
117
|
// Get the source coding
|
|
118
|
+
// Accept both R5 names (sourceCoding, sourceCodeableConcept, sourceCode/sourceSystem)
|
|
119
|
+
// and R4 names (coding, codeableConcept, code/system) as aliases
|
|
118
120
|
if (params.has('sourceCoding')) {
|
|
119
121
|
coding = params.get('sourceCoding');
|
|
122
|
+
} else if (params.has('coding')) {
|
|
123
|
+
coding = params.get('coding');
|
|
120
124
|
} else if (params.has('sourceCodeableConcept')) {
|
|
121
125
|
const cc = params.get('sourceCodeableConcept');
|
|
122
126
|
if (cc.coding && cc.coding.length > 0) {
|
|
@@ -125,16 +129,23 @@ class TranslateWorker extends TerminologyWorker {
|
|
|
125
129
|
throw new Issue('error', 'invalid', null, null,
|
|
126
130
|
'sourceCodeableConcept must contain at least one coding', null, 400);
|
|
127
131
|
}
|
|
128
|
-
} else if (params.has('
|
|
129
|
-
|
|
132
|
+
} else if (params.has('codeableConcept')) {
|
|
133
|
+
const cc = params.get('codeableConcept');
|
|
134
|
+
if (cc.coding && cc.coding.length > 0) {
|
|
135
|
+
coding = cc.coding[0];
|
|
136
|
+
} else {
|
|
130
137
|
throw new Issue('error', 'invalid', null, null,
|
|
131
|
-
'
|
|
138
|
+
'codeableConcept must contain at least one coding', null, 400);
|
|
132
139
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
140
|
+
} else if (params.has('sourceCode') || params.has('code')) {
|
|
141
|
+
const code = params.has('sourceCode') ? params.get('sourceCode') : params.get('code');
|
|
142
|
+
const system = params.has('sourceSystem') ? params.get('sourceSystem') : params.get('system');
|
|
143
|
+
if (!system) {
|
|
144
|
+
throw new Issue('error', 'invalid', null, null,
|
|
145
|
+
'system parameter is required when using code/sourceCode', null, 400);
|
|
146
|
+
}
|
|
147
|
+
const version = params.has('sourceVersion') ? params.get('sourceVersion') : params.get('version');
|
|
148
|
+
coding = { system, version, code };
|
|
138
149
|
} else {
|
|
139
150
|
throw new Issue('error', 'invalid', null, null,
|
|
140
151
|
'Must provide sourceCode (with system), sourceCoding, or sourceCodeableConcept', null, 400);
|
|
@@ -169,7 +180,7 @@ class TranslateWorker extends TerminologyWorker {
|
|
|
169
180
|
// If no explicit concept map, we need to find one based on source/target
|
|
170
181
|
if (conceptMaps.length == 0) {
|
|
171
182
|
await this.findConceptMapsInAdditionalResources(conceptMaps, coding.system, sourceScope, targetScope, targetSystem);
|
|
172
|
-
await this.provider.findConceptMapForTranslation(this.opContext, conceptMaps, coding.system, sourceScope, targetScope, targetSystem);
|
|
183
|
+
await this.provider.findConceptMapForTranslation(this.opContext, conceptMaps, coding.system, sourceScope, targetScope, targetSystem, coding.code);
|
|
173
184
|
if (conceptMaps.length == 0) {
|
|
174
185
|
throw new Issue('error', 'not-found', null, null, 'No suitable ConceptMaps found for the specified source and target', null, 404);
|
|
175
186
|
}
|
|
@@ -208,10 +219,14 @@ class TranslateWorker extends TerminologyWorker {
|
|
|
208
219
|
txp.readParams(params.jsonObj);
|
|
209
220
|
|
|
210
221
|
// Get the source coding
|
|
222
|
+
// Accept both R5 names (sourceCoding, sourceCodeableConcept, sourceCode)
|
|
223
|
+
// and R4 names (coding, codeableConcept, code) as aliases
|
|
211
224
|
let coding = null;
|
|
212
225
|
|
|
213
226
|
if (params.has('sourceCoding')) {
|
|
214
227
|
coding = params.get('sourceCoding');
|
|
228
|
+
} else if (params.has('coding')) {
|
|
229
|
+
coding = params.get('coding');
|
|
215
230
|
} else if (params.has('sourceCodeableConcept')) {
|
|
216
231
|
const cc = params.get('sourceCodeableConcept');
|
|
217
232
|
if (cc.coding && cc.coding.length > 0) {
|
|
@@ -220,15 +235,25 @@ class TranslateWorker extends TerminologyWorker {
|
|
|
220
235
|
throw new Issue('error', 'invalid', null, null,
|
|
221
236
|
'sourceCodeableConcept must contain at least one coding', null, 400);
|
|
222
237
|
}
|
|
223
|
-
} else if (params.has('
|
|
224
|
-
|
|
238
|
+
} else if (params.has('codeableConcept')) {
|
|
239
|
+
const cc = params.get('codeableConcept');
|
|
240
|
+
if (cc.coding && cc.coding.length > 0) {
|
|
241
|
+
coding = cc.coding[0];
|
|
242
|
+
} else {
|
|
243
|
+
throw new Issue('error', 'invalid', null, null,
|
|
244
|
+
'codeableConcept must contain at least one coding', null, 400);
|
|
245
|
+
}
|
|
246
|
+
} else if (params.has('sourceCode') || params.has('code')) {
|
|
247
|
+
const code = params.has('sourceCode') ? params.get('sourceCode') : params.get('code');
|
|
248
|
+
const system = params.has('system') ? params.get('system') : null;
|
|
249
|
+
if (!system) {
|
|
225
250
|
throw new Issue('error', 'invalid', null, null,
|
|
226
|
-
'system parameter is required when using sourceCode', null, 400);
|
|
251
|
+
'system parameter is required when using code/sourceCode', null, 400);
|
|
227
252
|
}
|
|
228
253
|
coding = {
|
|
229
|
-
system
|
|
254
|
+
system,
|
|
230
255
|
version: params.get('version'),
|
|
231
|
-
code
|
|
256
|
+
code
|
|
232
257
|
};
|
|
233
258
|
} else {
|
|
234
259
|
throw new Issue('error', 'invalid', null, null,
|
package/tx/workers/validate.js
CHANGED
|
@@ -1107,7 +1107,7 @@ class ValueSetChecker {
|
|
|
1107
1107
|
codelist = !codelist ? '\'' + cc + '\'' : codelist + ', \'' + cc + '\'';
|
|
1108
1108
|
|
|
1109
1109
|
if (v === false && !this.valueSet.jsonObj.internallyDefined && mode === 'codeableConcept') {
|
|
1110
|
-
let m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.
|
|
1110
|
+
let m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.vurlOrMsg, '\'' + cc + '\'']);
|
|
1111
1111
|
let p = issuePath + '.coding[' + i + '].code';
|
|
1112
1112
|
op.addIssue(new Issue('information', 'code-invalid', p, 'None_of_the_provided_codes_are_in_the_value_set_one', m, 'this-code-not-in-vs'));
|
|
1113
1113
|
if (cause.value === 'null') {
|
|
@@ -1284,10 +1284,10 @@ class ValueSetChecker {
|
|
|
1284
1284
|
let mid, m, p;
|
|
1285
1285
|
if (mode === 'codeableConcept') {
|
|
1286
1286
|
mid = 'TX_GENERAL_CC_ERROR_MESSAGE';
|
|
1287
|
-
m = this.worker.i18n.translate('TX_GENERAL_CC_ERROR_MESSAGE', this.params.HTTPLanguages, [this.valueSet.
|
|
1287
|
+
m = this.worker.i18n.translate('TX_GENERAL_CC_ERROR_MESSAGE', this.params.HTTPLanguages, [this.valueSet.vurlOrMsg]);
|
|
1288
1288
|
} else {
|
|
1289
1289
|
mid = 'None_of_the_provided_codes_are_in_the_value_set_one';
|
|
1290
|
-
m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.
|
|
1290
|
+
m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.vurlOrMsg, codelist]);
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
1293
|
if (mode === 'codeableConcept') {
|