Skip to content

Commit

Permalink
Merge branch 'main' into service-account
Browse files Browse the repository at this point in the history
  • Loading branch information
pauljohanneskraft authored Oct 3, 2024
2 parents 1d7326a + 9c10e94 commit 2c21004
Show file tree
Hide file tree
Showing 17 changed files with 102 additions and 39 deletions.
1 change: 1 addition & 0 deletions functions/src/models/medicationRequestContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@stanfordbdhg/engagehf-models'

export interface MedicationRequestContext {
lastUpdate: Date
request: FHIRMedicationRequest
requestReference: FHIRReference
drug: FHIRMedication
Expand Down
1 change: 1 addition & 0 deletions functions/src/services/database/databaseService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { type CollectionsService } from './collections'
export interface Document<Content> {
id: string
path: string
lastUpdate: Date
content: Content
}

Expand Down
11 changes: 9 additions & 2 deletions functions/src/services/database/firestoreService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class FirestoreService implements DatabaseService {
return collection.docs.map((doc) => ({
id: doc.id,
path: doc.ref.path,
lastUpdate: doc.updateTime.toDate(),
content: doc.data(),
}))
}
Expand All @@ -53,8 +54,14 @@ export class FirestoreService implements DatabaseService {
const ref = reference(this.collectionsService.value)
const doc = await ref.get()
const data = doc.exists ? doc.data() : undefined
return doc.exists && data ?
{ id: doc.id, path: doc.ref.path, content: data }
return doc.exists && data !== undefined ?
{
id: doc.id,
path: doc.ref.path,
// `lastUpdate` should not be undefined in this case
lastUpdate: doc.updateTime?.toDate() ?? doc.readTime.toDate(),
content: data,
}
: undefined
}

Expand Down
10 changes: 5 additions & 5 deletions functions/src/services/medication/databaseMedicationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,9 @@ export class DatabaseMedicationService implements MedicationService {
// Methods - Medication Request Context

async getContext(
request: FHIRMedicationRequest,
reference: FHIRReference,
request: Document<FHIRMedicationRequest>,
): Promise<MedicationRequestContext> {
const drugReference = request.medicationReference
const drugReference = request.content.medicationReference
if (drugReference === undefined) throw new Error('Drug reference not found')
const drug = (await this.getReference(drugReference))?.content
if (drug === undefined)
Expand All @@ -61,8 +60,9 @@ export class DatabaseMedicationService implements MedicationService {
`Medication class not found at ${medicationClassReference.reference}`,
)
return {
requestReference: reference,
request,
lastUpdate: request.lastUpdate,
requestReference: { reference: request.path },
request: request.content,
drugReference,
drug,
medicationReference,
Expand Down
3 changes: 1 addition & 2 deletions functions/src/services/medication/medicationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ export interface MedicationService {
// Medication Request Context

getContext(
request: FHIRMedicationRequest,
reference: FHIRReference,
request: Document<FHIRMedicationRequest>,
): Promise<MedicationRequestContext>

// Medication Classes
Expand Down
1 change: 1 addition & 0 deletions functions/src/services/message/defaultMessageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export class DefaultMessageService implements MessageService {
transaction.set(newMessageRef, message)
const document: Document<UserMessage> = {
id: newMessageRef.id,
lastUpdate: new Date(),
path: newMessageRef.path,
content: message,
}
Expand Down
5 changes: 5 additions & 0 deletions functions/src/services/patient/patientService.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class MockPatientService implements PatientService {
): Promise<Document<FHIRAppointment> | undefined> {
return {
id: '123',
lastUpdate: new Date(),
path: `users/${userId}/appointments/123`,
content: FHIRAppointment.create({
userId,
Expand Down Expand Up @@ -82,6 +83,7 @@ export class MockPatientService implements PatientService {
const values: UserMedicationRecommendation[] = []
return values.map((value, index) => ({
id: index.toString(),
lastUpdate: new Date(),
path: `users/${userId}/medicationRecommendations/${index}`,
content: value,
}))
Expand All @@ -99,6 +101,7 @@ export class MockPatientService implements PatientService {
]
return values.map((value, index) => ({
id: index.toString(),
lastUpdate: new Date(),
path: `users/${userId}/medicationRequests/${index}`,
content: value,
}))
Expand Down Expand Up @@ -243,6 +246,7 @@ export class MockPatientService implements PatientService {
): Promise<Array<Document<FHIRQuestionnaireResponse>>> {
return [mockQuestionnaireResponse()].map((value, index) => ({
id: index.toString(),
lastUpdate: new Date(),
path: `users/${userId}/questionnaireResponses/${index}`,
content: value,
}))
Expand Down Expand Up @@ -296,6 +300,7 @@ export class MockPatientService implements PatientService {
]
return values.map((value, index) => ({
id: index.toString(),
lastUpdate: new Date(),
path: `users/${userId}/symptomScores/${index}`,
content: value,
}))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,12 @@ describe('RecommendationService', () => {
].flatMap((x) => (x ? [x] : []))

const requestContexts = await Promise.all(
medicationRequests.map(async (medicationRequest) =>
medicationService.getContext(medicationRequest, {
reference: '',
medicationRequests.map(async (medicationRequest, index) =>
medicationService.getContext({
id: index.toString(),
path: `users/0/medicationRequests/${index}`,
lastUpdate: new Date(),
content: medicationRequest,
}),
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,11 @@ describe('BetaBlockerRecommender', () => {
frequencyPerDay: 1,
quantity: 1,
})
contextBelowTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
contextBelowTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
})

Expand All @@ -210,8 +213,11 @@ describe('BetaBlockerRecommender', () => {
frequencyPerDay: 1,
quantity: 2,
})
const contextAtTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
const contextAtTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
const result = recommender.compute({
requests: [contextAtTarget],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ describe('DiureticRecommender', () => {
describe('On furosemide', () => {
it('correctly keeps existing medication request', async () => {
const existingMedication: MedicationRequestContext = {
lastUpdate: new Date(),
requestReference: {
reference:
'users/mockPatient/medicationRequests/mockMedicationRequest',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,11 @@ describe('MraRecommender', () => {
frequencyPerDay: 1,
quantity: 1,
})
contextBelowTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
contextBelowTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
})

Expand All @@ -178,8 +181,11 @@ describe('MraRecommender', () => {
frequencyPerDay: 2,
quantity: 1,
})
const contextAtTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
const contextAtTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
const result = recommender.compute({
requests: [contextAtTarget],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,11 @@ describe('RasiRecommender', () => {
frequencyPerDay: 1,
quantity: 1,
})
contextBelowTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
contextBelowTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
})

Expand All @@ -288,8 +291,11 @@ describe('RasiRecommender', () => {
frequencyPerDay: 2,
quantity: 2,
})
const contextAtTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
const contextAtTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
const result = recommender.compute({
requests: [contextAtTarget],
Expand Down Expand Up @@ -525,8 +531,11 @@ describe('RasiRecommender', () => {
frequencyPerDay: 1,
quantity: 1,
})
contextBelowTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
contextBelowTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
})

Expand All @@ -536,8 +545,11 @@ describe('RasiRecommender', () => {
frequencyPerDay: 2,
quantity: 2,
})
const contextAtTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
const contextAtTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
const result = recommender.compute({
requests: [contextAtTarget],
Expand Down
15 changes: 13 additions & 2 deletions functions/src/services/recommendation/recommenders/recommender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export abstract class Recommender {
protected isTargetDailyDoseReached(
currentMedication: MedicationRequestContext[],
): boolean {
// TODO: Make sure that there is only one medication involved!
const medication = currentMedication.at(0)?.medication
if (!medication) throw new Error('Medication is missing')

Expand All @@ -77,12 +76,24 @@ export abstract class Recommender {
requests: MedicationRequestContext[],
references: MedicationClassReference[],
): MedicationRequestContext[] {
return requests.filter((request) =>
const validContexts = requests.filter((request) =>
references.some(
(reference) =>
request.medicationClassReference.reference === reference.toString(),
),
)
const latestContext =
validContexts.length > 0 ?
validContexts.reduce(
(acc, context) =>
acc.lastUpdate < context.lastUpdate ? context : acc,
validContexts[0],
)
: undefined
return validContexts.filter(
(context) =>
context.medicationReference === latestContext?.medicationReference,
)
}

protected medianValue(observations: Observation[]): number | undefined {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,11 @@ describe('Sglt2iRecommender', () => {
frequencyPerDay: 1,
quantity: 1,
})
contextBelowTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
contextBelowTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
})

Expand All @@ -197,8 +200,11 @@ describe('Sglt2iRecommender', () => {
frequencyPerDay: 2,
quantity: 1,
})
const contextAtTarget = await medicationService.getContext(request, {
reference: 'users/mockUser/medicationRequests/someMedicationRequest',
const contextAtTarget = await medicationService.getContext({
id: 'someMedicationRequest',
path: 'users/mockUser/medicationRequests/someMedicationRequest',
lastUpdate: new Date(),
content: request,
})
const result = recommender.compute({
requests: [contextAtTarget],
Expand Down
6 changes: 1 addition & 5 deletions functions/src/services/trigger/triggerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,11 +550,7 @@ export class TriggerService {
)

const requestContexts = await Promise.all(
requests.map(async (document) =>
medicationService.getContext(document.content, {
reference: `users/${userId}/medicationRequests/${document.id}`,
}),
),
requests.map(async (document) => medicationService.getContext(document)),
)

logger.debug(
Expand Down
3 changes: 3 additions & 0 deletions functions/src/services/user/userService.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class MockUserService implements UserService {
return {
id: '1',
path: 'invitations/1',
lastUpdate: new Date(),
content: new Invitation({
user: new UserRegistration({
type: UserType.patient,
Expand Down Expand Up @@ -105,6 +106,7 @@ export class MockUserService implements UserService {
return {
id: organizationId,
path: 'organizations/' + organizationId,
lastUpdate: new Date(),
content: new Organization({
name: 'Stanford University',
contactName: 'Alex Sandhu, MD',
Expand All @@ -129,6 +131,7 @@ export class MockUserService implements UserService {
return {
id: userId,
path: 'users/' + userId,
lastUpdate: new Date(),
content: new User({
type: UserType.clinician,
dateOfBirth: new Date('1970-01-02'),
Expand Down
5 changes: 5 additions & 0 deletions functions/src/tests/mocks/firestore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import {
Timestamp,
type FirestoreDataConverter,
type QueryDocumentSnapshot,
} from 'firebase-admin/firestore'
Expand Down Expand Up @@ -130,6 +131,7 @@ class MockFirestoreCollectionRef extends MockFirestoreRef {
id: key,
exists: true,
ref: this.doc(key as string) as any,
updateTime: Timestamp.now(),
data: () => value,
})
})
Expand Down Expand Up @@ -181,6 +183,7 @@ class MockFirestoreConvertedCollectionRef<
exists: doc.exists,
id: doc.id,
ref: doc.ref,
updateTime: doc.updateTime,
data: () => newData,
}
})
Expand Down Expand Up @@ -292,6 +295,7 @@ class MockFirestoreDocRef extends MockFirestoreRef {
exists: result !== undefined,
id: pathComponents[pathComponents.length - 1],
ref: this as any,
updateTime: Timestamp.now(),
data: () => result as any,
}
}
Expand Down Expand Up @@ -369,6 +373,7 @@ class MockFirestoreConvertedDocRef<T> extends MockFirestoreDocRef {
exists: result.exists,
id: result.id,
ref: result.ref,
updateTime: result.updateTime,
data: () => data,
}
result.data = () =>
Expand Down

0 comments on commit 2c21004

Please sign in to comment.