From b7645047686156d9e38ddd9362ebe733e82ad8e7 Mon Sep 17 00:00:00 2001 From: Rafael Leite <2132564+leite08@users.noreply.github.com> Date: Mon, 21 Apr 2025 12:52:22 -0300 Subject: [PATCH 1/3] refactor(api): only load the bundle when converting Ref eng-141 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com> --- .../medical/patient/consolidated-recreate.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/api/src/command/medical/patient/consolidated-recreate.ts b/packages/api/src/command/medical/patient/consolidated-recreate.ts index 5bd81d7a8e..305a777946 100644 --- a/packages/api/src/command/medical/patient/consolidated-recreate.ts +++ b/packages/api/src/command/medical/patient/consolidated-recreate.ts @@ -1,5 +1,7 @@ import { ConsolidationConversionType } from "@metriport/api-sdk"; import { deleteConsolidated } from "@metriport/core/command/consolidated/consolidated-delete"; +import { ConsolidatedSnapshotRequestSync } from "@metriport/core/command/consolidated/get-snapshot"; +import { buildConsolidatedSnapshotConnector } from "@metriport/core/command/consolidated/get-snapshot-factory"; import { Patient } from "@metriport/core/domain/patient"; import { processAsyncError } from "@metriport/core/util/error/shared"; import { out } from "@metriport/core/util/log"; @@ -40,7 +42,16 @@ export async function recreateConsolidated({ processAsyncError(`Failed to delete consolidated bundle`, log)(err); } try { - await getConsolidated({ patient, conversionType }); + if (conversionType) { + await getConsolidated({ patient, conversionType }); + } else { + const payload: ConsolidatedSnapshotRequestSync = { + patient, + isAsync: false, + }; + const connector = buildConsolidatedSnapshotConnector(); + await connector.execute(payload); + } if (isDq) { createResourceDiffBundles({ cxId: patient.cxId, From 4f84264f4d9df91c0cb36a61e8f335fbb72a59db Mon Sep 17 00:00:00 2001 From: Rafael Leite <2132564+leite08@users.noreply.github.com> Date: Wed, 30 Apr 2025 16:26:30 -0300 Subject: [PATCH 2/3] refactor: move analytics to the actual consolidate functions Ref eng-141 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com> --- .../medical/patient/consolidated-get.ts | 44 +++---------------- .../medical/patient/convert-fhir-bundle.ts | 11 +++++ .../consolidated/get-snapshot-local.ts | 23 +++++++--- 3 files changed, 35 insertions(+), 43 deletions(-) diff --git a/packages/api/src/command/medical/patient/consolidated-get.ts b/packages/api/src/command/medical/patient/consolidated-get.ts index ae9e8031f5..d500b669b9 100644 --- a/packages/api/src/command/medical/patient/consolidated-get.ts +++ b/packages/api/src/command/medical/patient/consolidated-get.ts @@ -18,7 +18,6 @@ import { analytics, EventTypes } from "@metriport/core/external/analytics/postho import { out } from "@metriport/core/util"; import { uuidv7 } from "@metriport/core/util/uuid-v7"; import { emptyFunction } from "@metriport/shared"; -import { elapsedTimeFromNow } from "@metriport/shared/common/date"; import { SearchSetBundle } from "@metriport/shared/medical"; import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; @@ -42,8 +41,6 @@ dayjs.extend(duration); export type GetConsolidatedParams = { patient: Patient; - bundle?: SearchSetBundle; - requestId?: string; documentIds?: string[]; } & GetConsolidatedFilters; @@ -246,9 +243,7 @@ export async function getConsolidated({ resources, dateFrom, dateTo, - requestId, conversionType, - bundle, }: GetConsolidatedParams): Promise { const { log } = out(`API getConsolidated - cxId ${patient.cxId}, patientId ${patient.id}`); const filters = { @@ -258,34 +253,16 @@ export async function getConsolidated({ conversionType, }; try { - if (!bundle) { - bundle = await getConsolidatedPatientData({ - patient, - resources, - dateFrom, - dateTo, - }); - } + let bundle = await getConsolidatedPatientData({ + patient, + resources, + dateFrom, + dateTo, + }); bundle.entry = filterOutPrelimDocRefs(bundle.entry); bundle.total = bundle.entry?.length ?? 0; const hasResources = bundle.entry && bundle.entry.length > 0; const shouldCreateMedicalRecord = conversionType && conversionType != "json" && hasResources; - const currentConsolidatedProgress = patient.data.consolidatedQueries?.find( - q => q.requestId === requestId - ); - - const defaultAnalyticsProps = { - distinctId: patient.cxId, - event: EventTypes.consolidatedQuery, - properties: { - patientId: patient.id, - conversionType: "bundle", - duration: elapsedTimeFromNow(currentConsolidatedProgress?.startedAt), - resourceCount: bundle.entry?.length, - }, - }; - - analytics(defaultAnalyticsProps); if (shouldCreateMedicalRecord) { // If we need to convert to medical record, we also have to update the resulting @@ -298,15 +275,6 @@ export async function getConsolidated({ dateTo, conversionType, }); - - analytics({ - ...defaultAnalyticsProps, - properties: { - ...defaultAnalyticsProps.properties, - duration: elapsedTimeFromNow(currentConsolidatedProgress?.startedAt), - conversionType, - }, - }); } if (conversionType === "json" && hasResources) { diff --git a/packages/api/src/command/medical/patient/convert-fhir-bundle.ts b/packages/api/src/command/medical/patient/convert-fhir-bundle.ts index c218a28c68..98c84fccd1 100644 --- a/packages/api/src/command/medical/patient/convert-fhir-bundle.ts +++ b/packages/api/src/command/medical/patient/convert-fhir-bundle.ts @@ -11,6 +11,7 @@ import { createSandboxMRSummaryFileName, } from "@metriport/core/domain/medical-record-summary"; import { Patient } from "@metriport/core/domain/patient"; +import { analytics, EventTypes } from "@metriport/core/external/analytics/posthog"; import { getLambdaResultPayload, makeLambdaClient } from "@metriport/core/external/aws/lambda"; import { makeS3Client, S3Utils } from "@metriport/core/external/aws/s3"; import { out } from "@metriport/core/util"; @@ -80,6 +81,16 @@ export async function handleBundleToMedicalRecord({ newBundle.entry = []; newBundle.total = 0; } + + analytics({ + distinctId: patient.cxId, + event: EventTypes.consolidatedQuery, + properties: { + patientId: patient.id, + conversionType, + resourceCount: newBundle.entry?.length, + }, + }); return newBundle; } diff --git a/packages/core/src/command/consolidated/get-snapshot-local.ts b/packages/core/src/command/consolidated/get-snapshot-local.ts index d4260ae3ec..62b7ec989c 100644 --- a/packages/core/src/command/consolidated/get-snapshot-local.ts +++ b/packages/core/src/command/consolidated/get-snapshot-local.ts @@ -8,6 +8,7 @@ import { import { elapsedTimeFromNow } from "@metriport/shared/common/date"; import { SearchSetBundle } from "@metriport/shared/medical"; import axios from "axios"; +import { analytics, EventTypes } from "../../external/analytics/posthog"; import { checkBundle } from "../../external/fhir/bundle/qa"; import { getConsolidatedFhirBundle as getConsolidatedFromFhirServer } from "../../external/fhir/consolidated/consolidated"; import { deduplicate } from "../../external/fhir/consolidated/deduplicate"; @@ -60,8 +61,10 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC bundle: dedupedBundle, }); + const resultBundle = normalizedBundle; + try { - checkBundle(normalizedBundle, cxId, patientId); + checkBundle(resultBundle, cxId, patientId); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { const msg = "Bundle contains invalid data"; @@ -72,7 +75,7 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC uploadConsolidatedSnapshotToS3({ ...params, s3BucketName: this.bucketName, - bundle: dedupedBundle, + bundle: resultBundle, type: "invalid", }); } catch (error) { @@ -81,7 +84,7 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC throw new MetriportError(msg, error, additionalInfo); } - const [, dedupedS3Info] = await Promise.all([ + const [, , resultS3Info] = await Promise.all([ uploadConsolidatedSnapshotToS3({ ...params, s3BucketName: this.bucketName, @@ -97,12 +100,12 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC uploadConsolidatedSnapshotToS3({ ...params, s3BucketName: this.bucketName, - bundle: normalizedBundle, + bundle: resultBundle, type: "normalized", }), ]); - const { bucket, key } = dedupedS3Info; + const { bucket, key } = resultS3Info; const info = { bundleLocation: bucket, bundleFilename: key, @@ -120,6 +123,16 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC }); } + analytics({ + distinctId: params.patient.cxId, + event: EventTypes.consolidatedQuery, + properties: { + patientId: params.patient.id, + conversionType: "bundle", + resourceCount: resultBundle.entry?.length, + }, + }); + return info; } } From 65acf46abad0b8bebe7f5edf31fb5299d868f0e9 Mon Sep 17 00:00:00 2001 From: Rafael Leite <2132564+leite08@users.noreply.github.com> Date: Wed, 30 Apr 2025 19:25:43 -0300 Subject: [PATCH 3/3] refactor: re-add bundle + requestId to getConsolidated Ref eng-141 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com> --- .../medical/patient/consolidated-get.ts | 23 ++++++++++++++----- .../medical/patient/consolidated-recreate.ts | 2 +- .../medical/patient/convert-fhir-bundle.ts | 7 +++++- .../consolidated/get-snapshot-local.ts | 12 ++++++---- packages/core/src/domain/patient.ts | 7 ++++++ 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/packages/api/src/command/medical/patient/consolidated-get.ts b/packages/api/src/command/medical/patient/consolidated-get.ts index d500b669b9..d86c64edc3 100644 --- a/packages/api/src/command/medical/patient/consolidated-get.ts +++ b/packages/api/src/command/medical/patient/consolidated-get.ts @@ -41,6 +41,8 @@ dayjs.extend(duration); export type GetConsolidatedParams = { patient: Patient; + bundle?: SearchSetBundle; + requestId?: string; documentIds?: string[]; } & GetConsolidatedFilters; @@ -49,6 +51,7 @@ type GetConsolidatedPatientData = { resources?: ResourceTypeForConsolidation[]; dateFrom?: string; dateTo?: string; + requestId?: string; fromDashboard?: boolean; // TODO 2215 Remove this when we have contributed data as part of get consolidated (from S3) forceDataFromFhir?: boolean; @@ -243,7 +246,9 @@ export async function getConsolidated({ resources, dateFrom, dateTo, + requestId, conversionType, + bundle, }: GetConsolidatedParams): Promise { const { log } = out(`API getConsolidated - cxId ${patient.cxId}, patientId ${patient.id}`); const filters = { @@ -253,12 +258,15 @@ export async function getConsolidated({ conversionType, }; try { - let bundle = await getConsolidatedPatientData({ - patient, - resources, - dateFrom, - dateTo, - }); + if (!bundle) { + bundle = await getConsolidatedPatientData({ + patient, + requestId, + resources, + dateFrom, + dateTo, + }); + } bundle.entry = filterOutPrelimDocRefs(bundle.entry); bundle.total = bundle.entry?.length ?? 0; const hasResources = bundle.entry && bundle.entry.length > 0; @@ -270,6 +278,7 @@ export async function getConsolidated({ bundle = await handleBundleToMedicalRecord({ bundle, patient, + requestId, resources, dateFrom, dateTo, @@ -378,6 +387,7 @@ async function uploadConsolidatedJsonAndReturnUrl({ */ export async function getConsolidatedPatientData({ patient, + requestId, resources, dateFrom, dateTo, @@ -387,6 +397,7 @@ export async function getConsolidatedPatientData({ const payload: ConsolidatedSnapshotRequestSync = { patient, resources, + requestId, dateFrom, dateTo, isAsync: false, diff --git a/packages/api/src/command/medical/patient/consolidated-recreate.ts b/packages/api/src/command/medical/patient/consolidated-recreate.ts index 305a777946..2db3ce324c 100644 --- a/packages/api/src/command/medical/patient/consolidated-recreate.ts +++ b/packages/api/src/command/medical/patient/consolidated-recreate.ts @@ -7,7 +7,7 @@ import { processAsyncError } from "@metriport/core/util/error/shared"; import { out } from "@metriport/core/util/log"; import { ResourceDiffDirection } from "@metriport/shared/interface/external/ehr/resource-diff"; import { createResourceDiffBundles } from "../../../external/ehr/create-resource-diff-bundles"; -import { getConsolidated } from "../patient/consolidated-get"; +import { getConsolidated } from "./consolidated-get"; /** * Recreates the consolidated bundle for a patient. diff --git a/packages/api/src/command/medical/patient/convert-fhir-bundle.ts b/packages/api/src/command/medical/patient/convert-fhir-bundle.ts index 98c84fccd1..9d7306132c 100644 --- a/packages/api/src/command/medical/patient/convert-fhir-bundle.ts +++ b/packages/api/src/command/medical/patient/convert-fhir-bundle.ts @@ -10,11 +10,12 @@ import { createMRSummaryFileName, createSandboxMRSummaryFileName, } from "@metriport/core/domain/medical-record-summary"; -import { Patient } from "@metriport/core/domain/patient"; +import { getConsolidatedQueryByRequestId, Patient } from "@metriport/core/domain/patient"; import { analytics, EventTypes } from "@metriport/core/external/analytics/posthog"; import { getLambdaResultPayload, makeLambdaClient } from "@metriport/core/external/aws/lambda"; import { makeS3Client, S3Utils } from "@metriport/core/external/aws/s3"; import { out } from "@metriport/core/util"; +import { elapsedTimeFromNow } from "@metriport/shared/common/date"; import { SearchSetBundle } from "@metriport/shared/medical"; import dayjs from "dayjs"; import duration from "dayjs/plugin/duration"; @@ -40,6 +41,7 @@ export const emptyMetaProp = "na"; export async function handleBundleToMedicalRecord({ bundle, patient, + requestId, resources, dateFrom, dateTo, @@ -47,6 +49,7 @@ export async function handleBundleToMedicalRecord({ }: { bundle: Bundle; patient: Pick; + requestId?: string; resources?: ResourceTypeForConsolidation[]; dateFrom?: string; dateTo?: string; @@ -82,12 +85,14 @@ export async function handleBundleToMedicalRecord({ newBundle.total = 0; } + const currentConsolidatedProgress = getConsolidatedQueryByRequestId(patient, requestId); analytics({ distinctId: patient.cxId, event: EventTypes.consolidatedQuery, properties: { patientId: patient.id, conversionType, + duration: elapsedTimeFromNow(currentConsolidatedProgress?.startedAt), resourceCount: newBundle.entry?.length, }, }); diff --git a/packages/core/src/command/consolidated/get-snapshot-local.ts b/packages/core/src/command/consolidated/get-snapshot-local.ts index 62b7ec989c..f125589f81 100644 --- a/packages/core/src/command/consolidated/get-snapshot-local.ts +++ b/packages/core/src/command/consolidated/get-snapshot-local.ts @@ -8,6 +8,7 @@ import { import { elapsedTimeFromNow } from "@metriport/shared/common/date"; import { SearchSetBundle } from "@metriport/shared/medical"; import axios from "axios"; +import { getConsolidatedQueryByRequestId } from "../../domain/patient"; import { analytics, EventTypes } from "../../external/analytics/posthog"; import { checkBundle } from "../../external/fhir/bundle/qa"; import { getConsolidatedFhirBundle as getConsolidatedFromFhirServer } from "../../external/fhir/consolidated/consolidated"; @@ -34,12 +35,13 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC async execute( params: ConsolidatedSnapshotRequestSync | ConsolidatedSnapshotRequestAsync ): Promise { - const { cxId, id: patientId } = params.patient; + const { patient, requestId } = params; + const { cxId, id: patientId } = patient; const { log } = out(`ConsolidatedSnapshotConnectorLocal cx ${cxId} pat ${patientId}`); const originalBundle = await getBundle(params); - const fhirPatient = patientToFhir(params.patient); + const fhirPatient = patientToFhir(patient); const patientEntry = buildBundleEntry(fhirPatient); originalBundle.entry = [patientEntry, ...(originalBundle.entry ?? [])]; originalBundle.total = originalBundle.entry.length; @@ -123,12 +125,14 @@ export class ConsolidatedSnapshotConnectorLocal implements ConsolidatedSnapshotC }); } + const currentConsolidatedProgress = getConsolidatedQueryByRequestId(patient, requestId); analytics({ - distinctId: params.patient.cxId, + distinctId: cxId, event: EventTypes.consolidatedQuery, properties: { - patientId: params.patient.id, + patientId: patientId, conversionType: "bundle", + duration: elapsedTimeFromNow(currentConsolidatedProgress?.startedAt), resourceCount: resultBundle.entry?.length, }, }); diff --git a/packages/core/src/domain/patient.ts b/packages/core/src/domain/patient.ts index e8e61b2f03..b0a67180b3 100644 --- a/packages/core/src/domain/patient.ts +++ b/packages/core/src/domain/patient.ts @@ -124,3 +124,10 @@ export function createDriversLicensePersonalIdentifier( }; return personalIdentifier; } + +export function getConsolidatedQueryByRequestId( + patient: Pick, + requestId: string | undefined +): ConsolidatedQuery | undefined { + return patient.data.consolidatedQueries?.find(q => q.requestId === requestId); +}