Skip to content

Commit

Permalink
Location MFL Code Update
Browse files Browse the repository at this point in the history
  • Loading branch information
pmanko committed May 3, 2024
1 parent e181b41 commit 9c783fe
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 51 deletions.
Binary file modified config/ipms_facility_mappings.xlsx
Binary file not shown.
Binary file added config/ipms_facility_mappings_v2.xlsx
Binary file not shown.
Binary file added config/ipms_facility_mappings_v3.xlsx
Binary file not shown.
18 changes: 18 additions & 0 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ export async function hapiPassthrough(targetUri: any, res: Response): Promise<an
}
}

export async function hapiGet(resource: string, options: any): Promise<any> {
const targetUri = config.get('fhirServer:baseURL') + '/' + resource

logger.info(`Getting ${targetUri}`)

// Merge options
const sendOptions = {...options, username: config.get('fhirServer:username'), password: config.get('fhirServer:password')}

try {
const result = got.get(targetUri, sendOptions)

return await result.json()
} catch (error) {
logger.error(`Could not get ${targetUri}:\n${JSON.stringify(error)}`)
return null
}
}

export function getHapiPassthrough(): any {
return async (req: Request, res: Response) => {
const targetUri = config.get('fhirServer:baseURL') + req.url
Expand Down
12 changes: 7 additions & 5 deletions src/lib/locationMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import * as Excel from 'exceljs'

type FacilityMapping = {
index: number
orderingFacility: string
orderingFacilityMflCode: string
orderingFacilityName: string
receivingFacility: string
provider: string
patientType: string
Expand Down Expand Up @@ -33,11 +34,12 @@ async function getFacilityMappings() {
const mappings = rows.map((row: Excel.Row): FacilityMapping => {
return {
index: parseInt(getCellValue(row, 1)),
orderingFacility: getCellValue(row, 4),
orderingFacilityMflCode: getCellValue(row, 4),
orderingFacilityName: getCellValue(row, 5),
receivingFacility: getCellValue(row, 2),
provider: getCellValue(row, 6),
patientType: getCellValue(row, 8),
patientStatus: getCellValue(row, 7),
provider: getCellValue(row, 7),
patientType: getCellValue(row, 9),
patientStatus: getCellValue(row, 8),
xLocation: getCellValue(row, 3),
}
})
Expand Down
66 changes: 34 additions & 32 deletions src/workflows/botswana/IpmsWorkflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ import {
IDiagnosticReport,
IObservation,
IPatient,
IReference,
IServiceRequest,
ITask,
TaskStatusKind,
} from '@ahryman40k/ts-fhir-types/lib/R4'
import { saveBundle } from '../../hapi/lab'
import { hapiGet } from '../../lib/helpers'

// New Error Type for IPMS Workflow Errors
export class IpmsWorkflowError extends Error {
Expand Down Expand Up @@ -327,9 +326,15 @@ export async function handleAdtFromIpms(adtMessage: string): Promise<any> {
}
}

/**
* Handles ORU (Observation Result) messages received from IPMS (Integrated Patient Management System).
*/
export async function handleOruFromIpms(message: any): Promise<R4.IBundle> {
let translatedBundle, resultBundle: R4.IBundle = { resourceType: 'Bundle' }
let taskPatient, task;
let translatedBundle: R4.IBundle = { resourceType: 'Bundle' }
let resultBundle: R4.IBundle = { resourceType: 'Bundle' }
let serviceRequestBundle: R4.IBundle = { resourceType: 'Bundle' }

let taskPatient, task

try {
if (!message)
Expand All @@ -343,7 +348,7 @@ export async function handleOruFromIpms(message: any): Promise<R4.IBundle> {
if (translatedBundle && translatedBundle.entry) {

// Extract Patient, DiagnosticReport, and Observation
let patient: IPatient = <IPatient>(
const patient: IPatient = <IPatient>(
translatedBundle.entry.find((e: any) => e.resource && e.resource.resourceType == 'Patient')!
.resource!
)
Expand All @@ -352,7 +357,7 @@ export async function handleOruFromIpms(message: any): Promise<R4.IBundle> {
translatedBundle.entry.find((e: any) => e.resource && e.resource.resourceType == 'DiagnosticReport')!.resource!
)

let obs: IObservation = <IObservation>(
const obs: IObservation = <IObservation>(
translatedBundle.entry.find((e: any) => e.resource && e.resource.resourceType == 'Observation')!
.resource!
)
Expand All @@ -368,26 +373,24 @@ export async function handleOruFromIpms(message: any): Promise<R4.IBundle> {
*/

// Extract Lab Order ID from Diagnostic Report
const labOrderId = dr.identifier && dr.identifier.length > 0 ? dr.identifier.find((i: any) => config.get('bwConfig:labOrderSystemUrl') && i.system == config.get('bwConfig:labOrderSystemUrl').value) : undefined
const labOrderMrn = dr.identifier && dr.identifier.length > 0 ? dr.identifier.find((i: any) => config.get('bwConfig:mrnSystemUrl') && i.system == config.get('bwConfig:mrnSystemUrl').value) : undefined
const labOrderId = dr.identifier && dr.identifier.length > 0 ? dr.identifier.find((i: any) => i.system == config.get('bwConfig:labOrderSystemUrl')) : undefined
const labOrderMrn = dr.identifier && dr.identifier.length > 0 ? dr.identifier.find((i: any) => i.system == config.get('bwConfig:mrnSystemUrl')) : undefined

let options = {
timeout: config.get('bwConfig:requestTimeout'),
searchParams: {},
}

// Grab service request with Task:
options.searchParams = {
_revInclude: 'Task:basedOn',
_include: 'ServiceRequest.patient',
_id: labOrderId,
if(labOrderId && labOrderId.value) {
const options = {
timeout: config.get('bwConfig:requestTimeout'),
searchParams: new URLSearchParams(),
}

options.searchParams.append('_include','Task:patient')
options.searchParams.append('_include','Task:based-on')
options.searchParams.append('based-on',labOrderId.value)

serviceRequestBundle = <R4.IBundle> (await hapiGet('Task', options))
}

const serviceRequestBundle: IBundle = await got
.get(`${config.get('fhirServer:baseURL')}/ServiceRequest`, options)
.json()

if(serviceRequestBundle && serviceRequestBundle.entry && serviceRequestBundle.entry.length > 0) {

// Extract Task and Patient Resources from ServiceRequest Bundle
taskPatient = <IPatient>(
serviceRequestBundle.entry.find((e: any) => e.resource && e.resource.resourceType == 'Patient')!
Expand All @@ -399,14 +402,19 @@ export async function handleOruFromIpms(message: any): Promise<R4.IBundle> {
)

// TODO: Validate Patient Match by Identifier/CR match
// taskPatient.identifier == patient.identifier (for omang/brn/ppn) or make sure the two are linked in CR

} else {
logger.error('Could not find ServiceRequest with Lab Order ID ' + labOrderId + '!')
logger.error('Could not find ServiceRequest with Lab Order ID ' + JSON.stringify(labOrderId) + '!')
return new IpmsErrorBundle('Could not find ServiceRequest with Lab Order ID ' + labOrderId + '!').bundle;
}

// Update Obs and DR with Patient Reference
obs.subject = { reference: 'Patient/' + taskPatient.id }
dr.subject = { reference: 'Patient/' + taskPatient.id }

// Generate SendBundle with Task, DiagnosticReport, Patient, and Observation
let entry = createSendBundleEntry(task, patient, dr, obs)
const entry = createSendBundleEntry(task, dr, obs)

// TODO: Only send if valid details available
const sendBundle: R4.IBundle = {
Expand Down Expand Up @@ -479,21 +487,15 @@ function processIpmsPatient(patient: R4.IPatient): any {
return { omang: omang, bcn: bcn, ppn: ppn, options: options }
}

function createSendBundleEntry(task: R4.ITask | undefined, patient: R4.IPatient | undefined, dr: R4.IDiagnosticReport | undefined, obs: R4.IObservation | undefined): R4.IBundle_Entry[] {
let entry = []
function createSendBundleEntry(task: R4.ITask | undefined, dr: R4.IDiagnosticReport | undefined, obs: R4.IObservation | undefined): R4.IBundle_Entry[] {
const entry = []

if (task) {
entry.push({
resource: task,
request: { method: Bundle_RequestMethodKind._put, url: 'Task/' + task.id }
})
}
if(patient) {
entry.push({
resource: patient,
request: { method: Bundle_RequestMethodKind._put, url: 'Patient/' + patient.id },
})
}
if(dr) {
entry.push({
resource: dr,
Expand Down
16 changes: 2 additions & 14 deletions src/workflows/botswana/terminologyWorkflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export async function translateCoding(r: R4.IServiceRequest | R4.IDiagnosticRepo

logger.info(`PIMS Coding: ${JSON.stringify(pimsCoding)}`)
logger.info(`CIEL Coding: ${JSON.stringify(cielCoding)}`)

logger.info(`IPMS Coding: ${JSON.stringify(ipmsCoding)}`)

if(ipmsCoding && ipmsCoding.code) {
// 1. IPMS Resulting Workflow:
// Translation from IPMS --> PIMS and CIEL
Expand Down Expand Up @@ -128,19 +129,6 @@ export async function translateCoding(r: R4.IServiceRequest | R4.IDiagnosticRepo
}
}

// Get LOINC Coding for all Workflows
if (cielCoding && cielCoding.code) {
loincCoding = await getMappedCode(
`/orgs/CIEL/sources/CIEL/mappings/?toConceptSource=LOINC&fromConcept=${cielCoding.code}`,
)
if (loincCoding && loincCoding.code) {
r.code.coding.push({
system: config.get('bwConfig:loincSystemUrl'),
code: loincCoding.code,
display: loincCoding.display,
})
}
}
return r
} else {
logger.error('Could not any codings to translate in:\n' + JSON.stringify(r))
Expand Down

0 comments on commit 9c783fe

Please sign in to comment.