diff --git a/frontend/src/app/pages/resource-detail/resource-detail.component.html b/frontend/src/app/pages/resource-detail/resource-detail.component.html index 045f17dc..14bc2cd4 100644 --- a/frontend/src/app/pages/resource-detail/resource-detail.component.html +++ b/frontend/src/app/pages/resource-detail/resource-detail.component.html @@ -2,7 +2,7 @@
- {{sourceName}} + {{sourceName}} Resource {{resource?.source_resource_type}} {{resource?.source_resource_id}} diff --git a/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts b/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts index e9afecd8..9b0d1883 100644 --- a/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts +++ b/frontend/src/lib/conduit/fhir/base/fhir401_r4_client.ts @@ -11,6 +11,35 @@ export class FHIR401Client extends BaseClient implements IClient { //clients extending this class must validate fhirVersion matches using conformance/metadata url. fhirVersion = "4.0.1" + // https://build.fhir.org/ig/HL7/US-Core/ + usCoreResources: string[] = [ + "AllergyIntolerance", + //"Binary", + "CarePlan", + "CareTeam", + "Condition", + //"Coverage", + "Device", + "DiagnosticReport", + "DocumentReference", + "Encounter", + "Goal", + "Immunization", + //"Location", + //"Medication", + //"MedicationRequest", + "Observation", + //"Organization", + //"Patient", + //"Practitioner", + //"PractitionerRole", + "Procedure", + //"Provenance", + //"RelatedPerson", + // "ServiceRequest", + // "Specimen", + ] + constructor(source: Source, clientConfig: ClientConfig) { super(source, clientConfig); } @@ -73,6 +102,348 @@ export class FHIR401Client extends BaseClient implements IClient { return upsertSummary } + /** + * Given a raw resource payload, this function will determine if there are references to other resources, and extract them if so + * This is useful because search (by patient id) is disabled for certain resource types. + * @param sourceResourceType + * @param resourceRaw + * @constructor + */ + public async ExtractResourceReference(sourceResourceType: string, resourceRaw): Promise { + let resourceRefs = [] + + switch (sourceResourceType) { + case "CarePlan": + // encounter can contain + //- Encounter + resourceRefs.push(resourceRaw.encounter?.reference) + + //author can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- CareTeam + //- RelatedPerson + resourceRefs.push(resourceRaw.author?.reference) + + + //contributor can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- CareTeam + //- RelatedPerson + resourceRefs.push(resourceRaw.contributor?.reference) + + //careTeam can contain + //- CareTeam + resourceRefs.push(resourceRaw.careTeam?.reference) + + break; + case "CareTeam": + // encounter can contain + //- Encounter + resourceRefs.push(resourceRaw.encounter?.reference) + + //participant[x].member can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- CareTeam + //- RelatedPerson + //participant[x].onBehalfOf can contain + //- Organization + resourceRaw.participant?.map((participant) => { + resourceRefs.push(participant.member?.reference) + resourceRefs.push(participant.onBehalfOf?.reference) + }) + + //managingOrganization + //- Organization + resourceRaw.managingOrganization?.map((managingOrganization) => { + resourceRefs.push(managingOrganization.reference) + }) + break; + case "Condition": + // recorder can contain + //- Practitioner + //- PractitionerRole + //- Patient + //- RelatedPerson + resourceRefs.push(resourceRaw.recorder?.reference) + + // asserter can contain + //- Practitioner + //- PractitionerRole + //- Patient + //- RelatedPerson + resourceRefs.push(resourceRaw.asserter?.reference) + + break; + case "DiagnosticReport": + //basedOn[x] can contain + //- CarePlan + //- ImmunizationRecommendation + //- MedicationRequest + //- NutritionOrder + //- ServiceRequest + resourceRaw.basedOn?.map((basedOn) => { + resourceRefs.push(basedOn.reference) + }) + + // performer[x] can contain + //- Practitioner + //- PractitionerRole + //- Organization + //- CareTeam + resourceRaw.performer?.map((performer) => { + resourceRefs.push(performer.reference) + }) + break; + case "DocumentReference": + //author[x] can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- CareTeam + //- Device + resourceRaw.author?.map((author) => { + resourceRefs.push(author.reference) + }) + + //authenticator can contain + //- Practitioner + //- Organization + //- PractitionerRole + resourceRefs.push(resourceRaw.authenticator?.reference) + + // custodian can contain + //- Organization + resourceRefs.push(resourceRaw.custodian?.reference) + + // relatesTo.target + //- DocumentReference + resourceRaw.relatesTo?.map((relatesTo) => { + resourceRefs.push(relatesTo.target?.reference) + }) + + //content.attachment can contain + //- Attachment + break + case "Encounter": + // basedOn[x] can contain + //- ServiceRequest + resourceRaw.basedOn?.map((basedOn) => { + resourceRefs.push(basedOn.reference) + }) + + //participant[x].individual can contain + //- Practitioner + //- PractitionerRole + //- RelatedPerson + resourceRaw.participant?.map((participant) => { + resourceRefs.push(participant.individual?.reference) + }) + + //reasonReference[x] can contain + //- Condition + //- Procedure + //- Observation + //- ImmunizationRecommendation + resourceRaw.reasonReference?.map((reasonReference) => { + resourceRefs.push(reasonReference.reference) + }) + + //hospitalization[x].origin can contain + //- Location + //- Organization + //hospitalization[x].destination can contain + //- Location + //- Organization + resourceRaw.hospitalization?.map((hospitalization) => { + resourceRefs.push(hospitalization.origin?.reference) + resourceRefs.push(hospitalization.destination?.reference) + }) + + //location[x].location can contain + //- Location + resourceRaw.location?.map((location) => { + resourceRefs.push(location.location?.reference) + }) + + //serviceProvider can contain + //- Organization + resourceRefs.push(resourceRaw.serviceProvider?.reference) + + break + case "Immunization": + // location can contain + //- Location + resourceRefs.push(resourceRaw.location?.reference) + + // manufacturer can contain + //- Organization + resourceRefs.push(resourceRaw.manufacturer?.reference) + + //performer[x].actor can contain + //- Practitioner | PractitionerRole | Organization + resourceRaw.performer?.map((performer) => { + resourceRefs.push(performer.actor?.reference) + }) + + //reasonReference[x] can contain + //- Condition | Observation | DiagnosticReport + resourceRaw.reasonReference?.map((reasonReference) => { + resourceRefs.push(reasonReference.reference) + }) + + //protocolApplied[x].authority can contain + //- Organization + resourceRaw.protocolApplied?.map((protocolApplied) => { + resourceRefs.push(protocolApplied.authority?.reference) + }) + break + case "Location": + // managingOrganization can contain + //- Organization + resourceRefs.push(resourceRaw.managingOrganization?.reference) + + // partOf can contain + //- Location + resourceRefs.push(resourceRaw.partOf?.reference) + + break + case "MedicationRequest": + // reported.reportedReference can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- RelatedPerson + resourceRefs.push(resourceRaw.reported?.reportedReference?.reference) + + // medication[x] can contain + //- Medication + resourceRefs.push(resourceRaw.reported?.reportedReference?.reference) + + // requester can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- RelatedPerson + //- Device + resourceRefs.push(resourceRaw.requester?.reference) + + // performer can contain + //- Practitioner | PractitionerRole | Organization | Patient | Device | RelatedPerson | CareTeam + resourceRefs.push(resourceRaw.performer?.reference) + // recorder can contain + //- Practitioner | PractitionerRole + resourceRefs.push(resourceRaw.recorder?.reference) + + //TODO: reasonReference + //TODO: basedOn + //TODO: insurance + + // dispenseRequest.performer can contain + //- Organization + resourceRefs.push(resourceRaw.dispenseRequest?.performer?.reference) + break + case "Observation": + //basedOn[x] can contain + //- CarePlan | DeviceRequest | ImmunizationRecommendation | MedicationRequest | NutritionOrder | ServiceRequest + resourceRaw.basedOn?.map((basedOn) => { + resourceRefs.push(basedOn.reference) + }) + + // partOf[x] can contain + //- MedicationAdministration | MedicationDispense | MedicationStatement | Procedure | Immunization | ImagingStudy + resourceRaw.partOf?.map((partOf) => { + resourceRefs.push(partOf.reference) + }) + // performer[x] can contain + //- Practitioner | PractitionerRole | Organization | CareTeam | Patient | RelatedPerson + resourceRaw.performer?.map((performer) => { + resourceRefs.push(performer.reference) + }) + // device can contain + //- Device | DeviceMetric + resourceRefs.push(resourceRaw.device?.reference) + + break + case "PractitionerRole": + // practitioner can contain + //- Practitioner + resourceRefs.push(resourceRaw.practitioner?.reference) + + //organization can contain + //- Organization + resourceRefs.push(resourceRaw.organization?.reference) + + //location can contain + //- Location + resourceRefs.push(resourceRaw.location?.reference) + + //TODO: healthcareService + //TODO: endpoint + break + case "ServiceRequest": + // basedOn[x] can contain + //- CarePlan | ServiceRequest | MedicationRequest + resourceRaw.basedOn?.map((basedOn) => { + resourceRefs.push(basedOn.reference) + }) + + //requester can contain + //- Practitioner + //- Organization + //- Patient + //- PractitionerRole + //- RelatedPerson + //- Device + resourceRefs.push(resourceRaw.requester?.reference) + + //performer[x] can contain + //- Practitioner | PractitionerRole | Organization | CareTeam | HealthcareService | Patient | Device | RelatedPerson + resourceRaw.performer?.map((performer) => { + resourceRefs.push(performer.reference) + }) + + //locationReference[x] an contain + //-Location + resourceRaw.locationReference?.map((locationReference) => { + resourceRefs.push(locationReference.reference) + }) + + //reasonReference[x] can contain + //-Condition + //-Observation + //-DiagnosticReport + //-DocumentReference + resourceRaw.reasonReference?.map((reasonReference) => { + resourceRefs.push(reasonReference.reference) + }) + + //insurance[x] can contain + //- Coverage | ClaimResponse + resourceRaw.insurance?.map((insurance) => { + resourceRefs.push(insurance.reference) + }) + break + } + + // remove all null values, remove all duplicates + let cleanResourceRefs = resourceRefs.filter(i => !(typeof i === 'undefined' || i === null)); + cleanResourceRefs = [...new Set(cleanResourceRefs)] + + return cleanResourceRefs + } + /** * This function is used to sync all resources from a Bundle file. Not applicable to this Client * @param db