8000 RELEASE XCPD w/ custodian + CCD fixes by leite08 · Pull Request #4015 · metriport/metriport · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

RELEASE XCPD w/ custodian + CCD fixes #4015

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 13, 2025
35 changes: 18 additions & 17 deletions packages/api/src/external/cda/generate-empty-ccd.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Address as FhirAddress, Organization } from "@medplum/fhirtypes";
import { AddressStrict } from "@metriport/core/domain/location-address";
import { Patient } from "@metriport/core/domain/patient";
import { Address } from "@metriport/core/domain/address";
import { Contact } from "@metriport/core/domain/contact";
import { AddressStrict } from "@metriport/core/domain/location-address";
import { Patient } from "@metriport/core/domain/patient";
import { encodeToHtml } from "@metriport/shared/common/html";
import { metriportOrganization } from "@metriport/shared/common/metriport-organization";
import { getOrganizationOrFail } from "../../command/medical/organization/get-organization";
import { OrganizationModel } from "../../models/medical/organization";
Expand All @@ -26,7 +27,7 @@ export async function generateEmptyCcd(patient: Patient): Promise<string> {
<typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/>
<templateId root="2.16.840.1.113883.10.20.22.1.1" extension="2015-08-01"/>
<templateId root="2.16.840.1.113883.10.20.22.1.2" extension="2015-08-01"/>
<id root="${metriportOid}" assigningAuthorityName="${metriportOrganization.name}"/>
<id root="${metriportOid}" assigningAuthorityName="${encodeToHtml(metriportOrganization.name)}"/>
<code code="34133-9" codeSystem="2.16.840.1.113883.6.1" displayName="Summarization of episode note" codeSystemName="LOINC"/>
<title>Continuity of Care Document</title>
<effectiveTime value="${currentTime}"/>
Expand All @@ -40,10 +41,10 @@ export async function generateEmptyCcd(patient: Patient): Promise<string> {
<patient>
<name use="L">
<given>
${data.firstName}
${encodeToHtml(data.firstName)}
</given>
<family>
${data.lastName}
${encodeToHtml(data.lastName)}
</family>
</name>
<administrativeGenderCode code="${
Expand Down Expand Up @@ -76,21 +77,21 @@ function buildAddress(addr: Address | AddressStrict): string {
let addressString = "";
addressString += `<addr use="H">
<streetAddressLine>
${addr.addressLine1}
${encodeToHtml(addr.addressLine1)}
</streetAddressLine>`;
if (addr.addressLine2) {
addressString += `<streetAddressLine>
${addr.addressLine2}
${encodeToHtml(addr.addressLine2)}
</streetAddressLine>`;
}
addressString += `<city>
${addr.city}
${encodeToHtml(addr.city)}
</city>
<state>
${addr.state}
${encodeToHtml(addr.state)}
</state>
<postalCode>
${addr.zip}
${encodeToHtml(addr.zip)}
</postalCode>
</addr>`;

Expand All @@ -102,7 +103,7 @@ function buildTelecom(contacts: Contact[] | undefined): string {

let telecomString = ``;
contacts.forEach(contact => {
telecomString += `<telecom value="tel:${contact.phone}"/>`;
telecomString += `<telecom value="tel:${encodeToHtml(contact.phone ?? "")}"/>`;
});

return telecomString;
Expand All @@ -111,16 +112,16 @@ function buildTelecom(contacts: Contact[] | undefined): string {
function buildCustodianAddresses(address: FhirAddress): string {
return `<addr>
<streetAddressLine>
${address.line?.[0]}
${encodeToHtml(address.line?.[0] ?? "")}
</streetAddressLine>
<city>
${address.city}
${encodeToHtml(address.city ?? "")}
</city>
<state>
${address.state}
${encodeToHtml(address.state ?? "")}
</state>
<postalCode>
${address.postalCode}
${encodeToHtml(address.postalCode ?? "")}
</postalCode>
<country>
US
Expand All @@ -141,7 +142,7 @@ function buildAuthor(org: OrganizationModel) {
<id nullFlavor="UNK">
</id>
<name>
${org.data.name}
${encodeToHtml(org.data.name)}
</name>
${address}
</representedOrganization>
Expand All @@ -155,7 +156,7 @@ function buildCustodian(org: Organization): string {
const address = buildCustodianAddresses(orgAddress);

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const phoneNumber = org.telecom![0]!.value;
const phoneNumber = encodeToHtml(org.telecom![0]!.value ?? "");
return `<custodian>
<assignedCustodian>
<representedCustodianOrganization>
Expand Down
3 changes: 3 additions & 0 deletions packages/api/src/routes/internal/medical/patient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,9 @@ router.post(
fromDashboard,
} = internalSendConsolidatedSchema.parse(req.body);

const { log } = out(`cx ${cxId}, pt ${id}, requestId ${requestId})`);
log(`conversionType: ${conversionType}, resources: ${resources}`);

const bundle = await getConsolidatedSnapshotFromS3({
bundleLocation,
bundleFilename,
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/routes/medical/patient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { makeSearchConsolidated } from "@metriport/core/command/consolidated/sea
import { mrFormat } from "@metriport/core/domain/conversion/fhir-to-medical-record";
import { MAXIMUM_UPLOAD_FILE_SIZE } from "@metriport/core/external/aws/lambda-logic/document-uploader";
import { toFHIR } from "@metriport/core/external/fhir/patient/conversion";
import { out } from "@metriport/core/util/log";
import { getRequestId } from "@metriport/core/util/request";
import { BadRequestError, isTrue, NotFoundError, stringToBoolean } from "@metriport/shared";
import { Request, Response } from "express";
Expand Down Expand Up @@ -198,6 +199,7 @@ router.get(
const queryParam = getFrom("query").optional("query", req);
const query = queryParam ? queryParam.trim() : undefined;

out(`cx ${patient.cxId} pt ${patient.id}`).log(`Searching for ||${query}||`);
const result = await makeSearchConsolidated().search({ patient, query });

return res.status(status.OK).json(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ function createSubjectAndRegistrationEvent(response: InboundPatientDiscoveryResp
},
},
},
custodian: {
"@_typeCode": "CST",
assignedEntity: {
"@_classCode": "ASSIGNED",
id: {
"@_root": METRIPORT_HOME_COMMUNITY_ID_NO_PREFIX,
},
code: {
"@_code": "NotHealthDataLocator",
"@_codeSystem": "1.3.6.1.4.1.19376.1.2.27.2",
},
},
},
},
};
return subject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export function formatIdentifier({
identifier: Identifier | undefined;
systemsToInclude?: string[] | undefined;
}): string | undefined {
if (!identifier) return undefined;
const value = identifier.value?.trim();
if (!identifier?.value) return undefined;
const value = String(identifier.value).trim();
if (!value) return undefined;
if (systemsToInclude && !systemsToInclude.some(system => identifier.system?.includes(system))) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CodeableConcept,
Coding,
} from "@medplum/fhirtypes";
import { encodeToHtml } from "@metriport/shared/common/html";
import { isAllergyIntolerance } from "../../../external/fhir/shared";
import { AllergiesSection } from "../../cda-types/sections";
import {
Expand All @@ -29,17 +30,17 @@ import {
withNullFlavor,
} from "../commons";
import {
NOT_SPECIFIED,
_xsiTypeAttribute,
extensionValue2014,
extensionValue2015,
hl7ActCode,
loincCodeSystem,
loincSystemName,
NOT_SPECIFIED,
oids,
placeholderOrgOid,
snomedCodeSystem,
snomedSystemName,
_xsiTypeAttribute,
} from "../constants";
import { createTableRowsAndEntries } from "../create-table-rows-and-entries";
import { initiateSectionTable } from "../table";
Expand Down Expand Up @@ -168,7 +169,7 @@ function createTableRowFromAllergyIntolerance(
["td"]: [
{
_ID: `${referenceId}-substance`,
"#text": allergenName ?? name ?? NOT_SPECIFIED,
"#text": encodeToHtml(allergenName ?? name ?? NOT_SPECIFIED),
},
{
"#text": category?.join(", ") ?? NOT_SPECIFIED,
Expand All @@ -184,7 +185,7 @@ function createTableRowFromAllergyIntolerance(
"#text": onsetDate ?? NOT_SPECIFIED,
},
{
"#text": note ?? NOT_SPECIFIED,
"#text": encodeToHtml(note ?? NOT_SPECIFIED),
},
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Bundle, Encounter, HumanName, Location, Practitioner } from "@medplum/fhirtypes";
import { toArray } from "@metriport/shared";
import { encodeToHtml } from "@metriport/shared/common/html";
import {
findResourceInBundle,
isEncounter,
Expand Down Expand Up @@ -29,10 +30,10 @@ import {
withoutNullFlavorObject,
} from "../commons";
import {
NOT_SPECIFIED,
extensionValue2015,
loincCodeSystem,
loincSystemName,
NOT_SPECIFIED,
oids,
placeholderOrgOid,
} from "../constants";
Expand Down Expand Up @@ -149,10 +150,12 @@ function createTableRowFromEncounter(
"#text": getDisplaysFromCodeableConcepts(encounter.resource.type) ?? NOT_SPECIFIED,
},
{
"#text": getPractitionerInformation(encounter.practitioners) ?? NOT_SPECIFIED,
"#text": encodeToHtml(
getPractitionerInformation(encounter.practitioners) ?? NOT_SPECIFIED
),
},
{
"#text": locationDesc ?? NOT_SPECIFIED,
"#text": encodeToHtml(locationDesc ?? NOT_SPECIFIED),
},
{
"#text":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
FamilyMemberHistory,
FamilyMemberHistoryCondition,
} from "@medplum/fhirtypes";
import { encodeToHtml } from "@metriport/shared/common/html";
import { isFamilyMemberHistory } from "../../../external/fhir/shared";
import { FamilyHistorySection } from "../../cda-types/sections";
import {
Expand All @@ -31,15 +32,15 @@ import {
withNullFlavor,
} from "../commons";
import {
NOT_SPECIFIED,
_xmlnsSdtcAttribute,
extensionValue2015,
loincCodeSystem,
loincSystemName,
NOT_SPECIFIED,
oids,
placeholderOrgOid,
snomedCodeSystem,
snomedSystemName,
_xmlnsSdtcAttribute,
} from "../constants";
import { createTableRowsAndEntries } from "../create-table-rows-and-entries";
import { initiateSectionTable } from "../table";
Expand Down Expand Up @@ -132,13 +133,13 @@ function createTableRowFromMemberHistory(
"#text": getConditionOnset(condition?.onsetAge) ?? NOT_SPECIFIED,
},
{
"#text": relationship ?? NOT_SPECIFIED,
"#text": encodeToHtml(relationship ?? NOT_SPECIFIED),
},
{
"#text": name ?? NOT_SPECIFIED,
"#text": encodeToHtml(name ?? NOT_SPECIFIED),
},
{
"#text": getNotes(condition?.note) ?? NOT_SPECIFIED,
"#text": encodeToHtml(getNotes(condition?.note) ?? NOT_SPECIFIED),
},
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Bundle, Immunization, Location } from "@medplum/fhirtypes";
import { encodeToHtml } from "@metriport/shared/common/html";
import { findResourceInBundle, isImmunization, isLocation } from "../../../external/fhir/shared";
import { ImmunizationsSection } from "../../cda-types/sections";
import {
Expand All @@ -21,11 +22,11 @@ import {
withoutNullFlavorObject,
} from "../commons";
import {
NOT_SPECIFIED,
extensionValue2015,
hl7ActCode,
loincCodeSystem,
loincSystemName,
NOT_SPECIFIED,
oids,
placeholderOrgOid,
} from "../constants";
Expand Down Expand Up @@ -125,7 +126,7 @@ function createTableRowFromImmunization(
"#text": mapImmunizationStatusCode(immunization.resource.status) ?? NOT_SPECIFIED,
},
{
"#text": locationInfo ?? immunization.locationName ?? NOT_SPECIFIED,
"#text": encodeToHtml(locationInfo ?? immunization.locationName ?? NOT_SPECIFIED),
},
{
"#text":
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Bundle, Dosage, DosageDoseAndRate, MedicationStatement } from "@medplum/fhirtypes";
import { BadRequestError } from "@metriport/shared";
import { encodeToHtml } from "@metriport/shared/common/html";
import {
findResourceInBundle,
isMedication,
Expand All @@ -26,13 +27,13 @@ import {
withoutNullFlavorObject,
} from "../commons";
import {
NOT_SPECIFIED,
_xsiTypeAttribute,
extensionValue2014,
loincCodeSystem,
loincSystemName,
NOT_SPECIFIED,
oids,
placeholderOrgOid,
_xsiTypeAttribute,
} from "../constants";
import { createTableRowsAndEntries } from "../create-table-rows-and-entries";
import { initiateSectionTable } from "../table";
Expand Down Expand Up @@ -112,7 +113,7 @@ function createTableRowsFromMedicationStatement(
_ID: referenceId,
["td"]: [
{
"#text": medicationName ?? NOT_SPECIFIED,
"#text": encodeToHtml(medicationName ?? NOT_SPECIFIED),
},
{
"#text": code?._code ?? NOT_SPECIFIED,
Expand Down
Loading
Loading
0