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
Binary file modified docs/CSV_Templates.xlsx
Binary file not shown.
8 changes: 4 additions & 4 deletions docs/ctc-adverse-event.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mrn,adverseEventId,adverseEventCode,adverseEventCodeSystem,adverseEventCodeVersion,adverseEventDisplayText,adverseEventText,suspectedCauseId,suspectedCauseType,seriousness,seriousnessCodeSystem,seriousnessDisplayText,category,categoryCodeSystem,categoryDisplayText,studyId,effectiveDate,recordedDate,grade,expectation,resolvedDate,seriousnessOutcome
mrn-full-example,example-id-1,event-code,code-system,code-version,code-display,event-text,cause-id,resourceType,seriousness-code,code-system,seriousness-display,category-code,code-system,category-dislpay,id,1994-12-09,1994-12-09,1,expectation-code,YYYY-MM-DD,seriousness-outcome-code
mrn-two-category-example,example-id-2,event-code,code-system,code-version,code-display,event-text,cause-id,resourceType,seriousness-code,code-system,seriousness-display,category-code,code-system,category-dislpay,id,1994-12-09,1994-12-09,1,expectation-code,YYYY-MM-DD,seriousness-outcome-code
mrn-minimal-example,,code-from-default-system,,,,,,,,,,,,,1994-12-09,,1,,,,,
mrn,adverseEventId,adverseEventCode,adverseEventCodeSystem,adverseEventCodeVersion,adverseEventDisplayText,adverseEventText,suspectedCauseId,suspectedCauseType,seriousness,seriousnessCodeSystem,seriousnessDisplayText,category,categoryCodeSystem,categoryDisplayText,studyId,effectiveDate,recordedDate,grade,expectation,resolvedDate,seriousnessOutcome,actor,functionCode
mrn-full-example,example-id-1,event-code,code-system,code-version,code-display,event-text,cause-id,resourceType,seriousness-code,code-system,seriousness-display,category-code,code-system,category-dislpay,id,1994-12-09,1994-12-09,1,expectation-code,YYYY-MM-DD,seriousness-outcome-code,practitioner-id,function-code
mrn-two-category-example,example-id-2,event-code,code-system,code-version,code-display,event-text,cause-id,resourceType,seriousness-code,code-system,seriousness-display,category-code,code-system,category-dislpay,id,1994-12-09,1994-12-09,1,expectation-code,YYYY-MM-DD,seriousness-outcome-code,practitioner-id,
mrn-minimal-example,,code-from-default-system,,,,,,,,,,,,,1994-12-09,,1,,,,,,
14 changes: 14 additions & 0 deletions src/extractors/CSVCTCAdverseEventExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,14 @@ function formatData(adverseEventData, patientId) {
expectation,
resolveddate: resolvedDate,
seriousnessoutcome: seriousnessOutcome,
actor,
functioncode: functionCode,
} = data;

if (!(adverseEventCode && effectiveDate && grade)) {
throw new Error('The adverse event is missing an expected attribute. Adverse event code, effective date, and grade are all required.');
} else if (functionCode && !actor) {
throw new Error('The adverse event is missing an expected attribute. Adverse event actor is a required element when a functionCode value is included.');
}

