diff --git a/src/converter/__tests__/fce.test.ts b/src/converter/__tests__/fce.test.ts index 6a3cba4..e7eb652 100644 --- a/src/converter/__tests__/fce.test.ts +++ b/src/converter/__tests__/fce.test.ts @@ -36,7 +36,7 @@ import fce_practitioner_create from './resources/questionnaire_fce/practitioner_ import fce_practitioner_create_structure_map from './resources/questionnaire_fce/practitioner_create_structure_map.json'; import fce_practitioner_edit from './resources/questionnaire_fce/practitioner_edit.json'; import fce_practitioner_role_create from './resources/questionnaire_fce/practitioner_role_create.json'; -import fce_printable_header from './resources/questionnaire_fce/printable_header.json'; +import fce_printable_elements from './resources/questionnaire_fce/printable_elements.json'; import fce_public_appointment from './resources/questionnaire_fce/public_appointment.json'; import fce_questionnaire_variable from './resources/questionnaire_fce/questionnaire_variable.json'; import fce_review_of_systems from './resources/questionnaire_fce/review_of_systems.json'; @@ -82,7 +82,7 @@ import fhir_practitioner_create from './resources/questionnaire_fhir/practitione import fhir_practitioner_create_structure_map from './resources/questionnaire_fhir/practitioner_create_structure_map.json'; import fhir_practitioner_edit from './resources/questionnaire_fhir/practitioner_edit.json'; import fhir_practitioner_role_create from './resources/questionnaire_fhir/practitioner_role_create.json'; -import fhir_printable_header from './resources/questionnaire_fhir/printable_header.json'; +import fhir_printable_elements from './resources/questionnaire_fhir/printable_elements.json'; import fhir_public_appointment from './resources/questionnaire_fhir/public_appointment.json'; import fhir_questionnaire_variable from './resources/questionnaire_fhir/questionnaire_variable.json'; import fhir_review_of_systems from './resources/questionnaire_fhir/review_of_systems.json'; @@ -149,7 +149,7 @@ describe('Questionanire and QuestionnaireResponses transformation', () => { ['chart-highlight', fhir_chart_highlight, fce_chart_highlight], ['column-width', fhir_column_width, fce_column_width], ['mapping-inline', fhir_mapping_inline, fce_mapping_inline], - ['printable-header', fhir_printable_header, fce_printable_header], + ['printable-elements', fhir_printable_elements, fce_printable_elements], ])('Each FHIR Questionnaire should convert to FCE %s', async (_, fhir_questionnaire, fce_questionnaire) => { expect(toFirstClassExtension(fhir_questionnaire as FHIRQuestionnaire)).toStrictEqual(fce_questionnaire); }); @@ -202,7 +202,7 @@ describe('Questionanire and QuestionnaireResponses transformation', () => { ['chart-highlight', fce_chart_highlight, fhir_chart_highlight], ['column-width', fce_column_width, fhir_column_width], ['mapping-inline', fce_mapping_inline, fhir_mapping_inline], - ['printable-header', fce_printable_header, fhir_printable_header], + ['printable-elements', fce_printable_elements, fhir_printable_elements], ])('Each FCE Questionnaire should convert to FHIR %s', async (_, fce_questionnaire, fhir_questionnaire) => { expect(sortExtensionsList(fromFirstClassExtension(fce_questionnaire as FCEQuestionnaire))).toStrictEqual( sortExtensionsList(fhir_questionnaire), diff --git a/src/converter/__tests__/resources/questionnaire_fce/printable_elements.json b/src/converter/__tests__/resources/questionnaire_fce/printable_elements.json new file mode 100644 index 0000000..22842f5 --- /dev/null +++ b/src/converter/__tests__/resources/questionnaire_fce/printable_elements.json @@ -0,0 +1,104 @@ +{ + "resourceType": "Questionnaire", + "status": "active", + "meta": { + "profile": ["https://emr-core.beda.software/StructureDefinition/fhir-emr-questionnaire"] + }, + "printableCover": [ + { + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-cover.pdf" + } + }, + { + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "valueString": "Cover Page" + } + ], + "printableHeaderFirstPage": [ + { + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-header-first-page.pdf" + } + }, + { + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "valueString": "First Page" + } + ], + "printableHeader": [ + { + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-header.pdf" + } + }, + { + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "valueString": "Patient Name" + } + ], + "printableFooter": [ + { + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-footer.pdf" + } + }, + { + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "valueString": "Footer" + } + ], + "printableFooterLastPage": [ + { + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-footer-last-page.pdf" + } + }, + { + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "valueString": "Last Page" + } + ], + "item": [ + { + "linkId": "title", + "type": "string", + "text": "Title" + } + ] +} diff --git a/src/converter/__tests__/resources/questionnaire_fce/printable_header.json b/src/converter/__tests__/resources/questionnaire_fce/printable_header.json deleted file mode 100644 index 111acaf..0000000 --- a/src/converter/__tests__/resources/questionnaire_fce/printable_header.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "resourceType": "Questionnaire", - "status": "active", - "meta": { - "profile": ["https://emr-core.beda.software/StructureDefinition/fhir-emr-questionnaire"] - }, - "printableHeader": { - "contentType": "application/pdf", - "data": "base64-encoded-pdf-data", - "url": "https://example.com/printable-header.pdf" - }, - "item": [ - { - "linkId": "title", - "type": "string", - "text": "Title" - } - ] -} diff --git a/src/converter/__tests__/resources/questionnaire_fhir/printable_elements.json b/src/converter/__tests__/resources/questionnaire_fhir/printable_elements.json new file mode 100644 index 0000000..3389f4a --- /dev/null +++ b/src/converter/__tests__/resources/questionnaire_fhir/printable_elements.json @@ -0,0 +1,111 @@ +{ + "resourceType": "Questionnaire", + "status": "active", + "meta": { + "profile": ["https://emr-core.beda.software/StructureDefinition/fhir-emr-questionnaire"] + }, + "extension": [ + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-cover", + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-cover.pdf" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-cover", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-cover", + "valueString": "Cover Page" + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header-first-page", + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-header-first-page.pdf" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header-first-page", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header-first-page", + "valueString": "First Page" + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header", + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-header.pdf" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer", + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-footer.pdf" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer", + "valueString": "Footer" + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer-last-page", + "valueAttachment": { + "contentType": "application/pdf", + "data": "base64-encoded-pdf-data", + "url": "https://example.com/printable-footer-last-page.pdf" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer-last-page", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%Patient.name.given[0] + ' ' + %Patient.name.family" + } + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-footer-last-page", + "valueString": "Last Page" + }, + { + "url": "https://emr-core.beda.software/StructureDefinition/printable-header", + "valueString": "Patient Name" + } + ], + "item": [ + { + "linkId": "title", + "type": "string", + "text": "Title" + } + ] +} diff --git a/src/converter/__tests__/resources/questionnaire_fhir/printable_header.json b/src/converter/__tests__/resources/questionnaire_fhir/printable_header.json deleted file mode 100644 index 8f53b3f..0000000 --- a/src/converter/__tests__/resources/questionnaire_fhir/printable_header.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "resourceType": "Questionnaire", - "status": "active", - "meta": { - "profile": ["https://emr-core.beda.software/StructureDefinition/fhir-emr-questionnaire"] - }, - "extension": [ - { - "url": "https://emr-core.beda.software/StructureDefinition/printable-header", - "valueAttachment": { - "contentType": "application/pdf", - "data": "base64-encoded-pdf-data", - "url": "https://example.com/printable-header.pdf" - } - } - ], - "item": [ - { - "linkId": "title", - "type": "string", - "text": "Title" - } - ] -} diff --git a/src/converter/fceToFhir/questionnaire/processExtensions.ts b/src/converter/fceToFhir/questionnaire/processExtensions.ts index a7d7579..33b4994 100644 --- a/src/converter/fceToFhir/questionnaire/processExtensions.ts +++ b/src/converter/fceToFhir/questionnaire/processExtensions.ts @@ -1,6 +1,20 @@ -import { FCEQuestionnaire } from '../../../fce.types'; +import { FCEPrintableElement, FCEQuestionnaire } from '../../../fce.types'; import { Extension as FHIRExtension, Questionnaire as FHIRQuestionnaire } from 'fhir/r4b'; +function processPrintableElements(url: string, elements: FCEPrintableElement[]): FHIRExtension[] { + return elements.map((element) => { + if ('valueAttachment' in element) { + return { url, valueAttachment: element.valueAttachment }; + } + + if ('valueExpression' in element) { + return { url, valueExpression: element.valueExpression }; + } + + return { url, valueString: (element as { valueString: string }).valueString }; + }); +} + export function processExtensions(questionnaire: FCEQuestionnaire): FHIRQuestionnaire { const { launchContext, @@ -11,8 +25,11 @@ export function processExtensions(questionnaire: FCEQuestionnaire): FHIRQuestion assembleContext, itemPopulationContext, variable, + printableCover, printableHeader, + printableHeaderFirstPage, printableFooter, + printableFooterLastPage, ...fhirQuestionnaire } = questionnaire; @@ -119,18 +136,49 @@ export function processExtensions(questionnaire: FCEQuestionnaire): FHIRQuestion ); } + if (printableCover) { + extensions = extensions.concat( + processPrintableElements( + 'https://emr-core.beda.software/StructureDefinition/printable-cover', + printableCover, + ), + ); + } + if (printableHeader) { - extensions.push({ - url: 'https://emr-core.beda.software/StructureDefinition/printable-header', - valueAttachment: printableHeader, - }); + extensions = extensions.concat( + processPrintableElements( + 'https://emr-core.beda.software/StructureDefinition/printable-header', + printableHeader, + ), + ); + } + + if (printableHeaderFirstPage) { + extensions = extensions.concat( + processPrintableElements( + 'https://emr-core.beda.software/StructureDefinition/printable-header-first-page', + printableHeaderFirstPage, + ), + ); } if (printableFooter) { - extensions.push({ - url: 'https://emr-core.beda.software/StructureDefinition/printable-footer', - valueAttachment: printableFooter, - }); + extensions = extensions.concat( + processPrintableElements( + 'https://emr-core.beda.software/StructureDefinition/printable-footer', + printableFooter, + ), + ); + } + + if (printableFooterLastPage) { + extensions = extensions.concat( + processPrintableElements( + 'https://emr-core.beda.software/StructureDefinition/printable-footer-last-page', + printableFooterLastPage, + ), + ); } if (extensions.length) { diff --git a/src/converter/fhirToFce/questionnaire/processExtensions.ts b/src/converter/fhirToFce/questionnaire/processExtensions.ts index 2a4b9aa..55497c3 100644 --- a/src/converter/fhirToFce/questionnaire/processExtensions.ts +++ b/src/converter/fhirToFce/questionnaire/processExtensions.ts @@ -1,4 +1,5 @@ -import { Questionnaire as FHIRQuestionnaire, Expression as FHIRExpression, Attachment } from 'fhir/r4b'; +import { Questionnaire as FHIRQuestionnaire, Expression as FHIRExpression } from 'fhir/r4b'; +import { FCEPrintableElement } from '../../../fce.types'; export function processExtensions(fhirQuestionnaire: FHIRQuestionnaire): { launchContext?: any[]; @@ -9,8 +10,11 @@ export function processExtensions(fhirQuestionnaire: FHIRQuestionnaire): { assembleContext?: string[]; itemPopulationContext?: FHIRExpression; variable?: FHIRExpression[]; - printableHeader?: Attachment; - printableFooter?: Attachment; + printableCover?: FCEPrintableElement[]; + printableHeader?: FCEPrintableElement[]; + printableHeaderFirstPage?: FCEPrintableElement[]; + printableFooter?: FCEPrintableElement[]; + printableFooterLastPage?: FCEPrintableElement[]; } { const launchContext = processLaunchContext(fhirQuestionnaire); const mapping = processMapping(fhirQuestionnaire); @@ -20,8 +24,26 @@ export function processExtensions(fhirQuestionnaire: FHIRQuestionnaire): { const assembleContext = processAssembleContext(fhirQuestionnaire); const itemPopulationContext = processItemPopulationContext(fhirQuestionnaire); const variable = processVariable(fhirQuestionnaire); - const printableHeader = processPrintableHeader(fhirQuestionnaire); - const printableFooter = processPrintableFooter(fhirQuestionnaire); + const printableCover = processPrintableElements( + fhirQuestionnaire, + 'https://emr-core.beda.software/StructureDefinition/printable-cover', + ); + const printableHeader = processPrintableElements( + fhirQuestionnaire, + 'https://emr-core.beda.software/StructureDefinition/printable-header', + ); + const printableHeaderFirstPage = processPrintableElements( + fhirQuestionnaire, + 'https://emr-core.beda.software/StructureDefinition/printable-header-first-page', + ); + const printableFooter = processPrintableElements( + fhirQuestionnaire, + 'https://emr-core.beda.software/StructureDefinition/printable-footer', + ); + const printableFooterLastPage = processPrintableElements( + fhirQuestionnaire, + 'https://emr-core.beda.software/StructureDefinition/printable-footer-last-page', + ); return { launchContext: launchContext?.length ? launchContext : undefined, @@ -32,8 +54,11 @@ export function processExtensions(fhirQuestionnaire: FHIRQuestionnaire): { assembleContext: assembleContext.length ? assembleContext : undefined, itemPopulationContext: itemPopulationContext ? itemPopulationContext : undefined, variable: variable?.length ? variable : undefined, - printableHeader: printableHeader ? printableHeader : undefined, - printableFooter: printableFooter ? printableFooter : undefined, + printableCover: printableCover?.length ? printableCover : undefined, + printableHeader: printableHeader?.length ? printableHeader : undefined, + printableHeaderFirstPage: printableHeaderFirstPage?.length ? printableHeaderFirstPage : undefined, + printableFooter: printableFooter?.length ? printableFooter : undefined, + printableFooterLastPage: printableFooterLastPage?.length ? printableFooterLastPage : undefined, }; } @@ -163,26 +188,26 @@ function processVariable(fhirQuestionnaire: FHIRQuestionnaire): FHIRExpression[] return extensions.map((ext) => ext.valueExpression!); } -function processPrintableHeader(fhirQuestionnaire: FHIRQuestionnaire): Attachment | undefined { - const extension = fhirQuestionnaire.extension?.find( - (ext) => ext.url === 'https://emr-core.beda.software/StructureDefinition/printable-header', - ); - - if (!extension) { +function processPrintableElements( + fhirQuestionnaire: FHIRQuestionnaire, + extensionUrl: string, +): FCEPrintableElement[] | undefined { + const extensions = fhirQuestionnaire.extension?.filter((ext) => ext.url === extensionUrl); + if (!extensions?.length) { return undefined; } - return extension.valueAttachment; -} - -function processPrintableFooter(fhirQuestionnaire: FHIRQuestionnaire): Attachment | undefined { - const extension = fhirQuestionnaire.extension?.find( - (ext) => ext.url === 'https://emr-core.beda.software/StructureDefinition/printable-footer', - ); + const elements: FCEPrintableElement[] = []; - if (!extension) { - return undefined; + for (const ext of extensions) { + if (ext.valueAttachment) { + elements.push({ valueAttachment: ext.valueAttachment }); + } else if (ext.valueExpression) { + elements.push({ valueExpression: ext.valueExpression }); + } else if (ext.valueString !== undefined) { + elements.push({ valueString: ext.valueString }); + } } - return extension.valueAttachment; + return elements.length ? elements : undefined; } diff --git a/src/fce.types.ts b/src/fce.types.ts index 09d667c..3725457 100644 --- a/src/fce.types.ts +++ b/src/fce.types.ts @@ -32,10 +32,16 @@ export interface FCEQuestionnaire extends Questionnaire { /** NOTE: from extension http://hl7.org/fhir/StructureDefinition/variable */ /** Variable specifying a logic to generate a variable for use in subsequent logic. The name of the variable will be added to FHIRPath's context when processing descendants of the element that contains this extension. */ variable?: Expression[]; + /** NOTE: from extension https://emr-core.beda.software/StructureDefinition/printable-cover */ + printableCover?: FCEPrintableElement[]; /** NOTE: from extension https://emr-core.beda.software/StructureDefinition/printable-header */ - printableHeader?: Attachment; + printableHeader?: FCEPrintableElement[]; + /** NOTE: from extension https://emr-core.beda.software/StructureDefinition/printable-header-first-page */ + printableHeaderFirstPage?: FCEPrintableElement[]; /** NOTE: from extension https://emr-core.beda.software/StructureDefinition/printable-footer */ - printableFooter?: Attachment; + printableFooter?: FCEPrintableElement[]; + /** NOTE: from extension https://emr-core.beda.software/StructureDefinition/printable-footer-last-page */ + printableFooterLastPage?: FCEPrintableElement[]; /** NOTE: from extension http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-targetStructureMap */ targetStructureMap?: string[]; } @@ -216,3 +222,17 @@ export interface FCEQuestionnaireMappingReference { export interface FCEQuestionnaireMappingExpression { valueExpression: Expression; } + +export interface FCEPrintableAttachmentElement { + valueAttachment: Attachment; +} +export interface FCEPrintableExpressionElement { + valueExpression: Expression; +} +export interface FCEPrintableStringElement { + valueString: string; +} +export type FCEPrintableElement = + | FCEPrintableAttachmentElement + | FCEPrintableExpressionElement + | FCEPrintableStringElement;