import type { TFunction } from 'i18next'; import { attachmentUrl, fhirBaseUrl, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework'; import { encounterRepresentation } from '../constants'; import type { AttachmentFieldValue, FHIRObsResource, OpenmrsForm, PatientDeathPayload, PatientIdentifier, PatientProgramPayload, PersonAttribute, } from '../types'; import { isUuid } from '../utils/boolean-utils'; export function saveEncounter(abortController: AbortController, payload, encounterUuid?: string) { const url = encounterUuid ? `${restBaseUrl}/encounter/${encounterUuid}?v=${encounterRepresentation}` : `${restBaseUrl}/encounter?v=${encounterRepresentation}`; return openmrsFetch(url, { headers: { 'Content-Type': 'application/json', }, method: 'POST', body: payload, signal: abortController.signal, }); } export async function createAttachment(patientUuid: string, encounterUUID: string, attachment: AttachmentFieldValue) { const formData = new FormData(); formData.append('fileCaption', attachment.fileDescription); formData.append('patient', patientUuid); if (attachment.file) { formData.append('file', attachment.file, attachment.fileName); } else { formData.append('file', new File([''], attachment.fileName), attachment.fileName); formData.append('base64Content', attachment.base64Content); } formData.append('encounter', encounterUUID); formData.append('formFieldNamespace', attachment.formFieldNamespace); formData.append('formFieldPath', attachment.formFieldPath); return openmrsFetch(`${attachmentUrl}`, { method: 'POST', body: formData, }); } export function getConcept(conceptUuid: string, v: string) { return openmrsFetch(`${restBaseUrl}/concept/${conceptUuid}?v=${v}`).then(({ data }) => data.results); } export function getLocationsByTag(tag: string) { return openmrsFetch(`${restBaseUrl}/location?tag=${tag}&v=custom:(uuid,display)`).then(({ data }) => data.results); } export function getAllLocations() { return openmrsFetch<{ results }>(`${restBaseUrl}/location?v=custom:(uuid,display)`).then(({ data }) => data.results); } export async function getPreviousEncounter(patientUuid: string, encounterType: string) { const query = `patient=${patientUuid}&_sort=-date&_count=1&type=${encounterType}`; let response = await openmrsFetch(`${fhirBaseUrl}/Encounter?${query}`); if (response?.data?.entry?.length) { const latestEncounter = response.data.entry[0].resource.id; response = await openmrsFetch(`${restBaseUrl}/encounter/${latestEncounter}?v=${encounterRepresentation}`); return response.data; } return null; } export async function getLatestObs( patientUuid: string, conceptUuid: string, encounterTypeUuid?: string, ): Promise { let params = `patient=${patientUuid}&code=${conceptUuid}${encounterTypeUuid ? `&encounter.type=${encounterTypeUuid}` : '' }`; // the latest obs params += '&_sort=-date&_count=1'; const { data } = await openmrsFetch(`${fhirBaseUrl}/Observation?${params}`); return data.entry?.length ? data.entry[0].resource : null; } export async function getLatestObsForConceptSet( patientUuid: string, conceptUuid: string, encounterTypeUuid?: string, ): Promise { // First, find the single latest obs to identify the encounter const latestObs = await getLatestObs(patientUuid, conceptUuid, encounterTypeUuid); if (!latestObs) { return []; } const encounterId = latestObs.encounter?.reference?.split('/').pop(); if (!encounterId) { return [latestObs]; } // Fetch ALL obs for that concept within the same encounter const params = `patient=${patientUuid}&code=${conceptUuid}&encounter=${encounterId}`; const { data } = await openmrsFetch(`${fhirBaseUrl}/Observation?${params}`); return data.entry?.map((e) => e.resource) ?? []; } /** * Fetches an OpenMRS form using either its name or UUID. * @param {string} nameOrUUID - The form's name or UUID. * @returns {Promise} - A Promise that resolves to the fetched OpenMRS form or null if not found. */ export async function fetchOpenMRSForm(nameOrUUID: string): Promise { if (!nameOrUUID) { return null; } const { url, isUUID } = isUuid(nameOrUUID) ? { url: `${restBaseUrl}/form/${nameOrUUID}?v=full`, isUUID: true } : { url: `${restBaseUrl}/form?q=${nameOrUUID}&v=full`, isUUID: false }; const { data: openmrsFormResponse } = await openmrsFetch(url); if (isUUID) { return openmrsFormResponse; } if (openmrsFormResponse.results?.length) { const form = openmrsFormResponse.results.find((form) => form.retired === false); if (form) { return form; } } throw new Error(`Form with ID "${nameOrUUID}" was not found`); } /** * Fetches ClobData for a given OpenMRS form. * @param {OpenmrsForm} form - The OpenMRS form object. * @returns {Promise} - A Promise that resolves to the fetched ClobData or null if not found. */ export async function fetchClobData(form: OpenmrsForm): Promise { if (!form) { return null; } const jsonSchemaResource = form.resources?.find(({ name }) => name === 'JSON schema'); if (!jsonSchemaResource) { return null; } const clobDataUrl = `${restBaseUrl}/clobdata/${jsonSchemaResource.valueReference}`; const { data: clobDataResponse } = await openmrsFetch(clobDataUrl); return clobDataResponse; } // Program Enrollment export function getPatientEnrolledPrograms(patientUuid: string) { return openmrsFetch( `${restBaseUrl}/programenrollment?patient=${patientUuid}&v=custom:(uuid,display,program:(uuid,name,allWorkflows),dateEnrolled,dateCompleted,location:(uuid,display),states:(state:(uuid,name,concept:(uuid),programWorkflow:(uuid)))`, ).then(({ data }) => { if (data) { return data; } return null; }); } export function saveProgramEnrollment(payload: PatientProgramPayload, abortController: AbortController) { if (!payload) { throw new Error('Program enrollment cannot be created because no payload is supplied'); } const url = payload.uuid ? `${restBaseUrl}/programenrollment/${payload.uuid}` : `${restBaseUrl}/programenrollment`; return openmrsFetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: payload, signal: abortController.signal, }); } export function savePatientIdentifier(patientIdentifier: PatientIdentifier, patientUuid: string) { let url: string; if (patientIdentifier.uuid) { url = `${restBaseUrl}/patient/${patientUuid}/identifier/${patientIdentifier.uuid}`; } else { url = `${restBaseUrl}/patient/${patientUuid}/identifier`; } return openmrsFetch(url, { headers: { 'Content-Type': 'application/json', }, method: 'POST', body: JSON.stringify(patientIdentifier), }); } export function savePersonAttribute(personAttribute: PersonAttribute, patientUuid: string) { let url: string; if (personAttribute.uuid) { url = `${restBaseUrl}/person/${patientUuid}/attribute/${personAttribute.uuid}`; } else { url = `${restBaseUrl}/person/${patientUuid}/attribute`; } return openmrsFetch(url, { headers: { 'Content-Type': 'application/json', }, method: 'POST', body: personAttribute, }); } export function markPatientAsDeceased( t: TFunction, patientUUID: string, payload: PatientDeathPayload, abortController: AbortController, ) { if (!payload) { throw new Error( t( 'patientCannotBeMarkedAsDeceasedBecauseNoPayloadSupplied', 'Patient cannot be marked as deceased because no payload is supplied', ), ); } const url = `${restBaseUrl}/person/${patientUUID}`; return openmrsFetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: payload, signal: abortController.signal, }); }