8000 feat(ehr): adding athena / elation / healthie to lambda + canvas get resources by thomasyopes · Pull Request #3882 · metriport/metriport · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(ehr): adding athena / elation / healthie to lambda + canvas get resources #3882

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 58 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
839983e
feat(ehr): addng all ehrs to lambda get for resources and appointments
May 20, 2025
4522524
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 20, 2025
dc6ab1d
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 20, 2025
35218fe
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 21, 2025
7fb571f
feat(ehr): adding in the rest of the methods
May 21, 2025
3c09437
feat(ehr): adding some infra
May 21, 2025
e0b3df5
feat(ehr): introducing handlers into the api
May 21, 2025
3c5ee27
feat(ehr): adding s3 permissions
May 21, 2025
588a6aa
feat(ehr): fixing lambdas
May 21, 2025
0d77525
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 28, 2025
1ed5cc8
feat(ehr): fix
May 28, 2025
5926433
feat(ehr): fixes
May 28, 2025
e6fee3b
feat(ehr): fixing typing
May 28, 2025
3ed6648
feat(ehr): fix
May 28, 2025
85e63b1
feat(ehr): fix
May 28, 2025
127996c
feat(ehr): fix
May 28, 2025
427f9a0
feat(ehr): final fix
May 28, 2025
839d305
feat(ehr): simply map
May 29, 2025
3b2567c
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
8ead2ea
feat(ehr): fix
May 29, 2025
7744940
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
0cb1d78
feat(ehr): fix
May 29, 2025
8462774
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
aab2bd3
feat(ehr): fix
May 29, 2025
18d26e0
feat(ehr): fix
May 29, 2025
4beb598
feat(ehr): moving refresh resources off api
May 29, 2025
799dcb4
feat(ehr): remove stuff
May 29, 2025
8c696ae
feat(ehr): fixes
May 29, 2025
ec3b7a2
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
3b98356
feat(ehr): re-using tokens when possible
May 29, 2025
0d80652
feat(ehr): fix
May 29, 2025
5ba5ebd
feat(ehr): tweak
May 29, 2025
51f7d3a
feat(ehr): fix
May 29, 2025
1e25f61
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
9ede6ee
feat(ehr): adding client fetcher
May 29, 2025
2b50ad9
feat(ehr): remove stuff
May 29, 2025
6019d33
feat(ehr): fix
May 29, 2025
7a737e0
feat(ehr): revert
May 29, 2025
ab2207e
feat(ehr): fix
May 29, 2025
7709a14
feat(ehr): fix
May 29, 2025
fd5271d
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 29, 2025
dcfd40f
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 30, 2025
4a34cc4
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
May 30, 2025
1e9d753
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 3, 2025
18ea344
feat(ehr): fixing imports
Jun 4, 2025
41b9edd
feat(ehr): moving secrets to new file
Jun 4, 2025
a3129cc
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 4, 2025
53fbb23
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
e9d7b9f
feat(ehr): fhir validation errors
Jun 5, 2025
c15b826
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
d43019b
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
928a04b
feat(ehr): better naming
Jun 5, 2025
f6588b7
feat(ehr): only add token id if exitss
Jun 5, 2025
85dbf77
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
3592c20
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
f680518
Merge branch '199-elation-contribution-1.5' of https://github.com/met…
Jun 5, 2025
9d9a6a1
Merge branch 'develop' of https://github.com/metriport/metriport into…
Jun 6, 2025
47c2f23
feat(ehr): final fixes1 8000
Jun 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
AE8F
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AthenaHealthApi from "@metriport/core/external/ehr/athenahealth/index";
import { AppointmentMethods } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments";
import { buildEhrGetAppointmentsHandler } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments-factory";
import { buildEhrSyncPatientHandler } from "@metriport/core/external/ehr/command/sync-patient/ehr-sync-patient-factory";
import { executeAsynchronously } from "@metriport/core/util/concurrency";
import { out } from "@metriport/core/util/log";
Expand All @@ -23,7 +24,7 @@ import {
parallelPatients,
parallelPractices,
} from "../../shared/utils/appointment";
import { LookupMode, LookupModes, createAthenaClient } from "../shared";
import { LookupMode, LookupModes, createAthenaClientWithTokenIdAndEnvironment } from "../shared";
import { SyncAthenaPatientIntoMetriportParams } from "./sync-patient";