const categoryCodes = category.split('|');
Expand Down Expand Up @@ -90,6 +94,16 @@ function formatData(adverseEventData, patientId) {
'http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl',
),
},
actor,
functionCode: !functionCode ? null : {
code: functionCode,
system: 'http://terminology.hl7.org/CodeSystem/v3-ParticipationType',
display: getDisplayFromConcept(
path.resolve(__dirname, '..', 'helpers', 'valueSets', 'adverse-event-participant-function-value-set.json'),
functionCode,
'http://terminology.hl7.org/CodeSystem/v3-ParticipationType',
),
},
};
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"resourceType": "ValueSet",
"id": "adverse-event-participant-function-value-set",
"text": {
"status": "extensions",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><ul><li>Include these codes as defined in <a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html\"><code>http://terminology.hl7.org/CodeSystem/v3-ParticipationType</code></a><table class=\"none\"><tr><td style=\"white-space:nowrap\"><b>Code</b></td><td><b>Display</b></td><td><b>Definition</b></td></tr><tr><td><a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html#v3-ParticipationType-INF\">INF</a></td><td>Informant</td><td>A source of reported information (e.g., a next of kin who answers questions about the patient's history). For history questions, the patient is logically an informant, yet the informant of history questions is implicitly the subject.</td></tr><tr><td><a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html#v3-ParticipationType-PART\">PART</a></td><td>Participation</td><td>Indicates that the target of the participation is involved in some manner in the act, but does not qualify how.</td></tr><tr><td><a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html#v3-ParticipationType-WIT\">WIT</a></td><td>Witness</td><td>Only with service events. A person witnessing the action happening without doing anything. A witness is not necessarily aware, much less approves of anything stated in the service event. Example for a witness is students watching an operation or an advanced directive witness.</td></tr><tr><td><a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html#v3-ParticipationType-AUT\">AUT</a></td><td>Author (originator)</td><td>**Definition:** A party that originates the Act and therefore has responsibility for the information given in the Act and ownership of this Act.<br/><br/>**Example:** the report writer, the person writing the act definition, the guideline author, the placer of an order, the EKG cart (device) creating a report etc. Every Act should have an author. Authorship is regardless of mood always actual authorship.<br/><br/>Examples of such policies might include:<br/><br/> * The author and anyone they explicitly delegate may update the report;<br/> * All administrators within the same clinic may cancel and reschedule appointments created by other administrators within that clinic;<br/><br/>A party that is neither an author nor a party who is extended authorship maintenance rights by policy, may only amend, reverse, override, replace, or follow up in other ways on this Act, whereby the Act remains intact and is linked to another Act authored by that other party.</td></tr><tr><td><a href=\"http://terminology.hl7.org/2.1.0/CodeSystem-v3-ParticipationType.html#v3-ParticipationType-AUTHEN\">AUTHEN</a></td><td>Authenticator</td><td>A verifier who attests to the accuracy of an act, but who does not have privileges to legally authenticate the act. An example would be a resident physician who sees a patient and dictates a note, then later signs it. Their signature constitutes an authentication.</td></tr></table></li></ul></div>"
},
"url": "http://hl7.org/fhir/us/ctcae/ValueSet/adverse-event-participant-function-value-set",
"version": "0.0.1",
"name": "AdverseEventParticipantFunctionVS",
"title": "Adverse Event Participant Function",
"status": "active",
"date": "2021-12-03T16:46:43+00:00",
"publisher": "HL7 International Clinical Interoperability Council",
"contact": [
{
"name": "HL7 International Clinical Interoperability Council",
"telecom": [
{
"system": "url",
"value": "http://www.mcodeinitiative.org"
}
]
}
],
"description": "This value set includes codes that describe the type of involvement of the actor in the adverse event",
"jurisdiction": [
{
"coding": [
{
"system": "urn:iso:std:iso:3166",
"code": "US",
"display": "United States of America"
}
]
}
],
"compose": {
"include": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"concept": [
{
"code": "INF",
"display": "Informant"
},
{
"code": "PART",
"display": "Participation"
},
{
"code": "WIT",
"display": "Witness"
},
{
"code": "AUT",
"display": "Author (originator)"
},
{
"code": "AUTHEN",
"display": "Authenticator"
}
]
}
]
}
}
39 changes: 37 additions & 2 deletions src/templates/CTCAdverseEventTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,47 @@ function seriousnessOutcomeTemplate(seriousnessOutcome) {
};
}

function participantFunctionTemplate(functionCode) {
return {
url: 'function',
valueCodeableConcept: {
coding: [
coding(functionCode),
],
},
};
}

function participantActorTemplate(actor) {
return {
url: 'actor',
valueReference: {
...reference({ id: actor }),
},
};
}

function participantTemplate(actor, functionCode) {
return {
url: 'http://hl7.org/fhir/us/ctcae/StructureDefinition/adverse-event-participant',
...extensionArr(
functionCode ? participantFunctionTemplate(functionCode) : null,
participantActorTemplate(actor),
),
};
}


