ac-fhir-models
Advanced tools
Comparing version 7.6.0 to 7.6.1
102
index.js
@@ -2141,2 +2141,87 @@ 'use strict'; | ||
const PARENT_ORG_URL_PREFIX = 'https://xchart.com/parent/'; | ||
/** | ||
* @typedef { | { type: 'Practitioner'; id: string } | ||
* | { | ||
* type: 'ParentOrgUser' | ||
* parentOrgId: string | ||
* id: string | ||
* display: string | ||
* } | ||
* | { type: 'XchartStaffUser'; id: string; display: string }} PractitionerOrExternalUser | ||
* @param {string} propName | ||
* @returns {{ | ||
* get: (data: any) => PractitionerOrExternalUser | ||
* set: (data: any, value: PractitionerOrExternalUser) => any | ||
* }} | ||
*/ | ||
const getPractitionerOrExternalUserProp = propName => ({ | ||
get: data => { | ||
if (!data[propName]) return null | ||
const { reference, display } = data[propName]; | ||
if (reference.startsWith('Practitioner/')) { | ||
return { | ||
type: 'Practitioner', | ||
id: reference.replace('Practitioner/', ''), | ||
} | ||
} | ||
if (reference.startsWith(PARENT_ORG_URL_PREFIX)) { | ||
const [parentOrgId, userType, id] = reference | ||
.replace(PARENT_ORG_URL_PREFIX, '') | ||
.split('/'); | ||
// this shouldn't be the case | ||
if (userType !== 'user') return null | ||
if (parentOrgId === 'xchart') { | ||
return { | ||
type: 'XchartStaffUser', | ||
id, | ||
display, | ||
} | ||
} | ||
return { | ||
type: 'ParentOrgUser', | ||
parentOrgId, | ||
id, | ||
display, | ||
} | ||
} | ||
}, | ||
set: (data, value) => { | ||
if (!value) { | ||
data[propName] = null; | ||
return data | ||
} | ||
if (value.type === 'Practitioner') { | ||
data[propName] = { | ||
reference: `Practitioner/${value.id}`, | ||
}; | ||
return data | ||
} | ||
if (value.type === 'ParentOrgUser') { | ||
data[propName] = { | ||
reference: `${PARENT_ORG_URL_PREFIX}${value.parentOrgId}/user/${value.id}`, | ||
}; | ||
} else if (value.type === 'XchartStaffUser') { | ||
data[propName] = { | ||
reference: `${PARENT_ORG_URL_PREFIX}xchart/user/${value.id}`, | ||
}; | ||
} | ||
if (value.display) { | ||
data[propName].display = value.display; | ||
} | ||
return data | ||
}, | ||
}); | ||
const patientCommentDefinition = createFHIRModelDefinition({ | ||
@@ -2147,6 +2232,5 @@ resourceType: 'Communication', | ||
patientId: getDirectReferenceProp('subject', 'Patient'), | ||
authorId: getDirectReferenceProp('sender', 'Practitioner'), | ||
author: getPractitionerOrExternalUserProp('sender'), | ||
date: getTimeProp('sent'), | ||
text: 'payload.[0].contentString', | ||
status: 'status', | ||
}, | ||
@@ -2159,2 +2243,3 @@ definition: sinks.buildDefinition( | ||
'sender.reference': 'str', | ||
'sender.display': 'str', | ||
sent: 'str', | ||
@@ -2168,2 +2253,5 @@ 'payload.[].contentString': 'str', | ||
'identifier.[].value': 'str', | ||
'category.[].coding.[].system': 'str', | ||
'category.[].coding.[].code': 'str', | ||
'category.[].coding.[].display': 'str', | ||
}, | ||
@@ -2174,2 +2262,12 @@ fhirFieldTypes | ||
status: 'completed', | ||
category: [ | ||
{ | ||
coding: [ | ||
{ | ||
system: 'https://ns.anesthesiacharting.com/communication-category', | ||
code: 'patient-comment', | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
@@ -2176,0 +2274,0 @@ }); |
{ | ||
"name": "ac-fhir-models", | ||
"version": "7.6.0", | ||
"version": "7.6.1", | ||
"author": "Henrik Joreteg <henrik@anesthesiacharting.com>", | ||
@@ -5,0 +5,0 @@ "dependencies": { |
@@ -11,2 +11,87 @@ // @ts-check | ||
const PARENT_ORG_URL_PREFIX = 'https://xchart.com/parent/' | ||
/** | ||
* @typedef { | { type: 'Practitioner'; id: string } | ||
* | { | ||
* type: 'ParentOrgUser' | ||
* parentOrgId: string | ||
* id: string | ||
* display: string | ||
* } | ||
* | { type: 'XchartStaffUser'; id: string; display: string }} PractitionerOrExternalUser | ||
* @param {string} propName | ||
* @returns {{ | ||
* get: (data: any) => PractitionerOrExternalUser | ||
* set: (data: any, value: PractitionerOrExternalUser) => any | ||
* }} | ||
*/ | ||
const getPractitionerOrExternalUserProp = propName => ({ | ||
get: data => { | ||
if (!data[propName]) return null | ||
const { reference, display } = data[propName] | ||
if (reference.startsWith('Practitioner/')) { | ||
return { | ||
type: 'Practitioner', | ||
id: reference.replace('Practitioner/', ''), | ||
} | ||
} | ||
if (reference.startsWith(PARENT_ORG_URL_PREFIX)) { | ||
const [parentOrgId, userType, id] = reference | ||
.replace(PARENT_ORG_URL_PREFIX, '') | ||
.split('/') | ||
// this shouldn't be the case | ||
if (userType !== 'user') return null | ||
if (parentOrgId === 'xchart') { | ||
return { | ||
type: 'XchartStaffUser', | ||
id, | ||
display, | ||
} | ||
} | ||
return { | ||
type: 'ParentOrgUser', | ||
parentOrgId, | ||
id, | ||
display, | ||
} | ||
} | ||
}, | ||
set: (data, value) => { | ||
if (!value) { | ||
data[propName] = null | ||
return data | ||
} | ||
if (value.type === 'Practitioner') { | ||
data[propName] = { | ||
reference: `Practitioner/${value.id}`, | ||
} | ||
return data | ||
} | ||
if (value.type === 'ParentOrgUser') { | ||
data[propName] = { | ||
reference: `${PARENT_ORG_URL_PREFIX}${value.parentOrgId}/user/${value.id}`, | ||
} | ||
} else if (value.type === 'XchartStaffUser') { | ||
data[propName] = { | ||
reference: `${PARENT_ORG_URL_PREFIX}xchart/user/${value.id}`, | ||
} | ||
} | ||
if (value.display) { | ||
data[propName].display = value.display | ||
} | ||
return data | ||
}, | ||
}) | ||
export const patientCommentDefinition = createFHIRModelDefinition({ | ||
@@ -17,6 +102,5 @@ resourceType: 'Communication', | ||
patientId: getDirectReferenceProp('subject', 'Patient'), | ||
authorId: getDirectReferenceProp('sender', 'Practitioner'), | ||
author: getPractitionerOrExternalUserProp('sender'), | ||
date: getTimeProp('sent'), | ||
text: 'payload.[0].contentString', | ||
status: 'status', | ||
}, | ||
@@ -29,2 +113,3 @@ definition: buildDefinition( | ||
'sender.reference': 'str', | ||
'sender.display': 'str', | ||
sent: 'str', | ||
@@ -38,2 +123,5 @@ 'payload.[].contentString': 'str', | ||
'identifier.[].value': 'str', | ||
'category.[].coding.[].system': 'str', | ||
'category.[].coding.[].code': 'str', | ||
'category.[].coding.[].display': 'str', | ||
}, | ||
@@ -44,3 +132,13 @@ fhirFieldTypes | ||
status: 'completed', | ||
category: [ | ||
{ | ||
coding: [ | ||
{ | ||
system: 'https://ns.anesthesiacharting.com/communication-category', | ||
code: 'patient-comment', | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
}) |
@@ -5,18 +5,74 @@ // @ts-check | ||
test('communicationStatus validation', t => { | ||
t.throws(() => { | ||
patientCommentDefinition.set({}, { status: 'blah' }) | ||
}, 'should error with bad status') | ||
test('patientCommentDefinition supports external author types', t => { | ||
const startProps = { | ||
patientId: '123', | ||
date: new Date().toISOString(), | ||
text: 'Hello', | ||
} | ||
t.doesNotThrow(() => { | ||
patientCommentDefinition.set({}, { status: 'preparation' }) | ||
patientCommentDefinition.set({}, { status: 'in-progress' }) | ||
patientCommentDefinition.set({}, { status: 'not-done' }) | ||
patientCommentDefinition.set({}, { status: 'on-hold' }) | ||
patientCommentDefinition.set({}, { status: 'stopped' }) | ||
patientCommentDefinition.set({}, { status: 'completed' }) | ||
patientCommentDefinition.set({}, { status: 'entered-in-error' }) | ||
patientCommentDefinition.set({}, { status: 'unknown' }) | ||
}, 'should not error with allowed criticalities') | ||
t.test('handles normal practitioner reference', t => { | ||
const comment = { | ||
...startProps, | ||
author: { type: 'Practitioner', id: '456' }, | ||
} | ||
const resource = patientCommentDefinition.create(comment) | ||
t.deepEqual(resource.sender, { | ||
reference: 'Practitioner/456', | ||
}) | ||
const values = patientCommentDefinition.getValues(resource) | ||
t.deepEqual(values.author, comment.author) | ||
t.end() | ||
}) | ||
t.test('handles a parent org commenter', t => { | ||
const comment = { | ||
...startProps, | ||
author: { | ||
type: 'ParentOrgUser', | ||
parentOrgId: 'foobar', | ||
id: 'user_xyz', | ||
display: 'John Doe', | ||
}, | ||
} | ||
const resource = patientCommentDefinition.create(comment) | ||
t.deepEqual(resource.sender, { | ||
reference: 'https://xchart.com/parent/foobar/user/user_xyz', | ||
display: 'John Doe', | ||
}) | ||
const values = patientCommentDefinition.getValues(resource) | ||
t.deepEqual(values.author, comment.author) | ||
t.end() | ||
}) | ||
t.test('handles an xchart staff commenter', t => { | ||
const comment = { | ||
...startProps, | ||
author: { | ||
type: 'XchartStaffUser', | ||
id: 'user_xyz', | ||
display: 'Henrik Joreteg', | ||
}, | ||
} | ||
const resource = patientCommentDefinition.create(comment) | ||
t.deepEqual(resource.sender, { | ||
reference: 'https://xchart.com/parent/xchart/user/user_xyz', | ||
display: 'Henrik Joreteg', | ||
}) | ||
const values = patientCommentDefinition.getValues(resource) | ||
t.deepEqual(values.author, comment.author) | ||
t.end() | ||
}) | ||
t.end() | ||
@@ -30,3 +86,3 @@ }) | ||
patientId: '123', | ||
authorId: '456', | ||
author: { type: 'Practitioner', id: '456' }, | ||
date: dateTime, | ||
@@ -44,10 +100,18 @@ text: 'Hello', | ||
payload: [{ contentString: 'Hello' }], | ||
category: [ | ||
{ | ||
coding: [ | ||
{ | ||
system: 'https://ns.anesthesiacharting.com/communication-category', | ||
code: 'patient-comment', | ||
}, | ||
], | ||
}, | ||
], | ||
status: 'completed', | ||
}) | ||
t.deepEqual(patientCommentDefinition.getValues(resource), { | ||
...startProps, | ||
status: 'completed', | ||
}) | ||
t.deepEqual(patientCommentDefinition.getValues(resource), startProps) | ||
t.end() | ||
}) |
197343
6872