Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
30 changes: 29 additions & 1 deletion src/fhir/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ export interface MetRequirements extends Document {
metRequirementId: any;
}

export interface PrescriptionEvent {
medicationRequestReference: string;
prescriberId: string;
pharmacyId?: string;
timestamp: Date;
originatingFhirServer?: string;
caseStatusAtTime: string;
}

export interface RemsCase extends Document {
case_number: string;
status: string;
Expand All @@ -39,6 +48,11 @@ export interface RemsCase extends Document {
patientFirstName: string;
patientLastName: string;
patientDOB: string;
currentPrescriberId?: string;
currentPharmacyId?: string;
prescriberHistory: string[];
pharmacyHistory: string[];
prescriptionEvents: PrescriptionEvent[];
medicationRequestReference?: string;
originatingFhirServer?: string;
metRequirements: Partial<MetRequirements>[];
Expand Down Expand Up @@ -98,6 +112,20 @@ const remsCaseCollectionSchema = new Schema<RemsCase>({
patientLastName: { type: String },
patientDOB: { type: String },
drugCode: { type: String },
currentPrescriberId: { type: String },
currentPharmacyId: { type: String },
prescriberHistory: [{ type: String }],
pharmacyHistory: [{ type: String }],
prescriptionEvents: [
{
medicationRequestReference: { type: String },
prescriberId: { type: String },
pharmacyId: { type: String },
timestamp: { type: Date },
originatingFhirServer: { type: String },
caseStatusAtTime: { type: String }
}
],
medicationRequestReference: { type: String },
originatingFhirServer: { type: String },
metRequirements: [
Expand All @@ -111,4 +139,4 @@ const remsCaseCollectionSchema = new Schema<RemsCase>({
]
});

export const remsCaseCollection = model<RemsCase>('RemsCaseCollection', remsCaseCollectionSchema);
export const remsCaseCollection = model<RemsCase>('RemsCaseCollection', remsCaseCollectionSchema);
45 changes: 42 additions & 3 deletions src/hooks/hookResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import axios from 'axios';
import { ServicePrefetch } from '../rems-cds-hooks/resources/CdsService';
import { hydrate } from '../rems-cds-hooks/prefetch/PrefetchHydrator';
import { createNewRemsCaseFromCDSHook } from '../lib/etasu';
import { createNewRemsCaseFromCDSHook, handleStakeholderChangesAndRecordEvent } from '../lib/etasu';

type HandleCallback = (
res: any,
Expand Down Expand Up @@ -406,11 +406,50 @@
drugCode: code
});

// If case exists, check for stakeholder changes and record prescription event
if (remsCase && drug && fhirServer) {
const practitionerReference = request.requester?.reference || '';
const pharmacistReference = pharmacy?.id ? `HealthcareService/${pharmacy.id}` : '';
const medicationRequestReference = `${request.resourceType}/${request.id}`;

const prescriberChanged = remsCase.currentPrescriberId !== practitionerReference;
const pharmacyChanged =
pharmacistReference && remsCase.currentPharmacyId !== pharmacistReference;

if (prescriberChanged || pharmacyChanged) {
try {
const updatedCase = await handleStakeholderChangesAndRecordEvent(
remsCase,
drug,
practitionerReference,
pharmacistReference,
medicationRequestReference,
fhirServer
);
console.log(`Updated case ${updatedCase?.case_number} with stakeholder changes`);
} catch (error) {
console.error('Failed to handle stakeholder changes:', error);
}
} else {
// Record prescription event even if no stakeholder change
remsCase.prescriptionEvents.push({
medicationRequestReference: medicationRequestReference,
prescriberId: practitionerReference,
pharmacyId: pharmacistReference,
timestamp: new Date(),
originatingFhirServer: fhirServer,
caseStatusAtTime: remsCase.status
});
remsCase.medicationRequestReference = medicationRequestReference;
await remsCase.save();
}
}

// If no REMS case exists and drug has requirements, create case with all requirements unmet
if (!remsCase && drug && patient && request) {
const requiresCase = drug.requirements.some(req => req.requiredToDispense);

if (requiresCase && fhirServer) {
if (requiresCase && fhirServer) {
try {
const patientReference = `Patient/${patient.id}`;
const medicationRequestReference = `${request.resourceType}/${request.id}`;
Expand Down Expand Up @@ -871,7 +910,7 @@
hookPrefetch: HookPrefetch | undefined,
_contextRequest: FhirResource | undefined,
resource: FhirResource | undefined,
fhirServer?: string

Check warning on line 913 in src/hooks/hookResources.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

'fhirServer' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 913 in src/hooks/hookResources.ts

View workflow job for this annotation

GitHub Actions / Check tsc, lint, and prettier

'fhirServer' is defined but never used. Allowed unused args must match /^_/u
): Promise<void> => {
const patient = resource?.resourceType === 'Patient' ? resource : undefined;
const medResource = hookPrefetch?.medicationRequests;
Expand Down Expand Up @@ -997,4 +1036,4 @@
]
};
return taskResource;
}
}
30 changes: 15 additions & 15 deletions src/lib/communication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import { Requirement } from '../fhir/models';

const logger = container.get('application');


export async function sendCommunicationToEHR(
remsCase: any,
medication: any,
outstandingRequirements: any[]
): Promise<void> {
try {
logger.info(`Creating Communication for case ${remsCase.case_number}`);

// Create patient object from REMS case
const patient: Patient = {
resourceType: 'Patient',
Expand Down Expand Up @@ -60,9 +59,10 @@ export async function sendCommunicationToEHR(
// Create Tasks for each outstanding requirement
const tasks: Task[] = [];
for (const outstandingReq of outstandingRequirements) {
const requirement = outstandingReq.requirement ||
const requirement =
outstandingReq.requirement ||
medication.requirements.find((r: Requirement) => r.name === outstandingReq.name);

if (requirement && requirement.appContext) {
const questionnaireUrl = requirement.appContext;
const task = createQuestionnaireCompletionTask(
Expand All @@ -80,7 +80,7 @@ export async function sendCommunicationToEHR(
const communication: Communication = {
resourceType: 'Communication',
id: `comm-${uid()}`,
status: 'completed',
status: 'completed',
category: [
{
coding: [
Expand All @@ -92,7 +92,7 @@ export async function sendCommunicationToEHR(
]
}
],
priority: 'urgent',
priority: 'urgent',
subject: {
reference: `Patient/${patient.id}`,
display: `${remsCase.patientFirstName} ${remsCase.patientLastName}`
Expand All @@ -107,7 +107,7 @@ export async function sendCommunicationToEHR(
],
text: 'Outstanding REMS Requirements for Medication Dispensing'
},
sent: new Date().toISOString(),
sent: new Date().toISOString(),
recipient: [
{
reference: medicationRequest.requester?.reference || ''
Expand All @@ -119,8 +119,9 @@ export async function sendCommunicationToEHR(
},
payload: [
{
contentString: `Medication dispensing authorization DENIED for ${remsCase.drugName}.\n\n` +
`The following REMS requirements must be completed:\n\n` +
contentString:
`Medication dispensing authorization DENIED for ${remsCase.drugName}.\n\n` +
'The following REMS requirements must be completed:\n\n' +
outstandingRequirements
.map((req, idx) => `${idx + 1}. ${req.name} (${req.stakeholder})`)
.join('\n') +
Expand All @@ -142,8 +143,8 @@ export async function sendCommunicationToEHR(
};

// Determine EHR endpoint: use originatingFhirServer if available, otherwise default
const ehrEndpoint = remsCase.originatingFhirServer ||
config.fhirServerConfig?.auth?.resourceServer;
const ehrEndpoint =
remsCase.originatingFhirServer || config.fhirServerConfig?.auth?.resourceServer;

if (!ehrEndpoint) {
logger.warn('No EHR endpoint configured, Communication not sent');
Expand All @@ -152,7 +153,7 @@ export async function sendCommunicationToEHR(

// Send Communication to EHR
logger.info(`Sending Communication to EHR: ${ehrEndpoint}`);

const response = await axios.post(`${ehrEndpoint}/Communication`, communication, {
headers: {
'Content-Type': 'application/fhir+json'
Expand All @@ -164,9 +165,8 @@ export async function sendCommunicationToEHR(
} else {
logger.warn(`Unexpected response status from EHR: ${response.status}`);
}

} catch (error: any) {
logger.error(`Failed to send Communication to EHR: ${error.message}`);
throw error;
throw error;
}
}
}
Loading
Loading