function CTCAdverseEventTemplate({
id, subjectId, code, system, version, display, text, suspectedCauseId, suspectedCauseType, seriousnessCode, seriousnessCodeSystem, seriousnessDisplayText, category,
studyId, effectiveDateTime, recordedDateTime, grade, resolvedDate, expectation, seriousnessOutcome,
studyId, effectiveDateTime, recordedDateTime, grade, resolvedDate, expectation, seriousnessOutcome, actor, functionCode,
}) {
if (!(subjectId && code && system && effectiveDateTime && grade)) {
throw Error('Trying to render an AdverseEventTemplate, but a required argument is messing; ensure that subjectId, code, system, grade, and effectiveDateTime are all present');
throw Error('Trying to render an AdverseEventTemplate, but a required argument is missing; ensure that subjectId, code, system, grade, and effectiveDateTime are all present');
}

if (functionCode && !actor) {
throw Error('Trying to render an AdverseEventTemplate, but a required argument is missing; actor is a required value when functionCode is included');
}

return {
Expand All @@ -119,6 +153,7 @@ function CTCAdverseEventTemplate({
resolvedDate ? resolvedDateTemplate(resolvedDate) : null,
expectation ? expectationTemplate(expectation) : null,
seriousnessOutcome ? seriousnessOutcomeTemplate(seriousnessOutcome) : null,
actor ? participantTemplate(actor, functionCode) : null,
),
subject: reference({ id: subjectId, resourceType: 'Patient' }),
...ifSomeArgs(eventTemplate)({ code, system, version, display }, text),
Expand Down
10 changes: 10 additions & 0 deletions test/extractors/CSVCTCAdverseEventextractor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('CSVCTCAdverseEventExtractor', () => {
test('should join data appropriately and throw errors when missing required properties', () => {
const expectedErrorString = 'The adverse event is missing an expected attribute. Adverse event code, effective date, and grade are all required.';
const expectedCategoryErrorString = 'A category attribute on the adverse event is missing a corresponding categoryCodeSystem or categoryDisplayText value.';
const expectedActorErrorString = 'The adverse event is missing an expected attribute. Adverse event actor is a required element when a functionCode value is included.';
const localData = _.cloneDeep(exampleCTCCSVAdverseEventModuleResponse);
const patientId = getPatientFromContext(MOCK_CONTEXT).id;

Expand All @@ -60,6 +61,15 @@ describe('CSVCTCAdverseEventExtractor', () => {
localData[0].categorydisplaytext = 'Product Use Error|';
expect(formatData(localData, patientId)).toEqual(expect.anything());

// Test that deleting the actor value but leaving functionCode will throw an error
delete localData[0].actor;
expect(() => formatData(localData, patientId)).toThrow(new Error(expectedActorErrorString));

// Test that deleting the functionCode value works fine
localData[0].actor = 'practitioner-id';
delete localData[0].functioncode;
expect(formatData(localData, patientId)).toEqual(expect.anything());

// Test that deleting a mandatory value throws an error
delete localData[0].grade;
expect(() => formatData(localData, patientId)).toThrow(new Error(expectedErrorString));
Expand Down
23 changes: 23 additions & 0 deletions test/extractors/fixtures/csv-ctc-adverse-event-bundle.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@
}
]
}
},
{
"url": "http://hl7.org/fhir/us/ctcae/StructureDefinition/adverse-event-participant",
"extension": [
{
"url": "function",
"valueCodeableConcept": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code": "INF",
"display": "Informant"
}
]
}
},
{
"url": "actor",
"valueReference": {
"reference": "urn:uuid:practitioner-id"
}
}
]
}
],
"subject": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"grade": "1",
"resolveddate": "2021-12-01",
"seriousnessoutcome": "C113380",
"expectation": "C41333"
"expectation": "C41333",
"actor": "practitioner-id",
"functioncode": "INF"
}
]
8 changes: 4 additions & 4 deletions test/sample-client-data/ctc-adverse-event-information.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mrn,adverseEventId,adverseEventCode,adverseEventCodeSystem,adverseEventCodeVersion,adverseEventDisplayText,adverseEventText,suspectedCauseId,suspectedCauseType,seriousness,seriousnessCodeSystem,seriousnessDisplayText,category,categoryCodeSystem,categoryDisplayText,studyId,effectiveDate,recordedDate,grade,expectation,resolvedDate,seriousnessOutcome
123,adverseEventId-1,10012174,http://terminology.hl7.org/CodeSystem/MDRAE,20.0,Dehydration,DHN IV given,procedure-id,Procedure,serious,http://terminology.hl7.org/CodeSystem/adverse-event-seriousness,Serious,product-use-error|product-quality|wrong-rate,http://terminology.hl7.org/CodeSystem/adverse-event-category|http://snomed.info/sct|http://terminology.hl7.org/CodeSystem/adverse-event-category,Product Use Error|Product Quality|Wrong Rate,researchId-1,12-09-1994,12-09-1994,1,C41333,2021-12-01,C113380
456,adverseEventId-2,C143283,http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl,20.0,Anemia,AIHA NGTD,medicationId-1,Medication,non-serious,http://terminology.hl7.org/CodeSystem/adverse-event-seriousness,Non-serious,product-quality|wrong-rate,http://terminology.hl7.org/CodeSystem/adverse-event-category|,Product Quality|,researchId-2,12-10-1995,12-10-1995,2,C41333,2020-10-02,C113380
789,adverseEventId-3,150003,,,,,,,,,,product-use-error,,,,12-09-1994,,3,,,
mrn,adverseEventId,adverseEventCode,adverseEventCodeSystem,adverseEventCodeVersion,adverseEventDisplayText,adverseEventText,suspectedCauseId,suspectedCauseType,seriousness,seriousnessCodeSystem,seriousnessDisplayText,category,categoryCodeSystem,categoryDisplayText,studyId,effectiveDate,recordedDate,grade,expectation,resolvedDate,seriousnessOutcome,actor,functionCode
123,adverseEventId-1,10012174,http://terminology.hl7.org/CodeSystem/MDRAE,20.0,Dehydration,DHN IV given,procedure-id,Procedure,serious,http://terminology.hl7.org/CodeSystem/adverse-event-seriousness,Serious,product-use-error|product-quality|wrong-rate,http://terminology.hl7.org/CodeSystem/adverse-event-category|http://snomed.info/sct|http://terminology.hl7.org/CodeSystem/adverse-event-category,Product Use Error|Product Quality|Wrong Rate,researchId-1,12-09-1994,12-09-1994,1,C41333,2021-12-01,C113380,practitioner-1,PART
456,adverseEventId-2,C143283,http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl,20.0,Anemia,AIHA NGTD,medicationId-1,Medication,non-serious,http://terminology.hl7.org/CodeSystem/adverse-event-seriousness,Non-serious,product-quality|wrong-rate,http://terminology.hl7.org/CodeSystem/adverse-event-category|,Product Quality|,researchId-2,12-10-1995,12-10-1995,2,C41333,2020-10-02,C113380,practitioner-2,
789,adverseEventId-3,150003,,,,,,,,,,product-use-error,,,,12-09-1994,,3,,,,,
18 changes: 18 additions & 0 deletions test/templates/ctcAdverseEvent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const VALID_DATA = {
system: 'http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl',
display: 'Expected Adverse Event',
},
actor: 'practitioner-id',
functionCode: {
code: 'PART',
system: 'http://terminology.hl7.org/CodeSystem/v3-ParticipationType',
display: 'Participation',
},
};

