Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions tx/cs/cs-snomed.js
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,19 @@ class SnomedProvider extends BaseCSServices {
}
}

async incompleteValidationMessage(context) {

const ctxt = await this.#ensureContext(context);

if (!ctxt) return null;

if (ctxt.isComplex()) {
return "The expression is grammatically correct and the concepts are valid, but the expression has not been checked against the SNOMED CT concept model (MRCM)";
} else {
return null;
}
}

async locateIsA(code, parent, disallowParent = false) {


Expand Down
123 changes: 71 additions & 52 deletions tx/workers/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ class ValueSetChecker {
let tsys = '';
let tcode = '';
let tver = '';
let vcc = {};
let vcc = {}; // todo: VCC is an appendage, and useless. remove it
if (code.text) {
vcc.text = code.text;
}
Expand Down Expand Up @@ -1066,6 +1066,9 @@ class ValueSetChecker {
tcode = c.code;
tver = c.version;
}
if (!tver && ver.value) {
tver = ver.value;
}
let cc;
if (!ws) {
ws = "";
Expand Down Expand Up @@ -1209,6 +1212,9 @@ class ValueSetChecker {
}
}
} else {
if (!c.version && mode == 'codeableConcept' && prov.version()) {
c.version = prov.version();
}
await this.worker.listDisplaysFromCodeSystem(list, prov, ctxt.context);
let pd = list.preferredDisplay(this.params.workingLanguages());
if (pd) {
Expand Down Expand Up @@ -1243,7 +1249,7 @@ class ValueSetChecker {
msg(m);
op.addIssue(new Issue(severity, 'invalid', addToPath(path, 'display'), baseMsg, m, 'invalid-display'));
}
if (prov.version() && code.coding.length < 2) {
if (prov.version() && mode != 'codeableConcept') {
result.addParamStr('version', prov.version());
}
}
Expand Down Expand Up @@ -1518,36 +1524,8 @@ class ValueSetChecker {
if (loc.message && op) {
op.addIssue(new Issue('information', 'code-invalid', addToPath(path, 'code'), null, loc.message, 'invalid-code'));
}
} else if (!(this.params.abstractOk || !(await cs.isAbstract(loc.context)))) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
if (!this.params.membershipOnly) {
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
}
} else if (this.excludeInactives() && await cs.isInactive(loc.context)) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
result = false;
messages.push(msg);
if (!this.params.membershipOnly) {
inactive.value = true;
inactive.path = path;
if (inactive.value) {
vstatus.value = await cs.getStatus(loc.context);
}
}
} else if (this.params.activeOnly && await cs.isInactive(loc.context)) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
result = false;
inactive.value = true;
inactive.path = path;
vstatus.value = await cs.getStatus(loc.context);
let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
messages.push(msg);
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
} else {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
result = true;
if (await cs.code(loc.context) != code) {
let msg;
if (cs.version()) {
Expand All @@ -1563,22 +1541,53 @@ class ValueSetChecker {
op.addIssue(new Issue('information', 'informational', addToPath(path, 'code'), null, msg, 'process-note'));
}
await this.worker.listDisplaysFromCodeSystem(displays, cs, loc.context);
inactive.value = await cs.isInactive(loc.context);
inactive.path = path;
vstatus.value = await cs.getStatus(loc.context);

if (vcc !== null) {
if (!vcc.coding) {
vcc.coding = [];
if (!(this.params.abstractOk || !(await cs.isAbstract(loc.context)))) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
if (!this.params.membershipOnly) {
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
}
vcc.coding.push({
system: cs.system(),
version: cs.version(),
code: await cs.code(loc.context),
display: displays.preferredDisplay(this.params.workingLanguages())
});
} else if (this.excludeInactives() && await cs.isInactive(loc.context)) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
result = false;
messages.push(msg);
if (!this.params.membershipOnly) {
inactive.value = true;
inactive.path = path;
if (inactive.value) {
vstatus.value = await cs.getStatus(loc.context);
}
}
} else if (this.params.activeOnly && await cs.isInactive(loc.context)) {
this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
result = false;
inactive.value = true;
inactive.path = path;
vstatus.value = await cs.getStatus(loc.context);
let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
messages.push(msg);
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
} else {
result = true;
inactive.value = await cs.isInactive(loc.context);
inactive.path = path;
vstatus.value = await cs.getStatus(loc.context);

if (vcc !== null) {
if (!vcc.coding) {
vcc.coding = [];
}
vcc.coding.push({
system: cs.system(),
version: cs.version(),
code: await cs.code(loc.context),
display: displays.preferredDisplay(this.params.workingLanguages())
});
}
return result;
}
return result;
}
}

Expand Down Expand Up @@ -1863,13 +1872,14 @@ class ValidateWorker extends TerminologyWorker {
let coded;
let mode;

try {
// Handle tx-resource and cache-id parameters
this.setupAdditionalResources(params);
// Handle tx-resource and cache-id parameters
this.setupAdditionalResources(params);

let txp = new TxParameters(this.languages, this.i18n, true);
txp.readParams(params);
for (const item of txp.supplements) this.requiredSupplements.add(item);
let txp = new TxParameters(this.languages, this.i18n, true);
txp.readParams(params);
for (const item of txp.supplements) this.requiredSupplements.add(item);

try {

// Extract coded value
mode = {mode: null};
Expand Down Expand Up @@ -1902,7 +1912,7 @@ class ValidateWorker extends TerminologyWorker {
this.log.error(error);
this.debugLog(error);
if (error instanceof Issue && !error.isHandleAsOO()) {
return this.handlePrepareError(error, coded, mode.mode);
return await this.handlePrepareError(error, coded, mode.mode, txp);
} else {
throw error;
}
Expand Down Expand Up @@ -2304,7 +2314,7 @@ class ValidateWorker extends TerminologyWorker {
if (!(error instanceof Issue) || error.isHandleAsOO()) {
throw error;
} else {
return this.handlePrepareError(error, coded, mode);
return await this.handlePrepareError(error, coded, mode, params);
}
}

Expand Down Expand Up @@ -2417,7 +2427,7 @@ class ValidateWorker extends TerminologyWorker {
}


handlePrepareError(error, coded, mode) {
async handlePrepareError(error, coded, mode, txp) {
let op = new OperationOutcome();
op.addIssue(error);
let p = new Parameters();
Expand All @@ -2434,6 +2444,15 @@ class ValidateWorker extends TerminologyWorker {
}
if (coded.coding[0].version) {
p.addParamStr('version', coded.coding[0].version)
} else if (coded.coding[0].system) {
try {
let cs = await this.findCodeSystem(coded.coding[0].system, null, txp);
if (cs && cs.version()) {
p.addParamStr('version', cs.version());
}
} catch (e) {
// nothing. not interested.
}
}
if (coded.coding[0].code) {
p.addParamCode('code', coded.coding[0].code)
Expand Down
Loading