You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3540 lines
111 KiB

/**
* @package OpenEMR CCDAServer
* @link http://www.open-emr.org
*
* @author Jerry Padgett <sjpadgett@gmail.com>
* @copyright Copyright (c) 2016-2022 Jerry Padgett <sjpadgett@gmail.com>
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/
"use strict";
const enableDebug = true;
const net = require('net');
const server = net.createServer();
const to_json = require('xmljson').to_json;
const bbg = require(__dirname + '/oe-blue-button-generate');
const fs = require('fs');
var conn = ''; // make our connection scope global to script
var oidFacility = "";
var all = "";
var npiProvider = "";
var npiFacility = "";
var webRoot = "";
var authorDateTime = '';
var documentLocation = '';
class DataStack {
constructor(delimiter) {
this.delimiter = delimiter;
this.buffer = "";
}
endOfCcda() {
return this.buffer.length === 0 || this.buffer.indexOf(this.delimiter) === -1;
}
pushToStack(data) {
this.buffer += data;
}
fetchBuffer() {
const delimiterIndex = this.buffer.indexOf(this.delimiter);
if (delimiterIndex !== -1) {
const bufferMsg = this.buffer.slice(0, delimiterIndex);
this.buffer = this.buffer.replace(bufferMsg + this.delimiter, "");
return bufferMsg;
}
return null
}
returnData() {
return this.fetchBuffer();
}
clearStack() {
this.buffer = "";
}
readStackByDelimiter(delimiter) {
let backup = this.delimiter;
let part = '';
this.delimiter = delimiter;
part = this.fetchBuffer();
this.delimiter = backup;
return part;
}
}
function trim(s) {
if (typeof s === 'string') return s.trim();
return s;
}
function cleanText(s) {
if (typeof s === 'string') {
//s = s.replace(new RegExp('\r?\n','g'), '<br />');
return s.trim();
}
return s;
}
// do a recursive descent transformation of the node object populating the timezone offset value if we have
// a precision property (inside a date) with the value of timezone.
function populateTimezones(node, tzOffset, depthCheck) {
if (!node || typeof node !== 'object') {
return node;
}
// we should NEVER go farther than 25 recursive loops down in our heirarchy, if we do it means we have an infinite loop
if (depthCheck > 25) {
console.error("Max depth traversal reached. Potential infinite loop. Breaking out of loop")
return node;
}
if (node.hasOwnProperty('precision') && node.precision == 'tz' && !node.hasOwnProperty('timezoneOffset')) {
node.timezoneOffset = tzOffset;
} else {
for (const [key, value] of Object.entries(node)) {
node[key] = populateTimezones(value, tzOffset, depthCheck + 1);
}
}
return node;
}
function fDate(str, lim8 = false) {
str = String(str);
if (lim8) {
let rtn = str.substring(0, 8);
return rtn;
}
if (Number(str) === 0) {
return (new Date()).toISOString();
}
if (str.length === 1 || str === "0000-00-00") return (new Date()).toISOString();
if (str.length === 8 || (str.length === 14 && (1 * str.substring(12, 14)) === 0)) {
return [str.slice(0, 4), str.slice(4, 6), str.slice(6, 8)].join('-');
} else if (str.length === 10 && (1 * str.substring(0, 2)) <= 12) {
// case mm/dd/yyyy or mm-dd-yyyy
return [str.slice(6, 10), str.slice(0, 2), str.slice(3, 5)].join('-');
} else if (str.length === 17) {
str = str.split(' ');
str = [str[0].slice(0, 4), str[0].slice(4, 6), str[0].slice(6, 8)].join('-') + ' ' + str[1];
return str;
} else if (str.length === 19 && (str.substring(14, 15)) == '-') {
let strZone = str.split('-');
let strDate = [strZone[0].substring(0, 4), strZone[0].substring(4, 6), strZone[0].substring(6, 8)].join('-');
let strTime = [str.substring(8, 10), str.substring(10, 12), str.substring(12, 14)].join(':');
let str1 = strDate + ' ' + strTime + '-' + strZone[1];
return str1;
} else {
return str;
}
return str;
}
function getPrecision(str) {
str = String(str);
let pflg = "day";
if (Number(str) === 0) {
return "day";
}
if (str.length > 8) {
pflg = "day";
}
if (str.length > 12) {
pflg = "second";
}
if (str.length > 23) {
pflg = "tz";
}
return pflg;
}
function templateDate(date, precision) {
return {'date': fDate(date), 'precision': precision}
}
function cleanCode(code) {
if (typeof code === 'undefined') {
return "null_flavor";
}
if (code.length < 2) {
code = "null_flavor";
return code;
}
return code.replace(/[.#]/, "");
}
function isOne(who) {
try {
if (who !== null && typeof who === 'object') {
return (who.hasOwnProperty('npi')
|| who.hasOwnProperty('code')
|| who.hasOwnProperty('extension')
|| who.hasOwnProperty('id')
|| who.hasOwnProperty('date')
|| who.hasOwnProperty('use')
|| who.hasOwnProperty('type')
) ? 1 : Object.keys(who).length;
}
} catch (e) {
return false;
}
return 0;
}
function headReplace(content, xslUrl = "") {
let xsl = "CDA.xsl";
if (typeof xslUrl == "string" && xslUrl.trim() != "") {
xsl = xslUrl;
}
let r = '<?xml version="1.0" encoding="UTF-8"?>' + "\n" +
'<?xml-stylesheet type="text/xsl" href="' + xsl + '"?>';
r += "\n" + content.substring(content.search(/<ClinicalDocument/i));
return r;
}
function fetchPreviousAddresses(pd) {
let addressArray = [];
let pa = pd.previous_addresses.address;
let streetLine = [pd.street[0]];
if (pd.street[1].length > 0) {
streetLine = [pd.street[0], pd.street[1]];
}
addressArray.push({
"use": "HP",
"street_lines": streetLine,
"city": pd.city,
"state": pd.state,
"zip": pd.postalCode,
"country": pd.country || "US",
"date_time": {
// use current date for current residence
"low": {
"date": fDate(""),
"precision": "day"
}
}
});
let count = isOne(pa);
// how do we ever get here where we just have one object?
if (count === 1) {
streetLine = [pa.street[0]];
if (pa.street[1].length > 0) {
streetLine = [pa.street[0], pa.street[1]];
}
addressArray.push({
"use": pa.use,
"street_lines": streetLine,
"city": pa.city,
"state": pa.state,
"zip": pa.postalCode,
"country": pa.country || "US",
"date_time": {
"low": {
"date": fDate(pa.period_start),
"precision": "day"
},
"high": {
"date": fDate(pa.period_end) || fDate(""),
"precision": "day"
}
}
});
} else if (count > 1) {
for (let i in pa) {
streetLine = [pa[i].street[0]];
if (pa[i].street[1].length > 0) {
streetLine = [pa[i].street[0], pa[i].street[1]];
}
addressArray.push({
"use": pa[i].use,
"street_lines": streetLine,
"city": pa[i].city,
"state": pa[i].state,
"zip": pa[i].postalCode,
"country": pa[i].country || "US",
"date_time": {
"low": {
"date": fDate(pa[i].period_start),
"precision": "day"
},
"high": {
"date": fDate(pa[i].period_end) || fDate(""),
"precision": "day"
}
}
});
}
}
return addressArray;
}
function populateDemographic(pd, g) {
let guardian = [{
"relation": g.relation,
"addresses": [{
"street_lines": [g.address],
"city": g.city,
"state": g.state,
"zip": g.postalCode,
"country": g.country || "US",
"use": "primary home"
}],
"names": [{
"last": g.display_name, //@todo parse first/last
"first": g.display_name
}],
"phone": [{
"number": g.telecom,
"type": "primary home"
}]
}];
if (pd.race === 'Declined To Specify' || pd.race === '') {
pd.race = "null_flavor";
}
if (pd.race_group === 'Declined To Specify' || pd.race_group === '') {
pd.race_group = "null_flavor";
}
if (pd.ethnicity === 'Declined To Specify' || pd.ethnicity === '') {
pd.ethnicity = "null_flavor";
}
let addressArray = fetchPreviousAddresses(pd);
return {
"name": {
"prefix": pd.prefix,
"suffix": pd.suffix,
"middle": [pd.mname] || "",
"last": pd.lname,
"first": pd.fname
},
"birth_name": {
"middle": pd.birth_mname || "",
"last": pd.birth_lname || "",
"first": pd.birth_fname || ""
},
"dob": {
"point": {
"date": fDate(pd.dob),
"precision": "day"
}
},
"gender": pd.gender.toUpperCase() || "null_flavor",
"identifiers": [{
"identifier": oidFacility,
"extension": "PT-" + pd.id
}],
"marital_status": pd.status.toUpperCase(),
"addresses": addressArray,
"phone": [
{
"number": pd.phone_home,
"type": "primary home"
}, {
"number": pd.phone_mobile,
"type": "primary mobile"
}, {
"email": pd.email,
"type": "contact_email"
}
],
"ethnicity": pd.ethnicity || "",
"race": pd.race || "null_flavor",
"race_additional": pd.race_group || "null_flavor",
"languages": [{
"language": pd.language === 'English' ? "en-US" : pd.language === 'Spanish' ? "sp-US" : 'en-US',
"preferred": true,
"mode": "Expressed spoken",
"proficiency": "Good"
}],
//"religion": pd.religion.toUpperCase() || "",
/*"birthplace":'', {
"city": "",
"state": "",
"zip": "",
"country": ""
},*/
"attributed_provider": {
"identity": [
{
"root": "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"phone": [{
"number": all.encounter_provider.facility_phone || "",
}],
"name": [
{
"full": all.encounter_provider.facility_name || ""
}
],
"address": [
{
"street_lines": [
all.encounter_provider.facility_street
],
"city": all.encounter_provider.facility_city,
"state": all.encounter_provider.facility_state,
"zip": all.encounter_provider.facility_postal_code,
"country": all.encounter_provider.facility_country_code || "US",
"use": "work place"
}
],
},
//"guardians": g.display_name ? guardian : '' //not required
}
}
function populateProvider(provider) {
// The provider role is a maybe and will only be provided for physicians as a
// primary care role. All other team members will id via taxonomy only and if not physicians.
return {
"function_code": provider.physician_type ? "PP" : "",
"date_time": {
"low": {
"date": provider.provider_since ? fDate(provider.provider_since) : fDate(""),
"precision": "tz"
}
},
"identity": [
{
"root": provider.npi ? "2.16.840.1.113883.4.6" : oidFacility,
"extension": provider.npi || provider.table_id || ""
}
],
"type": [
{
"name": provider.taxonomy_description || "",
"code": cleanCode(provider.taxonomy) || "",
"code_system": "2.16.840.1.113883.6.101",
"code_system_name": "NUCC Health Care Provider Taxonomy"
}
],
"name": [
{
"last": provider.lname || "",
"first": provider.fname || ""
}
],
"address": [
{
"street_lines": [
all.encounter_provider.facility_street
],
"city": all.encounter_provider.facility_city,
"state": all.encounter_provider.facility_state,
"zip": all.encounter_provider.facility_postal_code,
"country": all.encounter_provider.facility_country_code || "US"
}
],
"phone": [{
"number": all.encounter_provider.facility_phone || ""
}]
}
}
function populateProviders(all) {
let providerArray = [];
// primary provider
let provider = populateProvider(all.primary_care_provider.provider);
providerArray.push(provider);
let count = isOne(all.care_team.provider);
if (count === 1) {
provider = populateProvider(all.care_team.provider);
providerArray.push(provider);
} else if (count > 1) {
for (let i in all.care_team.provider) {
provider = populateProvider(all.care_team.provider[i]);
providerArray.push(provider);
}
}
return {
"providers":
{
"date_time": {
"low": {
"date": fDate(all.time_start) || fDate(""),
"precision": "tz"
},
"high": {
"date": fDate(all.time_end) || fDate(""),
"precision": "tz"
}
},
"code": {
"name": all.primary_diagnosis.text || "",
"code": cleanCode(all.primary_diagnosis.code || ""),
"code_system_name": all.primary_diagnosis.code_type || ""
},
"provider": providerArray,
}
}
}
function populateCareTeamMember(provider) {
return {
//"function_code": provider.physician_type ? "PP" : "",
"function_code": {
"xmlns": "urn:hl7-org:sdtc",
"name": provider.taxonomy_description || "",
"code": cleanCode(provider.taxonomy) || "",
"code_system": "2.16.840.1.113883.6.101",
"code_system_name": "NUCC Health Care Provider Taxonomy"
},
"status": "active",
"date_time": {
"low": {
"date": fDate(provider.provider_since) || fDate(""),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": provider.npi ? "2.16.840.1.113883.4.6" : oidFacility,
"extension": provider.npi || provider.table_id
}
],
"full_name": provider.fname + " " + provider.lname,
"name": {
"last": provider.lname || "",
"first": provider.fname || ""
},
"address": {
"street_lines": [
provider.street
],
"city": provider.city,
"state": provider.state,
"zip": provider.zip,
"country": all.encounter_provider.facility_country_code || "US"
},
"phone": [
{
"number": provider.telecom,
"type": "work place"
}
]
}
}
function populateAuthorFromAuthorContainer(pd) {
let author = pd.author || {};
return {
"code": {
"name": author.physician_type || '',
"code": author.physician_type_code || '',
"code_system": author.physician_type_system,
"code_system_name": author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": author.npi ? "2.16.840.1.113883.4.6" : author.id,
"extension": author.npi ? author.npi : ''
}
],
"name": [
{
"last": author.lname || "",
"first": author.fname || ""
}
],
"organization": [
{
"identity": [
{
"root": author.facility_oid || "2.16.840.1.113883.4.6",
"extension": author.facility_npi || ""
}
],
"name": [
author.facility_name || ""
]
}
]
};
}
function populateCareTeamMembers(pd) {
let providerArray = [];
// primary provider
let primaryCareProvider = pd.primary_care_provider || {provider: {}};
let providerSince = fDate(primaryCareProvider.provider.provider_since || '');
if (pd.primary_care_provider) {
let provider = populateCareTeamMember(pd.primary_care_provider.provider);
providerArray.push(provider);
let count = isOne(pd.care_team.provider);
if (count === 1) {
provider = populateCareTeamMember(pd.care_team.provider);
providerSince = providerSince || fDate(provider.provider_since);
providerArray.push(provider);
} else if (count > 1) {
for (let i in pd.care_team.provider) {
provider = populateCareTeamMember(pd.care_team.provider[i]);
providerSince = providerSince || fDate(provider.provider_since);
providerArray.push(provider);
}
}
}
return {
"providers":
{
"provider": providerArray,
},
"status": "active",
"date_time": {
"low": {
"date": providerSince || fDate(""),
"precision": "tz"
}
},
// we treat this author a bit differently since we are working at the main pd object instead of the sub pd.care_team
"author": populateAuthorFromAuthorContainer(pd.care_team)
}
}
function populateMedication(pd) {
pd.status = 'Completed'; //@todo invoke prescribed
return {
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "tz"
}/*,
"high": {
"date": fDate(pd.end_date),
"precision": "day"
}*/
},
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension || ""
}],
"status": pd.status,
"sig": pd.direction,
"product": {
"identifiers": [{
"identifier": pd.sha_extension || "2a620155-9d11-439e-92b3-5d9815ff4ee8",
"extension": pd.extension + 1 || ""
}],
"unencoded_name": pd.drug,
"product": {
"name": pd.drug,
"code": cleanCode(pd.rxnorm),
"code_system_name": "RXNORM"
/*"translations": [{
"name": pd.drug,
"code": pd.rxnorm,
"code_system_name": "RXNORM"
}],*/
},
//"manufacturer": ""
},
"author": {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
},
"supply": {
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "day"
},
"high": {
"date": fDate(pd.end_date),
"precision": "day"
}
},
"repeatNumber": "0",
"quantity": "0",
"product": {
"identifiers": [{
"identifier": pd.sha_extension || "2a620155-9d11-439e-92b3-5d9815ff4ee8",
"extension": pd.extension + 1 || ""
}],
"unencoded_name": pd.drug,
"product": {
"name": pd.drug,
"code": cleanCode(pd.rxnorm),
/*"translations": [{
"name": pd.drug,
"code": pd.rxnorm,
"code_system_name": "RXNORM"
}],*/
"code_system_name": "RXNORM"
},
//"manufacturer": ""
},
"author": {
"code": {
"name": all.author.physician_type || '',
"code": all.author.physician_type_code || '',
"code_system": all.author.physician_type_system, "code_system_name": all.author.physician_type_system_name
},
"date_time": {
"point": {
"date": authorDateTime,
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.author.npi ? "2.16.840.1.113883.4.6" : all.author.id,
"extension": all.author.npi ? all.author.npi : ''
}
],
"name": [
{
"last": all.author.lname,
"first": all.author.fname
}
],
"organization": [
{
"identity": [
{
"root": oidFacility || "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
all.encounter_provider.facility_name
]
}
]
},
"instructions": {
"code": {
"name": "instruction",
"code": "409073007",
"code_system_name": "SNOMED CT"
},
"free_text": pd.instructions || "No Instructions"
},
},
"administration": {
"route": {
"name": pd.route || "",
"code": cleanCode(pd.route_code) || "",
"code_system_name": "Medication Route FDA"
},
"form": {
"name": pd.form,
"code": cleanCode(pd.form_code),
"code_system_name": "Medication Route FDA"
},
"dose": {
"value": parseFloat(pd.size),
"unit": pd.unit,
},
/*"rate": {
"value": parseFloat(pd.dosage),
"unit": ""
},*/
"interval": {
"period": {
"value": parseFloat(pd.dosage),
"unit": pd.interval
},
"frequency": true
}
},
"performer": {
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": pd.npi || ""
}],
"organization": [{
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension || ""
}],
"name": [pd.performer_name]
}]
},
"drug_vehicle": {
"name": pd.form,
"code": cleanCode(pd.form_code),
"code_system_name": "RXNORM"
},
/*"precondition": {
"code": {
"code": "ASSERTION",
"code_system_name": "ActCode"
},
"value": {
"name": "none",
"code": "none",
"code_system_name": "SNOMED CT"
}
},
"indication": {
"identifiers": [{
"identifier": "db734647-fc99-424c-a864-7e3cda82e703",
"extension": "45665"
}],
"code": {
"name": "Finding",
"code": "404684003",
"code_system_name": "SNOMED CT"
},
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "day"
}
},
"value": {
"name": pd.indications,
"code": pd.indications_code,
"code_system_name": "SNOMED CT"
}
},
"dispense": {
"identifiers": [{
"identifier": "1.2.3.4.56789.1",
"extension": "cb734647-fc99-424c-a864-7e3cda82e704"
}],
"performer": {
"identifiers": [{
"identifier": "2.16.840.1.113883.19.5.9999.456",
"extension": "2981823"
}],
"address": [{
"street_lines": [pd.address],
"city": pd.city,
"state": pd.state,
"zip": pd.zip,
"country": "US"
}],
"organization": [{
"identifiers": [{
"identifier": "2.16.840.1.113883.19.5.9999.1393"
}],
"name": [pd.performer_name]
}]
},
"product": {
"identifiers": [{
"identifier": "2a620155-9d11-439e-92b3-5d9815ff4ee8"
}],
"unencoded_name": pd.drug,
"product": {
"name": pd.drug,
"code": pd.rxnorm,
"translations": [{
"name": pd.drug,
"code": pd.rxnorm,
"code_system_name": "RXNORM"
}],
"code_system_name": "RXNORM"
},
"manufacturer": ""
}
}*/
};
}
function populateEncounter(pd) {
let name = '';
let code = '';
let code_system_name = "";
let status = "Active";
// just to get diagnosis. for findings..
if (typeof pd.encounter_diagnosis !== 'undefined') {
name = pd.encounter_diagnosis.text;
code = cleanCode(pd.encounter_diagnosis.code);
code_system_name = pd.encounter_diagnosis.code_type;
status = pd.encounter_diagnosis.status;
}
return {
"encounter": {
"name": pd.visit_category ? pd.visit_category : 'UNK',
"code": "185347001",
"code_system": "2.16.840.1.113883.6.96",
"code_system_name": "SNOMED CT",
"translations": [{
"name": "Ambulatory",
"code": "AMB",
"code_system_name": "ActCode"
}]
},
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension
}],
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "tz"
}
},
"performers": [{
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": pd.npi || ""
}],
"code": [{
"name": pd.physician_type,
"code": cleanCode(pd.physician_type_code),
"code_system_name": pd.physician_code_type
}],
"name": [
{
"last": pd.lname || "",
"first": pd.fname || ""
}
],
"phone": [
{
"number": pd.work_phone,
"type": "work place"
}
]
}],
"locations": [{
"name": pd.location,
"location_type": {
"name": pd.location_details,
"code": "1160-1",
"code_system_name": "HealthcareServiceLocation"
},
"address": [{
"street_lines": [pd.facility_address],
"city": pd.facility_city,
"state": pd.facility_state,
"zip": pd.facility_zip,
"country": pd.facility_country || "US"
}],
"phone": [
{
"number": pd.facility_phone,
"type": "work place"
}
]
}],
"findings": [{
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension
}],
"value": {
"name": name,
"code": cleanCode(code),
"code_system_name": code_system_name
},
"date_time": {
"low": {
"date": fDate(pd.date),
"precision": "day"
}
},
"status": status,
"reason": pd.encounter_reason,
"author": {
"code": {
"name": all.author.physician_type || '',
"code": all.author.physician_type_code || '',
"code_system": all.author.physician_type_system, "code_system_name": all.author.physician_type_system_name
},
"date_time": {
"point": {
"date": authorDateTime,
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.author.npi ? "2.16.840.1.113883.4.6" : all.author.id,
"extension": all.author.npi ? all.author.npi : ''
}
],
"name": [
{
"last": all.author.lname,
"first": all.author.fname
}
],
"organization": [
{
"identity": [
{
"root": oidFacility || "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
all.encounter_provider.facility_name
]
}
]
},
}]
};
}
function populateAllergy(pd) {
if (!pd) {
return {
"no_know_allergies": "No Known Allergies",
"date_time": {
"low": templateDate("", "day"),
//"high": templateDate(pd.enddate, "day")
}
}
}
let allergyAuthor = {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
};
return {
"identifiers": [{
"identifier": pd.sha_id,
"extension": pd.id || ""
}],
"date_time": {
"low": templateDate(pd.startdate, "day"),
//"high": templateDate(pd.enddate, "day")
},
"author": allergyAuthor,
"observation": {
"identifiers": [{
"identifier": pd.sha_extension || "2a620155-9d11-439e-92b3-5d9815ff4ee8",
"extension": pd.id + 1 || ""
}],
"author": allergyAuthor,
"allergen": {
"name": pd.title || "",
"code": pd.rxnorm_code_text ? cleanCode(pd.rxnorm_code) : pd.snomed_code_text ? cleanCode(pd.snomed_code) : cleanCode(""),
"code_system_name": pd.rxnorm_code_text ? "RXNORM" : pd.snomed_code_text ? "SNOMED CT" : ""
},
"date_time": {
"low": {
"date": fDate(pd.startdate) || fDate(""),
"precision": "day"
}
},
"intolerance": {
"name": "Propensity to adverse reactions to drug",
"code": "420134006",
"code_system_name": "SNOMED CT"
},
"severity": {
"code": {
"name": pd.outcome || "",
"code": cleanCode(pd.outcome_code) || "",
"code_system_name": "SNOMED CT"
}
},
"status": {
"name": pd.status_table || "",
"code": cleanCode(pd.status_code),
"code_system_name": "SNOMED CT"
},
"reactions": [{
"identifiers": [{
"identifier": "4adc1020-7b14-11db-9fe1-0800200c9a64"
}],
"date_time": {
"low": templateDate(pd.startdate, "day"),
"high": templateDate(pd.enddate, "day")
},
"reaction": {
"name": pd.reaction_text,
"code": cleanCode(pd.reaction_code) || "",
"code_system_name": pd.reaction_code_type || "SNOMED CT"
},
"severity": {
"code": {
"name": pd.outcome || "",
"code": cleanCode(pd.outcome_code),
"code_system_name": "SNOMED CT"
}
}
}]
}
}
}
function populateProblem(pd) {
let primary_care_provider = all.primary_care_provider || {provider: {}};
return {
"date_time": {
"low": {
"date": fDate(pd.start_date_table),
"precision": "day"
},
/*"high": {
"date": fDate(pd.end_date),
"precision": "day"
}*/
},
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension || ""
}],
"translations": [{
"name": "Condition",
"code": "75323-6",
"code_system_name": "LOINC"
}],
"problem": {
"code": {
"name": trim(pd.title),
"code": cleanCode(pd.code),
"code_system_name": trim(pd.code_type)
},
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "day"
},
/*"high": {
"date": fDate(pd.end_date),
"precision": getPrecision()
}*/
}
},
"author": {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
},
"performer": [
{
"identifiers": [
{
"identifier": "2.16.840.1.113883.4.6",
"extension": primary_care_provider.provider.npi || ""
}
],
"name": [
{
"last": primary_care_provider.provider.lname || "",
"first": primary_care_provider.provider.fname || ""
}
]
}],
"onset_age": pd.age,
"onset_age_unit": "Year",
"status": {
"name": pd.status_table,
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "day"
},
/*"high": {
"date": fDate(pd.end_date),
"precision": getPrecision()
}*/
}
},
"patient_status": pd.observation,
"source_list_identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension || ""
}]
};
}
function populateProcedure(pd) {
return {
"procedure": {
"name": pd.description,
"code": cleanCode(pd.code),
//"code_system": "2.16.840.1.113883.6.12",
"code_system_name": "SNOMED CT"
},
"identifiers": [{
"identifier": "d68b7e32-7810-4f5b-9cc2-acd54b0fd85d",
"extension": pd.extension
}],
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "day"
}
},
/*"body_sites": [{
"name": "",
"code": "",
"code_system_name": ""
}],
"specimen": {
"identifiers": [{
"identifier": "c2ee9ee9-ae31-4628-a919-fec1cbb58683"
}],
"code": {
"name": "",
"code": "",
"code_system_name": "SNOMED CT"
}
},*/
"performers": [{
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": pd.npi || ""
}],
"address": [{
"street_lines": [pd.address],
"city": pd.city,
"state": pd.state,
"zip": pd.zip,
"country": "US"
}],
"phone": [{
"number": pd.work_phone,
"type": "work place"
}],
"organization": [{
"identifiers": [{
"identifier": pd.facility_sha_extension,
"extension": pd.facility_extension
}],
"name": [pd.facility_name],
"address": [{
"street_lines": [pd.facility_address],
"city": pd.facility_city,
"state": pd.facility_state,
"zip": pd.facility_zip,
"country": pd.facility_country || "US"
}],
"phone": [{
"number": pd.facility_phone,
"type": "work place"
}]
}]
}],
"author": populateAuthorFromAuthorContainer(pd),
"procedure_type": "procedure"
};
}
function populateMedicalDevice(pd) {
return {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension
}],
"date_time": {
"low": {
"date": fDate(pd.start_date),
"precision": "day"
}/*,
"high": {
"date": fDate(pd.end_date),
"precision": "day"
}*/
},
"device_type": "UDI",
"device": {
"name": pd.code_text,
"code": cleanCode(pd.code),
"code_system_name": "SNOMED CT",
"identifiers": [{
"identifier": "2.16.840.1.113883.3.3719",
"extension": pd.udi
}],
"status": "completed",
"body_sites": [{
"name": "",
"code": "",
"code_system_name": ""
}],
"udi": pd.udi
},
"author": {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
}
}
}
function populateResult(pd) {
let icode = pd.subtest.abnormal_flag;
let value = parseFloat(pd.subtest.result_value) || pd.subtest.result_value || "";
let type = isNaN(value) ? "ST" : "PQ";
type = !pd.subtest.unit ? "ST" : type;
value += "";
let range_type = pd.subtest.range.toUpperCase() == "NEGATIVE" ? "CO" : type;
type = value.toUpperCase() == "NEGATIVE" ? "CO" : type;
switch (pd.subtest.abnormal_flag.toUpperCase()) {
case "NO":
icode = "Normal";
break;
case "YES":
icode = "Abnormal";
break;
case "":
icode = "";
break;
}
let result = {
"identifiers": [{
"identifier": pd.subtest.root,
"extension": pd.subtest.extension
}],
"result": {
"name": pd.title,
"code": cleanCode(pd.subtest.result_code) || "",
"code_system_name": "LOINC"
},
"date_time": {
"point": {
"date": fDate(pd.date_ordered),
"precision": "day"
}
},
"status": pd.order_status,
"reference_range": {
"low": pd.subtest.low,
"high": pd.subtest.high,
"unit": pd.subtest.unit,
"type": type,
"range_type": range_type
},
"value": value + "",
"unit": pd.subtest.unit,
"type": type,
"range": pd.subtest.range,
"range_type": range_type
};
// interpretation cannot be an empty value so we skip it if it is
// empty as Observation.interpretationCode is [0..*]
if (icode !== "") {
result["interpretations"] = [icode];
}
return result;
}
function getResultSet(results) {
if (!results) return '';
// not sure if the result set should be grouped better on the backend as the author information needs to be more nuanced here
let tResult = results.result[0] || results.result;
var resultSet = {
"identifiers": [{
"identifier": tResult.root,
"extension": tResult.extension
}],
"author": populateAuthorFromAuthorContainer(tResult),
"result_set": {
"name": tResult.test_name,
"code": cleanCode(tResult.test_code),
"code_system_name": "LOINC"
}
};
var rs = [];
var many = [];
var theone = {};
var count = 0;
many.results = [];
try {
count = isOne(results.result);
} catch (e) {
count = 0;
}
if (count > 1) {
for (let i in results.result) {
theone[i] = populateResult(results.result[i]);
many.results.push(theone[i]);
}
} else if (count !== 0) {
theone = populateResult(results.result);
many.results.push(theone);
}
rs.results = Object.assign(resultSet);
rs.results.results = Object.assign(many.results);
return rs;
}
function getPlanOfCare(pd) {
let name = '';
let code = '';
let code_system_name = "";
let status = "Active";
let one = true;
let encounter;
let planType = "observation";
switch (pd.care_plan_type) {
case 'plan_of_care':
planType = "observation"; // mood code INT. sets code in template
break;
case 'test_or_order':
planType = "observation"; // mood code RQO
break;
case 'procedure':
planType = "procedure";
break;
case 'appointments':
planType = "encounter";
break;
case 'instructions':
planType = "instructions";
break;
case 'referral':
planType = ""; // for now exclude. unsure how to template.
break;
default:
planType = "observation";
}
if (pd.code_type === 'RXCUI') {
pd.code_type = 'RXNORM';
}
if (pd.code_type === 'RXNORM') {
planType = "substanceAdministration";
}
if (planType === "") {
return false;
}
for (let key in all.encounter_list.encounter) {
// skip loop if the property is from prototype
if (!all.encounter_list.encounter.hasOwnProperty(key)) {
continue;
}
encounter = all.encounter_list.encounter[key];
if (pd.encounter == encounter.encounter_id) {
one = false;
name = encounter.encounter_diagnosis.text;
code = cleanCode(encounter.encounter_diagnosis.code);
code_system_name = encounter.encounter_diagnosis.code_type;
status = encounter.encounter_diagnosis.status;
encounter = all.encounter_list.encounter[key]; // to be sure.
break;
}
}
if (one) {
let value = "";
if (all.encounter_list && all.encounter_list.encounter && all.encounter_list.encounter.encounter_diagnosis) {
value = all.encounter_list.encounter.encounter_diagnosis;
}
name = value.text;
code = cleanCode(value.code);
code_system_name = value.code_type;
status = value.status;
encounter = all.encounter_list.encounter;
}
return {
"plan": {
"name": pd.code_text || "",
"code": cleanCode(pd.code) || "",
"code_system_name": pd.code_type || "SNOMED CT"
},
"identifiers": [{
"identifier": pd.sha_extension
}],
"goal": {
"code": cleanCode(pd.code) || "",
"name": cleanText(pd.description) || ""
},
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "day"
}
},
"type": planType,
"status": {
"code": cleanCode(pd.status)
},
"author": populateAuthorFromAuthorContainer(pd),
"performers": [{
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": encounter.npi || ""
}],
"code": [{
"name": encounter.physician_type,
"code": cleanCode(encounter.physician_type_code),
"code_system_name": "SNOMED CT"
}],
"name": [
{
"last": encounter.lname || "",
"first": encounter.fname || ""
}
],
"phone": [
{
"number": encounter.work_phone,
"type": "work place"
}
]
}],
"locations": [{
"name": encounter.location,
"location_type": {
"name": encounter.location_details,
"code": "1160-1",
"code_system_name": "HealthcareServiceLocation"
},
"address": [{
"street_lines": [encounter.facility_address],
"city": encounter.facility_city,
"state": encounter.facility_state,
"zip": encounter.facility_zip,
"country": encounter.facility_country || "US"
}],
"phone": [
{
"number": encounter.facility_phone,
"type": "work place"
}
]
}],
"findings": [{
"identifiers": [{
"identifier": encounter.sha_extension,
"extension": encounter.extension
}],
"value": {
"name": name,
"code": code,
"code_system_name": code_system_name
},
"date_time": {
"low": {
"date": fDate(encounter.date),
"precision": "day"
}
},
"status": status,
"reason": encounter.encounter_reason
}],
"name": cleanText(pd.description),
"mood_code": pd.moodCode
};
}
function getGoals(pd) {
return {
"goal_code": {
"name": pd.code_text !== "NULL" ? pd.code_text : "",
"code": cleanCode(pd.code) || "",
"code_system_name": pd.code_type || ""
},
"identifiers": [{
"identifier": pd.sha_extension
}],
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "day"
}
},
"type": "observation",
"status": {
"code": "active", //cleanCode(pd.status)
},
"author": populateAuthorFromAuthorContainer(pd),
"name": pd.description
};
}
function getFunctionalStatus(pd) {
let functionalStatusAuthor = {
"code": {
"name": all.author.physician_type || '',
"code": all.author.physician_type_code || '',
"code_system": all.author.physician_type_system, "code_system_name": all.author.physician_type_system_name
},
"date_time": {
"point": {
"date": authorDateTime,
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.author.npi ? "2.16.840.1.113883.4.6" : all.author.id,
"extension": all.author.npi ? all.author.npi : ''
}
],
"name": [
{
"last": all.author.lname,
"first": all.author.fname
}
],
"organization": [
{
"identity": [
{
"root": oidFacility || "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
all.encounter_provider.facility_name
]
}
]
};
return {
"status": "completed",
"author": functionalStatusAuthor,
"identifiers": [{
"identifier": "9a6d1bac-17d3-4195-89a4-1121bc809000"
}],
"observation": {
"value": {
"name": pd.code_text !== "NULL" ? cleanText(pd.code_text) : "",
"code": cleanCode(pd.code) || "",
"code_system_name": pd.code_type || "SNOMED-CT"
},
"identifiers": [{
"identifier": "9a6d1bac-17d3-4195-89a4-1121bc8090ab"
}],
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "day"
}
},
"status": "completed",
"author": functionalStatusAuthor
}
};
}
function getMentalStatus(pd) {
return {
"value": {
"name": pd.code_text !== "NULL" ? pd.code_text : "",
"code": cleanCode(pd.code) || "",
"code_system_name": pd.code_type || ""
},
"identifiers": [{
"identifier": "9a6d1bac-17d3-4195-89a4-1121bc809ccc"
}],
"note": cleanText(pd.description),
"date_time": {
"low": templateDate(pd.date, "day")
//"high": templateDate(pd.date, "day")
},
"author": {
"code": {
"name": all.author.physician_type || '',
"code": all.author.physician_type_code || '',
"code_system": all.author.physician_type_system, "code_system_name": all.author.physician_type_system_name
},
"date_time": {
"point": {
"date": authorDateTime,
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.author.npi ? "2.16.840.1.113883.4.6" : all.author.id,
"extension": all.author.npi ? all.author.npi : ''
}
],
"name": [
{
"last": all.author.lname,
"first": all.author.fname
}
],
"organization": [
{
"identity": [
{
"root": oidFacility || "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
all.encounter_provider.facility_name
]
}
]
}
};
}
function getAssessments(pd) {
return {
"description": cleanText(pd.description),
"author": populateAuthorFromAuthorContainer(pd)
};
}
function getHealthConcerns(pd) {
let one = true;
let issue_uuid;
let problems = [], problem = {};
if (isOne(pd.issues.issue_uuid) !== 0) {
for (let key in pd.issues.issue_uuid) {
issue_uuid = pd.issues.issue_uuid[key];
if (issue_uuid) {
one = false;
}
problem = {
"identifiers": [{
"identifier": issue_uuid
}]
};
problems.push(problem);
}
}
if (one) {
if (pd.issues.issue_uuid) {
problem = {
"identifiers": [{
"identifier": pd.issues.issue_uuid
}]
};
problems.push(problem);
}
}
return {
"type": "act",
"text": cleanText(pd.text),
"value": {
"name": pd.code_text || "",
"code": cleanCode(pd.code) || "",
"code_system_name": pd.code_type || "SNOMED CT"
},
"author": populateAuthorFromAuthorContainer(pd),
"identifiers": [{
"identifier": pd.sha_extension
}],
problems: problems
}
}
function getReferralReason(pd) {
return {
"reason": cleanText(pd.text),
"author": populateAuthorFromAuthorContainer(pd)
};
}
function populateVital(pd) {
return {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension
}],
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
// our list of vitals per organizer.
"vital_list": [{
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_bps
}],
"vital": {
"name": "Blood Pressure Systolic",
"code": "8480-6",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.bps) || pd.bps,
"unit": "mm[Hg]",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_bpd
}],
"vital": {
"name": "Blood Pressure Diastolic",
"code": "8462-4",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.bpd) || pd.bpd,
"unit": "mm[Hg]",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_height
}],
"vital": {
"name": "Height",
"code": "8302-2",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.height) || pd.height,
"unit": pd.unit_height,
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_weight
}],
"vital": {
"name": "Weight Measured",
"code": "29463-7",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.weight) || "",
"unit": pd.unit_weight,
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_BMI
}],
"vital": {
"name": "BMI (Body Mass Index)",
"code": "39156-5",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": [pd.BMI_status == 'Overweight' ? 'High' : pd.BMI_status == 'Overweight' ? 'Low' : 'Normal'],
"value": parseFloat(pd.BMI) || "",
"unit": "kg/m2",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_pulse
}],
"vital": {
"name": "Heart Rate",
"code": "8867-4",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.pulse) || "",
"unit": "/min",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": "2.16.840.1.113883.3.140.1.0.6.10.14.2",
"extension": pd.extension_breath
}],
"vital": {
"name": "Respiratory Rate",
"code": "9279-1",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.breath) || "",
"unit": "/min",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": "2.16.840.1.113883.3.140.1.0.6.10.14.3",
"extension": pd.extension_temperature
}],
"vital": {
"name": "Body Temperature",
"code": "8310-5",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.temperature) || "",
"unit": pd.unit_temperature,
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_oxygen_saturation
}],
"vital": {
"name": "O2 % BldC Oximetry",
"code": "59408-5",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.oxygen_saturation) || "",
"unit": "%",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_ped_weight_height
}],
"vital": { // --------------------------------------------------------------------------------
"name": "Weight for Height Percentile",
"code": "77606-2",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.ped_weight_height) || "",
"unit": "%",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_inhaled_oxygen_concentration
}],
"vital": {
"name": "Inhaled Oxygen Concentration",
"code": "3150-0",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.inhaled_oxygen_concentration) || "",
"unit": "%",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_ped_bmi
}],
"vital": {
"name": "BMI Percentile",
"code": "59576-9",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.ped_bmi) || "",
"unit": "%",
"author": populateAuthorFromAuthorContainer(pd),
}, {
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension_ped_head_circ
}],
"vital": {
"name": "Head Occipital-frontal Circumference Percentile",
"code": "8289-1",
"code_system_name": "LOINC"
},
"status": "completed",
"date_time": {
"point": {
"date": fDate(pd.effectivetime),
"precision": "day"
}
},
"interpretations": ["Normal"],
"value": parseFloat(pd.ped_head_circ) || "",
"unit": "%",
"author": populateAuthorFromAuthorContainer(pd),
}
]
}
}
function populateSocialHistory(pd) {
return {
"date_time": {
"low": templateDate(pd.date, "day")
//"high": templateDate(pd.date, "day")
},
"identifiers": [{
"identifier": pd.sha_extension,
"extension": pd.extension
}],
"code": {
"name": pd.code
},
"element": pd.element,
"value": pd.description,
"gender": all.patient.gender,
"author": {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
}
, "gender_author": {
"code": {
"name": all.patient.author.physician_type || '',
"code": all.patient.author.physician_type_code || '',
"code_system": all.patient.author.physician_type_system, "code_system_name": all.patient.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(all.patient.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.patient.author.npi ? "2.16.840.1.113883.4.6" : all.patient.author.id,
"extension": all.patient.author.npi ? all.patient.author.npi : ''
}
],
"name": [
{
"last": all.patient.author.lname,
"first": all.patient.author.fname
}
],
"organization": [
{
"identity": [
{
"root": all.patient.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": all.patient.author.facility_npi || ""
}
],
"name": [
all.patient.author.facility_name
]
}
]
}
};
}
function populateImmunization(pd) {
return {
"date_time": {
"point": {
"date": fDate(pd.administered_on),
"precision": "month"
}
},
"identifiers": [{
"identifier": "e6f1ba43-c0ed-4b9b-9f12-f435d8ad8f92",
"extension": pd.extension || ""
}],
"status": "complete",
"product": {
"product": {
"name": pd.code_text,
"code": cleanCode(pd.cvx_code),
"code_system_name": "CVX"
/*"translations": [{
"name": "",
"code": "",
"code_system_name": "CVX"
}]*/
},
"lot_number": "",
"manufacturer": ""
},
"administration": {
"route": {
"name": pd.route_of_administration,
"code": cleanCode(pd.route_code) || "",
"code_system_name": "Medication Route FDA"
}/*,
"dose": {
"value": 50,
"unit": "mcg"
}*/
},
"performer": {
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": pd.npi || ""
}],
"name": [{
"last": pd.lname,
"first": pd.fname
}],
"address": [{
"street_lines": [pd.address],
"city": pd.city,
"state": pd.state,
"zip": pd.zip,
"country": "US"
}],
"organization": [{
"identifiers": [{
"identifier": "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}],
"name": [pd.facility_name]
}]
},
"instructions": {
"code": {
"name": "immunization education",
"code": "171044003",
"code_system_name": "SNOMED CT"
},
"free_text": "Needs Attention for more data."
},
"author": {
"code": {
"name": pd.author.physician_type || '',
"code": pd.author.physician_type_code || '',
"code_system": pd.author.physician_type_system, "code_system_name": pd.author.physician_type_system_name
},
"date_time": {
"point": {
"date": fDate(pd.author.time),
"precision": "tz"
}
},
"identifiers": [
{
"identifier": pd.author.npi ? "2.16.840.1.113883.4.6" : pd.author.id,
"extension": pd.author.npi ? pd.author.npi : ''
}
],
"name": [
{
"last": pd.author.lname,
"first": pd.author.fname
}
],
"organization": [
{
"identity": [
{
"root": pd.author.facility_oid || "2.16.840.1.113883.4.6",
"extension": pd.author.facility_npi || ""
}
],
"name": [
pd.author.facility_name
]
}
]
}
};
}
function populatePayer(pd) {
return {
"identifiers": [{
"identifier": "1fe2cdd0-7aad-11db-9fe1-0800200c9a66"
}],
"policy": {
"identifiers": [{
"identifier": "3e676a50-7aac-11db-9fe1-0800200c9a66"
}],
"code": {
"code": "SELF",
"code_system_name": "HL7 RoleCode"
},
"insurance": {
"code": {
"code": "PAYOR",
"code_system_name": "HL7 RoleCode"
},
"performer": {
"identifiers": [{
"identifier": "2.16.840.1.113883.19"
}],
"address": [{
"street_lines": ["123 Insurance Road"],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
"country": "US",
"use": "work place"
}],
"phone": [{
"number": "(781)555-1515",
"type": "work place"
}],
"organization": [{
"name": ["Good Health Insurance"],
"address": [{
"street_lines": ["123 Insurance Road"],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
"country": "US",
"use": "work place"
}],
"phone": [{
"number": "(781)555-1515",
"type": "work place"
}]
}],
"code": [{
"code": "PAYOR",
"code_system_name": "HL7 RoleCode"
}]
}
}
},
"guarantor": {
"code": {
"code": "GUAR",
"code_system_name": "HL7 Role"
},
"identifiers": [{
"identifier": "329fcdf0-7ab3-11db-9fe1-0800200c9a66"
}],
"name": [{
"prefix": "Mr.",
"middle": ["Frankie"],
"last": "Everyman",
"first": "Adam"
}],
"address": [{
"street_lines": ["17 Daws Rd."],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
"country": "US",
"use": "primary home"
}],
"phone": [{
"number": "(781)555-1212",
"type": "primary home"
}]
},
"participant": {
"code": {
"name": "Self",
"code": "SELF",
"code_system_name": "HL7 Role"
},
"performer": {
"identifiers": [{
"identifier": "14d4a520-7aae-11db-9fe1-0800200c9a66",
"extension": "1138345"
}],
"address": [{
"street_lines": ["17 Daws Rd."],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
"country": "US",
"use": "primary home"
}],
"code": [{
"name": "Self",
"code": "SELF",
"code_system_name": "HL7 Role"
}]
},
"name": [{
"prefix": "Mr.",
"middle": ["A."],
"last": "Everyman",
"first": "Frank"
}]
},
"policy_holder": {
"performer": {
"identifiers": [{
"identifier": "2.16.840.1.113883.19",
"extension": "1138345"
}],
"address": [{
"street_lines": ["17 Daws Rd."],
"city": "Blue Bell",
"state": "MA",
"zip": "02368",
"country": "US",
"use": "primary home"
}]
}
},
"authorization": {
"identifiers": [{
"identifier": "f4dce790-8328-11db-9fe1-0800200c9a66"
}],
"procedure": {
"code": {
"name": "Colonoscopy",
"code": "73761001",
"code_system_name": "SNOMED CT"
}
}
}
};
}
function populateNote(pd) {
return {
"date_time": {
"point": {
"date": fDate(pd.date),
"precision": "day"
}
},
"translations": {
code_system: "2.16.840.1.113883.6.1",
code_system_name: "LOINC",
code: cleanCode(pd.code),
name: pd.code_text || ""
},
"author": populateAuthorFromAuthorContainer(pd),
"note": cleanText(pd.description),
};
}
function populateParticipant(participant) {
return {
"name": {
"prefix": participant.prefix || "",
"suffix": participant.suffix || "",
"middle": [participant.mname] || "",
"last": participant.lname || "",
"first": participant.fname || ""
},
"typeCode": participant.type || "",
"classCode": "ASSIGNED",
"code": {
"name": participant.organization_taxonomy_description || "",
"code": cleanCode(participant.organization_taxonomy) || "",
"code_system": "2.16.840.1.113883.6.101",
"code_system_name": "NUCC Health Care Provider Taxonomy"
},
"identifiers": [{
"identifier": participant.organization_npi ? "2.16.840.1.113883.4.6" : participant.organization_id,
"extension": participant.organization_npi ? participant.organization_npi : ''
}],
"date_time": {
"point": {
"date": participant.date_time,
"precision": "tz"
}
},
"phone": [
{
"number": participant.phonew1 || "",
"type": "WP"
}
],
"address": [
{
"street_lines": [
participant.street
],
"city": participant.city,
"state": participant.state,
"zip": participant.postalCode,
"country": participant.country || "US",
"use": participant.address_use || "WP"
}
],
}
}
function populateHeader(pd) {
// default doc type ToC CCD
let name = "Summarization of Episode Note";
let docCode = "34133-9";
let docOid = "2.16.840.1.113883.10.20.22.1.2";
if (pd.doc_type == 'referral') {
name = "Referral Note";
docCode = "57133-1";
docOid = "2.16.840.1.113883.10.20.22.1.14";
}
const head = {
"identifiers": [
{
"identifier": oidFacility,
"extension": "123456"
}
],
"code": {
"name": name,
"code": docCode,
"code_system_name": "LOINC"
},
"template": {
"root": docOid,
"extension": "2015-08-01"
},
"title": name,
"date_time": {
"point": {
"date": fDate(pd.created_time_timezone),
"precision": "tz"
}
},
"author": {
"code": {
"name": all.author.physician_type || '',
"code": all.author.physician_type_code || '',
"code_system": all.author.physician_type_system, "code_system_name": all.author.physician_type_system_name
},
"date_time": {
"point": {
"date": authorDateTime,
"precision": "tz"
}
},
"identifiers": [
{
"identifier": all.author.npi ? "2.16.840.1.113883.4.6" : all.author.id,
"extension": all.author.npi ? all.author.npi : ''
}
],
"name": [
{
"last": all.author.lname,
"first": all.author.fname
}
],
"address": [
{
"street_lines": [
all.author.streetAddressLine
],
"city": all.author.city,
"state": all.author.state,
"zip": all.author.postalCode,
"country": all.author.country || "US",
"use": "work place"
}
],
"phone": [
{
"number": all.author.telecom || "",
"type": "WP"
}
],
"organization": [
{
"identity": [
{
"root": oidFacility || "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
all.encounter_provider.facility_name
],
"address": [
{
"street_lines": [
all.encounter_provider.facility_street
],
"city": all.encounter_provider.facility_city,
"state": all.encounter_provider.facility_state,
"zip": all.encounter_provider.facility_postal_code,
"country": all.encounter_provider.facility_country_code || "US",
"use": "work place"
}
],
"phone": [
{
"number": all.encounter_provider.facility_phone,
"type": "work primary"
}
]
}
]
},
"custodian": {
"identity": [
{
"root": "2.16.840.1.113883.4.6",
"extension": npiFacility || ""
}
],
"name": [
pd.custodian.organization || pd.custodian.name
],
"address": [
{
"street_lines": [
pd.custodian.streetAddressLine
],
"city": pd.custodian.city,
"state": pd.custodian.state,
"zip": pd.custodian.postalCode,
"country": pd.custodian.country || "US"
}
],
"phone": [
{
"number": pd.custodian.telecom,
"type": "work primary"
}
]
},
"information_recipient": {
"name": {
"prefix": pd.information_recipient.prefix || "",
"suffix": pd.information_recipient.suffix || "",
"middle": [pd.information_recipient.mname] || "",
"last": pd.information_recipient.lname || "",
"first": pd.information_recipient.fname || ""
},
"organization": {
"name": pd.information_recipient.organization || "org"
},
}
};
let participants = [];
let docParticipants = pd.document_participants || {participant: []};
let count = 0;
try {
count = isOne(docParticipants.participant);
} catch (e) {
count = 0
}
if (count === 1) {
participants = [populateParticipant(docParticipants.participant)];
} else {
// grab the values of our object
participants = Object.values(docParticipants.participant).filter(pcpt => pcpt.type).map(pcpt => populateParticipant(pcpt));
}
if (participants.length) {
head.participants = participants;
}
if (isOne(all.encounter_list.encounter) === 1) {
let primary_care_provider = pd.primary_care_provider || {provider: {}};
head.component_of = {
"identifiers": [
{
"identifier": oidFacility || "",
"extension": "PT-" + (pd.patient.id || "")
}
],
"code": {
"name": pd.primary_diagnosis.text || "",
"code": pd.primary_diagnosis.code || "",
"code_system_name": pd.primary_diagnosis.code_type || ""
},
"date_time": {
"low": {
"date": pd.primary_diagnosis.encounter_date || "",
"precision": "tz"
},
"high": {
"date": pd.primary_diagnosis.encounter_end_date || "",
"precision": "tz"
}
},
"responsible_party": {
"root": oidFacility,
"name": {
"last": pd.author.lname,
"first": pd.author.fname
},
},
"encounter_participant": {
"root": oidFacility,
"name": {
"last": primary_care_provider.provider.lname || "",
"first": primary_care_provider.provider.fname || ""
},
"address": [
{
"street_lines": [
pd.encounter_provider.facility_street
],
"city": pd.encounter_provider.facility_city,
"state": pd.encounter_provider.facility_state,
"zip": pd.encounter_provider.facility_postal_code,
"country": pd.encounter_provider.facility_country_code || "US",
"use": "work place"
}
],
"phone": [
{
"number": pd.encounter_provider.facility_phone,
"type": "work primary"
}
]
}
}
}
return head;
}
function getMeta(pd) {
var meta = {};
meta = {
"type": pd.doc_type,
"identifiers": [
{
"identifier": oidFacility || "",
"extension": "TT988"
}
],
"confidentiality": "Normal",
"set_id": {
"identifier": oidFacility || "",
"extension": "sTT988"
}
}
return meta;
}
/**
/ * function genCcda
/* The main document builder
/* pd array the xml parsed array of data sent from CCM.
*/
function genCcda(pd) {
let doc = {};
let data = {};
let count = 0;
let many = [];
let theone = {};
let primary_care_provider = all.primary_care_provider || {};
all = pd;
npiProvider = primary_care_provider.provider ? primary_care_provider.provider.npi : "";
oidFacility = all.encounter_provider.facility_oid ? all.encounter_provider.facility_oid : "2.16.840.1.113883.19.5.99999.1";
npiFacility = all.encounter_provider.facility_npi;
webRoot = all.serverRoot;
documentLocation = all.document_location;
authorDateTime = pd.created_time_timezone;
if (pd.author.time.length > 7) {
authorDateTime = pd.author.time;
} else if (all.encounter_list && all.encounter_list.encounter) {
if (isOne(all.encounter_list.encounter) === 1) {
authorDateTime = all.encounter_list.encounter.date;
} else {
authorDateTime = all.encounter_list.encounter[0].date;
}
}
authorDateTime = fDate(authorDateTime);
// Demographics
let demographic = populateDemographic(pd.patient, pd.guardian, pd);
// This populates documentationOf. We are using providerOrganization also.
if (pd.primary_care_provider) {
Object.assign(demographic, populateProviders(pd));
}
data.demographics = Object.assign(demographic);
// Encounters
let encs = [];
let enc = {};
encs.encounters = [];
try {
count = isOne(pd.encounter_list.encounter);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.encounter_list.encounter) {
enc[i] = populateEncounter(pd.encounter_list.encounter[i]);
encs.encounters.push(enc[i]);
}
} else if (count !== 0) {
enc = populateEncounter(pd.encounter_list.encounter);
encs.encounters.push(enc);
}
if (count !== 0) {
data.encounters = Object.assign(encs.encounters);
}
// vitals
many.vitals = [];
try {
count = isOne(pd.history_physical.vitals_list.vitals);
} catch (e) {
count = 0
}
if (count !== 0) {
data.vitals = Object.assign(populateVital(pd.history_physical.vitals_list.vitals));
}
// Medications
let meds = [];
let m = {};
meds.medications = [];
try {
count = isOne(pd.medications.medication);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.medications.medication) {
m[i] = populateMedication(pd.medications.medication[i]);
meds.medications.push(m[i]);
}
} else if (count !== 0) {
m = populateMedication(pd.medications.medication);
meds.medications.push(m);
}
if (count !== 0) {
data.medications = Object.assign(meds.medications);
}
// Allergies
let allergies = [];
let allergy = {};
allergies.allergies = [];
try {
count = isOne(pd.allergies.allergy);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.allergies.allergy) {
allergy[i] = populateAllergy(pd.allergies.allergy[i]);
allergies.allergies.push(allergy[i]);
}
} else if (count <= 1) {
allergy = populateAllergy(pd.allergies.allergy);
allergies.allergies.push(allergy);
count = 1;
}
if (count !== 0) {
data.allergies = Object.assign(allergies.allergies);
}
// Problems
let problems = [];
let problem = {};
problems.problems = [];
try {
count = isOne(pd.problem_lists.problem);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.problem_lists.problem) {
problem[i] = populateProblem(pd.problem_lists.problem[i], pd);
problems.problems.push(problem[i]);
}
} else if (count !== 0) {
problem = populateProblem(pd.problem_lists.problem);
problems.problems.push(problem);
}
if (count !== 0) {
data.problems = Object.assign(problems.problems);
}
// Procedures
many = [];
theone = {};
many.procedures = [];
try {
count = isOne(pd.procedures.procedure);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.procedures.procedure) {
theone[i] = populateProcedure(pd.procedures.procedure[i]);
many.procedures.push(theone[i]);
}
} else if (count !== 0) {
theone = populateProcedure(pd.procedures.procedure);
many.procedures.push(theone);
}
if (count !== 0) {
data.procedures = Object.assign(many.procedures);
}
// Medical Devices
many = [];
theone = {};
many.medical_devices = [];
try {
count = isOne(pd.medical_devices.device);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.medical_devices.device) {
theone[i] = populateMedicalDevice(pd.medical_devices.device[i]);
many.medical_devices.push(theone[i]);
}
} else if (count !== 0) {
theone = populateMedicalDevice(pd.medical_devices.device);
many.medical_devices.push(theone);
}
if (count !== 0) {
data.medical_devices = Object.assign(many.medical_devices);
}
// Results
if (pd.results) {
data.results = Object.assign(getResultSet(pd.results, pd)['results']);
}
// Referral TODO sjp I'm not happy with this.
// different referral sources. 1st is dynamic with doc gen from CCM.
// 2nd is the latest referral from transactions.
if (pd.referral_reason[0].text !== "") {
data.referral_reason = Object.assign(getReferralReason(pd.referral_reason[0], pd));
} else if (pd.referral_reason[1].text !== "" && typeof pd.referral_reason[1].text !== 'undefined') {
data.referral_reason = Object.assign(getReferralReason(pd.referral_reason[1], pd));
} else {
data.referral_reason = {}; // leave as empty so we can get our null flavor section.
}
// Health Concerns
many = [];
theone = {};
many.health_concerns = [];
try {
count = isOne(pd.health_concerns.concern);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.health_concerns.concern) {
theone[i] = getHealthConcerns(pd.health_concerns.concern[i]);
many.health_concerns.push(theone[i]);
break;
}
} else if (count !== 0) {
theone = getHealthConcerns(pd.health_concerns.concern);
many.health_concerns.push(theone);
}
if (count !== 0) {
data.health_concerns = Object.assign(many.health_concerns);
} else {
data.health_concerns = {"type": "act"}; // leave it as an empty section that we'll null flavor
}
// Immunizations
many = [];
theone = {};
many.immunizations = [];
try {
count = isOne(pd.immunizations.immunization);
} catch (e) {
count = 0;
}
if (count > 1) {
for (let i in pd.immunizations.immunization) {
theone[i] = populateImmunization(pd.immunizations.immunization[i]);
many.immunizations.push(theone[i]);
}
} else if (count !== 0) {
theone = populateImmunization(pd.immunizations.immunization);
many.immunizations.push(theone);
}
if (count !== 0) {
data.immunizations = Object.assign(many.immunizations);
}
// Plan of Care
many = [];
theone = {};
many.plan_of_care = [];
try {
count = isOne(pd.planofcare.item);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.planofcare.item) {
if (cleanCode(pd.planofcare.item[i].date) === '') {
i--;
continue;
}
theone[i] = getPlanOfCare(pd.planofcare.item[i]);
if (theone[i]) {
many.plan_of_care.push(theone[i]);
}
}
} else if (count !== 0) {
theone = getPlanOfCare(pd.planofcare.item);
if (theone) {
many.plan_of_care.push(theone);
}
}
if (count !== 0) {
data.plan_of_care = Object.assign(many.plan_of_care);
}
// Goals
many = [];
theone = {};
many.goals = [];
try {
count = isOne(pd.goals.item);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.goals.item) {
theone[i] = getGoals(pd.goals.item[i]);
many.goals.push(theone[i]);
}
} else if (count !== 0) {
theone = getGoals(pd.goals.item);
many.goals.push(theone);
}
if (count !== 0) {
data.goals = Object.assign(many.goals);
}
// Assessments.
many = [];
theone = {};
many.clinicalNoteAssessments = [];
try {
count = isOne(pd.clinical_notes.evaluation_note);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.clinical_notes.evaluation_note) {
theone[i] = getAssessments(pd.clinical_notes.evaluation_note[i]);
many.clinicalNoteAssessments.push(theone[i]);
break; // for now only one assessment. @todo concat notes to one.
}
} else if (count !== 0) {
theone = getAssessments(pd.clinical_notes.evaluation_note);
many.clinicalNoteAssessments.push(theone);
}
if (count !== 0) {
data.clinicalNoteAssessments = Object.assign(many.clinicalNoteAssessments);
}
// Functional Status.
many = [];
theone = {};
many.functional_status = [];
try {
count = isOne(pd.functional_status.item);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.functional_status.item) {
theone[i] = getFunctionalStatus(pd.functional_status.item[i]);
many.functional_status.push(theone[i]);
}
} else if (count !== 0) {
theone = getFunctionalStatus(pd.functional_status.item);
many.functional_status.push(theone);
}
if (count !== 0) {
data.functional_status = Object.assign(many.functional_status);
}
// Mental Status.
many = [];
theone = {};
many.mental_status = [];
try {
count = isOne(pd.mental_status.item);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.mental_status.item) {
theone[i] = getMentalStatus(pd.mental_status.item[i]);
many.mental_status.push(theone[i]);
}
} else if (count !== 0) {
theone = getMentalStatus(pd.mental_status.item);
many.mental_status.push(theone);
}
if (count !== 0) {
data.mental_status = Object.assign(many.mental_status);
}
// Social History
many = [];
theone = {};
many.social_history = [];
try {
count = isOne(pd.history_physical.social_history.history_element);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.history_physical.social_history.history_element) {
if (i > 0) break;
theone[i] = populateSocialHistory(pd.history_physical.social_history.history_element[i]);
many.social_history.push(theone[i]);
}
} else if (count !== 0) {
theone = populateSocialHistory(pd.history_physical.social_history.history_element);
many.social_history.push(theone);
}
if (count !== 0) {
data.social_history = Object.assign(many.social_history);
}
// Notes
for (let currentNote in pd.clinical_notes) {
many = [];
theone = {};
switch (pd.clinical_notes[currentNote].clinical_notes_type) {
case 'evaluation_note':
continue;
break;
case 'progress_note':
break;
case 'history_physical':
pd.clinical_notes[currentNote].code_text = "History and Physical";
break;
case 'nurse_note':
break;
case 'general_note':
break;
case 'discharge_summary':
break;
case 'procedure_note':
break;
case 'consultation_note':
break;
case 'imaging_narrative':
break;
case 'laboratory_report_narrative':
break;
case 'pathology_report_narrative':
break;
default:
continue;
}
try {
count = isOne(pd.clinical_notes[currentNote]);
} catch (e) {
count = 0
}
if (count > 1) {
for (let i in pd.clinical_notes[currentNote]) {
theone[i] = populateNote(pd.clinical_notes[currentNote]);
many.push(theone[i]);
}
} else if (count !== 0) {
theone = populateNote(pd.clinical_notes[currentNote]);
many.push(theone);
}
if (count !== 0) {
data[currentNote] = Object.assign(many);
}
}
// Care Team and members
if (pd.care_team.is_active == 'active') {
data.care_team = Object.assign(populateCareTeamMembers(pd));
}
// ------------------------------------------ End Sections ----------------------------------------//
doc.data = Object.assign(data);
let meta = getMeta(pd);
let header = populateHeader(pd);
meta.ccda_header = Object.assign(header);
doc.meta = Object.assign(meta);
if (pd.timezone_local_offset) {
populateTimezones(doc, pd.timezone_local_offset, 0);
}
// build to cda
let xml = bbg.generateCCD(doc);
/* Debug */
if (enableDebug === true) {
let place = documentLocation + "/documents/temp/";
if (fs.existsSync(place)) {
fs.writeFile(place + "ccda.json", JSON.stringify(all, null, 4), function (err) {
if (err) {
return console.log(err);
}
//console.log("Json saved!");
});
fs.writeFile(place + "ccda.xml", xml, function (err) {
if (err) {
return console.log(err);
}
//console.log("Xml saved!");
});
}
}
return xml;
}
function processConnection(connection) {
conn = connection; // make it global
let remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
conn.setEncoding('utf8');
let xml_complete = "";
function eventData(xml) {
xml_complete = xml.toString();
//console.log("length: " + xml.length + " " + xml_complete);
// ensure we have an array start and end
if (xml_complete.match(/^<CCDA/g) && xml_complete.match(/<\/CCDA>$/g)) {
let doc = "";
let xslUrl = "";
xml_complete = xml_complete.replace(/(\u000b|\u001c)/gm, "").trim();
// let's not allow windows CR/LF
xml_complete = xml_complete.replace(/[\r\n]/gm, '').trim();
xml_complete = xml_complete.replace(/\t\s+/g, ' ').trim();
// convert xml data set for document to json array
to_json(xml_complete, function (error, data) {
//console.log(JSON.stringify(data, null, 4));
if (error) { // need try catch
console.log('toJson error: ' + error + 'Len: ' + xml_complete.length);
return;
}
// create document
doc = genCcda(data.CCDA);
if (data.CCDA.xslUrl) {
xslUrl = data.CCDA.xslUrl || "";
}
});
doc = headReplace(doc, xslUrl);
doc = doc.toString().replace(/(\u000b|\u001c|\r)/gm, "").trim();
let chunk = "";
let numChunks = Math.ceil(doc.length / 1024);
for (let i = 0, o = 0; i < numChunks; ++i, o += 1024) {
chunk = doc.substring(o, o + 1024);
conn.write(chunk);
}
conn.write(String.fromCharCode(28) + "\r\r" + '');
conn.end();
}
}
function eventCloseConn() {
//console.log('connection from %s closed', remoteAddress);
}
function eventErrorConn(err) {
console.log('Connection %s error: %s', remoteAddress, err.message);
}
// Connection Events //
// CCM will send two File Separator characters to mark end of array.
let received = new DataStack(String.fromCharCode(28));
conn.on("data", data => {
received.pushToStack(data);
while (!received.endOfCcda() && data.length > 0) {
data = "";
eventData(received.returnData())
}
});
conn.once('close', eventCloseConn);
conn.on('error', eventErrorConn);
}
function setUp(server) {
server.on('connection', processConnection);
server.listen(6661, 'localhost', function () { // never change port!
//console.log('server listening to %j', server.address());
});
}
// start up listener for requests from CCM or others.
setUp(server);
/* ---------------------------------For future use in header. Do not remove!-------------------------------------------- */
/*"data_enterer": {
"identifiers": [
{
"identifier": "2.16.840.1.113883.4.6",
"extension": "999999943252"
}
],
"name": [
{
"last": pd.data_enterer.lname,
"first": pd.data_enterer.fname
}
],
"address": [
{
"street_lines": [
pd.data_enterer.streetAddressLine
],
"city": pd.data_enterer.city,
"state": pd.data_enterer.state,
"zip": pd.data_enterer.postalCode,
"country": pd.data_enterer.country
}
],
"phone": [
{
"number": pd.data_enterer.telecom,
"type": "work place"
}
]
},
"informant": {
"identifiers": [
{
"identifier": "2.16.840.1.113883.19.5",
"extension": "KP00017"
}
],
"name": [
{
"last": pd.informer.lname || "",
"first": pd.informer.fname || ""
}
],
"address": [
{
"street_lines": [
pd.informer.streetAddressLine || ""
],
"city": pd.informer.city,
"state": pd.informer.state,
"zip": pd.informer.postalCode,
"country": pd.informer.country
}
],
"phone": [
{
"number": pd.informer.telecom || "",
"type": "work place"
}
]
},*/
/*"service_event": {
"code": {
"name": "",
"code": "",
"code_system_name": "SNOMED CT"
},
"date_time": {
"low": {
"date": "2021-03-11",
"precision": "day"
},
"high": {
"date": pd.created_time,
"precision": "day"
}
},
"performer": [
{
"performer": [
{
"identifiers": [
{
"identifier": "2.16.840.1.113883.4.6",
"extension": npiProvider
}
],
"name": [
{
"last": pd.information_recipient.lname || "DAH",
"first": pd.information_recipient.fname || "DAH"
}
],
"address": [
{
"street_lines": [
pd.information_recipient.streetAddressLine
],
"city": pd.information_recipient.city,
"state": pd.information_recipient.state,
"zip": pd.information_recipient.postalCode,
"country": pd.information_recipient.country || "US"
}
],
"phone": [
{
"number": pd.information_recipient.telecom,
"type": "work place"
}
],
"organization": [
{
"identifiers": [
{
"identifier": "2.16.840.1.113883.19.5.9999.1393"
}
],
"name": [
pd.encounter_provider.facility_name
],
"address": [
{
"street_lines": [
pd.encounter_provider.facility_street
],
"city": pd.encounter_provider.facility_city,
"state": pd.encounter_provider.facility_state,
"zip": pd.encounter_provider.facility_postal_code,
"country": pd.encounter_provider.facility_country_code || "US"
}
],
"phone": [
{
"number": pd.encounter_provider.facility_phone,
"type": "primary work"
}
]
}
],
"code": [
{
"name": "",
"code": "",
"code_system_name": "Provider Codes"
}
]
}
],
"code": {
"name": "Primary Performer",
"code": "PP",
"code_system_name": "Provider Role"
}
}
]
}*/