const MINIMAL_DATA = {
Expand Down Expand Up @@ -90,13 +96,20 @@ const INVALID_DATA = {
system: 'http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl',
display: 'Expected Adverse Event',
},
actor: 'practitioner-id',
functionCode: {
code: 'PART',
system: 'http://terminology.hl7.org/CodeSystem/v3-ParticipationType',
display: 'Participation',
},
};

describe('test Adverse Event template', () => {
test('valid data passed into template should generate FHIR resource', () => {
const generatedAdverseEvent = CTCAdverseEventTemplate(VALID_DATA);

expect(generatedAdverseEvent).toEqual(maximalValidExampleAdverseEvent);

expect(isValidFHIR(generatedAdverseEvent)).toBeTruthy();
});

Expand Down Expand Up @@ -137,4 +150,9 @@ describe('test Adverse Event template', () => {
test('invalid data should throw an error', () => {
expect(() => CTCAdverseEventTemplate(INVALID_DATA)).toThrow(Error);
});

test('Otherwise valid data including the functionCode but not an actor should throw an error', () => {
delete VALID_DATA.actor;
expect(() => CTCAdverseEventTemplate(VALID_DATA)).toThrow(Error);
});
});
23 changes: 23 additions & 0 deletions test/templates/fixtures/maximal-ctc-adverse-event-resource.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@
}
]
}
},
{
"url": "http://hl7.org/fhir/us/ctcae/StructureDefinition/adverse-event-participant",
"extension": [
{
"url": "function",
"valueCodeableConcept": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ParticipationType",
"code": "PART",
"display": "Participation"
}
]
}
},
{
"url": "actor",
"valueReference": {
"reference": "urn:uuid:practitioner-id"
}
}
]
}
],
"event": {
Expand Down