dayjs.extend(duration);
Expand Down Expand Up @@ -149,11 +150,15 @@ async function getAppointments({
const { log } = out(
`AthenaHealth getAppointments - cxId ${cxId} practiceId ${practiceId} departmentIds ${departmentIds} lookupMode ${lookupMode}`
);
const api = await createAthenaClient({ cxId, practiceId });
const { tokenId, client } = await createAthenaClientWithTokenIdAndEnvironment({
cxId,
practiceId,
});
try {
let appointments = await getAppointmentsFromApi({
api,
tokenId,
cxId,
practiceId,
departmentIds,
lookupMode,
log,
Expand All @@ -168,8 +173,8 @@ async function getAppointments({
return {
cxId,
practiceId,
patientId: api.createPatientId(appointment.patientid),
departmentId: api.createDepartmentId(appointment.departmentid),
patientId: client.createPatientId(appointment.patientid),
departmentId: client.createDepartmentId(appointment.departmentid),
};
}),
};
Expand All @@ -180,44 +185,55 @@ async function getAppointments({
}
}

type GetAppointmentsFromApiParams = Omit<GetAppointmentsParams, "practiceId"> & {
api: AthenaHealthApi;
type GetAppointmentsFromApiParams = GetAppointmentsParams & {
tokenId: string;
log: typeof console.log;
};

async function getAppointmentsFromApi({
api,
tokenId,
cxId,
practiceId,
departmentIds,
lookupMode,
log,
}: GetAppointmentsFromApiParams): Promise<BookedAppointment[]> {
const handler = buildEhrGetAppointmentsHandler();
const handlerParams = {
tokenId,
cxId,
practiceId,
departmentIds,
};
if (lookupMode === LookupModes.Appointments) {
const { startRange, endRange } = getLookForwardTimeRange({
lookForward: appointmentsLookForward,
});
log(`Getting appointments from ${startRange} to ${endRange}`);
return await api.getAppointments({
cxId,
departmentIds,
startAppointmentDate: startRange,
endAppointmentDate: endRange,
return await handler.getAppointments<BookedAppointment>({
...handlerParams,
method: AppointmentMethods.athenaGetAppointments,
fromDate: startRange,
toDate: endRange,
});
}
if (lookupMode === LookupModes.FromSubscription) {
log(`Getting change events since last call`);
return await api.getAppointmentsFromSubscription({ cxId, departmentIds });
return await handler.getAppointments<BookedAppointment>({
...handlerParams,
method: AppointmentMethods.athenaGetAppointmentFromSubscriptionEvents,
});
}
if (lookupMode === LookupModes.FromSubscriptionBackfill) {
const { startRange, endRange } = getLookBackTimeRange({
lookBack: subscriptionBackfillLookBack,
});
log(`Getting already-processed change events from ${startRange} to ${endRange}`);
return await api.getAppointmentsFromSubscription({
cxId,
departmentIds,
startProcessedDate: startRange,
endProcessedDate: endRange,
return await handler.getAppointments<BookedAppointment>({
...handlerParams,
method: AppointmentMethods.athenaGetAppointmentFromSubscriptionEvents,
fromDate: startRange,
toDate: endRange,
});
}
throw new MetriportError("Invalid lookup mode @ AthenaHealth", undefined, { cxId, lookupMode });
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/external/ehr/athenahealth/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { getAthenaEnv } from "@metriport/core/external/ehr/athenahealth/environm
import AthenaHealthApi, { AthenaEnv } from "@metriport/core/external/ehr/athenahealth/index";
import { EhrPerPracticeParams } from "@metriport/core/external/ehr/environment";
import { athenaClientSource } from "@metriport/shared/interface/external/ehr/athenahealth/jwt-token";
import { createEhrClient } from "../shared/utils/client";
import { createEhrClientWithClientCredentials } from "../shared/utils/client";

export async function createAthenaClientWithTokenIdAndEnvironment(
perPracticeParams: EhrPerPracticeParams
): Promise<{ client: AthenaHealthApi; tokenId: string; environment: AthenaEnv }> {
return await createEhrClient<AthenaEnv, AthenaHealthApi>({
return await createEhrClientWithClientCredentials<AthenaEnv, AthenaHealthApi>({
...perPracticeParams,
source: athenaClientSource,
getEnv: { params: undefined, getEnv: getAthenaEnv },
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions packages/api/src/external/ehr/canvas/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { getCanvasEnv } from "@metriport/core/external/ehr/canvas/environment";
import CanvasApi, { CanvasEnv } from "@metriport/core/external/ehr/canvas/index";
import { EhrPerPracticeParams } from "@metriport/core/external/ehr/environment";
import { canvasClientSource } from "@metriport/shared/interface/external/ehr/canvas/jwt-token";
import { createEhrClient } from "../shared/utils/client";
import { createEhrClientWithClientCredentials } from "../shared/utils/client";

export async function createCanvasClientWithTokenIdAndEnvironment(
perPracticeParams: EhrPerPracticeParams
): Promise<{ client: CanvasApi; tokenId: string; environment: CanvasEnv }> {
return await createEhrClient<CanvasEnv, CanvasApi, EhrPerPracticeParams>({
return await createEhrClientWithClientCredentials<CanvasEnv, CanvasApi, EhrPerPracticeParams>({
...perPracticeParams,
source: canvasClientSource,
getEnv: { params: perPracticeParams, getEnv: getCanvasEnv },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { buildEhrSyncPatientHandler } from "@metriport/core/external/ehr/command/sync-patient/ehr-sync-patient-factory";
import { buildElationLinkPatientHandler } from "@metriport/core/external/ehr/elation/command/link-patient/elation-link-patient-factory";
import { AppointmentMethods } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments";
import { buildEhrGetAppointmentsHandler } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments-factory";
import { buildEhrSyncPatientHandler } from "@metriport/core/external/ehr/command/sync-patient/ehr-sync-patient-factory";
import { executeAsynchronously } from "@metriport/core/util/concurrency";
import { out } from "@metriport/core/util/log";
import { capture } from "@metriport/core/util/notifications";
Expand All @@ -8,6 +10,7 @@ import {
ElationSecondaryMappings,
elationSecondaryMappingsSchema,
} from "@metriport/shared/interface/external/ehr/elation/cx-mapping";
import { BookedAppointment } from "@metriport/shared/interface/external/ehr/elation/index";
import { EhrSources } from "@metriport/shared/interface/external/ehr/source";
import dayjs from "dayjs";
import duration from "dayjs/plugin/duration";
Expand All @@ -21,7 +24,7 @@ import {
parallelPatients,
parallelPractices,
} from "../../shared/utils/appointment";
import { createElationClient } from "../shared";
import { createElationClientWithTokenIdAndEnvironment } from "../shared";
import {
CreateOrUpdateElationPatientMetadataParams,
SyncElationPatientIntoMetriportParams,
Expand Down Expand Up @@ -143,14 +146,21 @@ async function getAppointments({
practiceId,
}: GetAppointmentsParams): Promise<{ appointments?: Appointment[]; error?: unknown }> {
const { log } = out(`Elation getAppointments - cxId ${cxId} practiceId ${practiceId}`);
const api = await createElationClient({ cxId, practiceId });
const { tokenId } = await createElationClientWithTokenIdAndEnvironment({
cxId,
practiceId,
});
const { startRange, endRange } = getLookForwardTimeRange({
lookForward: appointmentsLookForward,
});
log(`Getting appointments from ${startRange} to ${endRange}`);
try {
const appointments = await api.getAppointments({
const handler = buildEhrGetAppointmentsHandler();
const appointments = await handler.getAppointments<BookedAppointment>({
method: AppointmentMethods.elationGetAppointments,
tokenId,
cxId,
practiceId,
fromDate: startRange,
toDate: endRange,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/api/src/external/ehr/elation/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Patient as ElationPatient } from "@metriport/shared/interface/external/
import { SubscriptionResource } from "@metriport/shared/interface/external/ehr/elation/subscription";
import dayjs from "dayjs";
import { getCxMappingOrFail } from "../../../command/mapping/cx";
import { createEhrClient } from "../shared/utils/client";
import { createEhrClientWithClientCredentials } from "../shared/utils/client";

export const elationClientJwtTokenSource = "elation-client";
export const elationWebhookJwtTokenSource = "elation-webhook";
Expand Down Expand Up @@ -98,7 +98,7 @@ function getCxIdAndPracticeIdFromElationApplicationId(applicationId: string): {
export async function createElationClientWithTokenIdAndEnvironment(
perPracticeParams: EhrPerPracticeParams
): Promise<{ client: ElationApi; tokenId: string; environment: ElationEnv }> {
return await createEhrClient<ElationEnv, ElationApi, EhrPerPracticeParams>({
return await createEhrClientWithClientCredentials<ElationEnv, ElationApi, EhrPerPracticeParams>({
...perPracticeParams,
source: elationClientJwtTokenSource,
getEnv: { params: perPracticeParams, getEnv: getElationEnv },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AppointmentMethods } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments";
import { buildEhrGetAppointmentsHandler } from "@metriport/core/external/ehr/command/get-appointments/ehr-get-appointments-factory";
import { buildEhrSyncPatientHandler } from "@metriport/core/external/ehr/command/sync-patient/ehr-sync-patient-factory";
import HealthieApi from "@metriport/core/external/ehr/healthie";
import { buildHealthieLinkPatientHandler } from "@metriport/core/external/ehr/healthie/command/link-patient/healthie-link-patient-factory";
import { executeAsynchronously } from "@metriport/core/util/concurrency";
import { out } from "@metriport/core/util/log";
Expand All @@ -24,7 +25,7 @@ import {
parallelPatients,
parallelPractices,
} from "../../shared/utils/appointment";
import { createHealthieClient, LookupMode, LookupModes } from "../shared";
import { LookupMode, LookupModes } from "../shared";
import {
SyncHealthiePatientIntoMetriportParams,
UpdateHealthiePatientQuickNotesParams,
Expand Down Expand Up @@ -175,11 +176,10 @@ async function getAppointments({
const { log } = out(
`Healthie getAppointments - cxId ${cxId} practiceId ${practiceId} lookupMode ${lookupMode}`
);
const api = await createHealthieClient({ cxId, practiceId });
try {
const appointments = await getAppointmentsFromApi({
api,
cxId,
practiceId,
lookupMode,
log,
});
Expand All @@ -195,26 +195,31 @@ async function getAppointments({
}
}

type GetAppointmentsFromApiParams = Omit<GetAppointmentsParams, "practiceId"> & {
api: HealthieApi;
type GetAppointmentsFromApiParams = GetAppointmentsParams & {
log: typeof console.log;
};

async function getAppointmentsFromApi({
api,
cxId,
practiceId,
lookupMode,
log,
}: GetAppointmentsFromApiParams): Promise<AppointmentWithAttendee[]> {
const handler = buildEhrGetAppointmentsHandler();
const handlerParams = {
cxId,
practiceId,
};
if (lookupMode === LookupModes.Appointments) {
const { startRange, endRange } = getLookForwardTimeRange({
lookForward: appointmentsLookForward,
});
log(`Getting appointments from ${startRange} to ${endRange}`);
return await api.getAppointments({
cxId,
startAppointmentDate: startRange,
endAppointmentDate: endRange,
return await handler.getAppointments({
...handlerParams,
method: AppointmentMethods.healthieGetAppointments,
fromDate: startRange,
toDate: endRange,
});
}
if (lookupMode === LookupModes.Appointments48hr) {
Expand All @@ -223,10 +228,11 @@ async function getAppointmentsFromApi({
offset: oneDayOffset,
});
log(`Getting appointments from ${startRange} to ${endRange}`);
return await api.getAppointments({
cxId,
startAppointmentDate: startRange,
endAppointmentDate: endRange,
return await handler.getAppointments({
...handlerParams,
method: AppointmentMethods.healthieGetAppointments,
fromDate: startRange,
toDate: endRange,
});
}
throw new MetriportError("Invalid lookup mode @ Healthie", undefined, { cxId, lookupMode });
Expand Down

This file was deleted.

Loading
0